2 std_macros.c - MaLa standard module macros
4 Copyright (C) 2005, 2006, Christian Thaeter <ct@pipapo.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
25 #include "std_macros.h"
28 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10]);
31 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10]);
34 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
);
37 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
);
42 mala_actioninit std_macros
[] =
45 //MALA_PARSER_BRIEF("MACROS", "TODO"),
46 //MALA_PARSER_HELP("MACROS", ("TODO")),
49 MALA_PARSER("--", mala__parser, NULL, NULL, NULL),
50 MALA_PARSER_BRIEF("--", ""),
51 MALA_PARSER_HELP("--", ("TODO")),
52 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
53 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
54 MALA_PARSER_RESULT_TYPE("--", ("")),
55 MALA_PARSER_RESULT_USAGE("--", ("")),
57 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
58 MALA_PARSER_BRIEF("--", ""),
59 MALA_PARSER_HELP("--", ("TODO")),
60 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
61 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
62 MALA_PARSER_RESULT_TYPE("--", ("")),
63 MALA_PARSER_RESULT_USAGE("--", ("")),
68 //MALA_SIMPLE_PARSER("--DEF", mala_def_parser),
69 //MALA_PARSER_BRIEF("--DEF", "defines a substitution"),
70 //MALA_PARSER_SIGNATURE_TYPE("--DEF", ("WORD", "WORD-OR-BLOCK")),
71 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEF", ("word to be substituted",
72 // "replaced with this")),
73 //TODO MALA_PARSER_HELP("--DEF", ("The second argument can be a block of words enclosed in --BEGIN ... --END with % substitution sequences. See help for --BEGIN for details.")),
74 //TODO MALA_PARSER_EXAMPLE("--DEF", "--DEF `foo `bar\t expands foo to bar\n--DEF `--action --BEGIN foo bar --END\t --action will expand to foo bar"),
77 //MALA_PARSER("--END", mala_end_parser, NULL, NULL, NULL),
78 // TODO MALA_PARSER_BRIEF("--END", "closes a block"),
79 //TODOMALA_PARSER_HELP("--END", ("an --END without a matching --BEGIN raises an error.")),
82 MALA_PARSER_SIMPLE("--DEL", mala_delete_parser
),
84 //MALA_PARSER_BRIEF("--DEL", "deletes a macro"),
85 //TODO MALA_PARSER_SIGNATURE_TYPE("--DEL", ("WORD")),
86 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEL", ("name of the Macro to delete")),
87 //TODO MALA_PARSER_HELP("--DEL", ("Removes the last definition of the most recent definition with the matching name and any childs which where attached to it (see --ATTACH)")),
89 MALA_PARSER_SIMPLE("--BEGIN", mala_begin_parser
),
90 // MALA_PARSER_BRIEF("--BEGIN", "defines a block or list"),
91 //TODO MALA_PARSER_SIGNATURE_TYPE("--BEGIN", ("SEQUENCE","END")),
92 //TODO MALA_PARSER_SIGNATURE_USAGE("--BEGIN", ("content of the block", "a --END which closes the block")),
93 //TODO MALA_PARSER_RESULT_TYPE("--BEGIN", ("BLOCK")),
94 //TODO MALA_PARSER_RESULT_USAGE("--BEGIN", ("a unique name of the block")),
95 //TODO MALA_PARSER_HELP("--BEGIN", ("Blocks can have % substitutions, Blocks are garbage collected, TODO")),
103 mala_substitute_parser (MalaProgram prg
)
107 TODO("treat data_alloc_type");
109 mala_stringlist_next (prg
->pptr
)->string
= (MalaString
) mala_program_pptr_action (prg
)->string
;
113 return MALA_CONTINUE
;
117 mala_expand_parser (MalaProgram prg
)
121 MalaAction act
= mala_program_pptr_action (prg
);
122 MalaStringList pos
= mala_stringlist_next (prg
->pptr
);
125 for (itr
= mala_stringlist_tail_get ((MalaStringList
) act
->data
);
126 !mala_stringlist_is_end ((MalaStringList
) act
->data
, itr
);
127 mala_stringlist_rev (&itr
))
129 MalaStringList node
= mala_stringlist_node_new (mala_stringlist_string (itr
), prg
->engine
);
130 mala_stringlist_insert_after (pos
, node
);
135 mala_program_action_done (prg
, 0);
136 return MALA_CONTINUE
;
141 mala_macro_parser (MalaProgram prg
)
143 NOTICE (mala_module_std_macros
, "macro parser");
146 /* How much to eveluate the argument (for now, likely extended in future):
147 MALA_REMOVE is used as pseudo tag for unused arguments/initialization
148 MALA_START doesn't evaluate the argument
149 MALA_LITERAL will evaluate fully
150 .. other destination states are reserved for future
152 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
153 MalaAction act
= mala_program_pptr_action (prg
);
155 // scan for arguments
156 AcogcFactory type
= mala_action_data_type (act
);
157 if (type
== &prg
->engine
->gcfactory_strings
)
159 mala_string_macrocheck (mala_action_string (act
), &max_arg
, argt
);
161 else if (type
== &prg
->engine
->gcfactory_stringlists
)
163 mala_stringlist_macrocheck (mala_action_stringlist (act
), &max_arg
, argt
);
168 BUG ("if (max_arg == INT_MAX) syntax error");
171 return mala_expand_parser (prg
);
175 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
177 for (int i
=1; i
<= max_arg
; ++i
)
179 if (argt
[i
] < MALA_START
)
181 mala_program_eval_arg (prg
, i
, argt
[i
]);
182 TODO (" return / error handlen");
186 // construct result list
188 MalaStringList p
= mala_stringlist_next (prg
->pptr
);
189 for (int i
=1; i
<= max_arg
; ++i
)
191 mala_stringlist_fwd (&p
);
192 args
[i
] = mala_stringlist_string (p
);
196 if (type
== &prg
->engine
->gcfactory_strings
)
198 ACOGC_STACK_PTR (MalaString
, string
);
199 string
.ptr
= mala_string_new_macrosubst (mala_action_string (act
),
202 MalaStringList n
= mala_stringlist_node_new (string
.ptr
, prg
->engine
);
203 mala_stringlist_insert_after (p
, n
);
205 else if (type
== &prg
->engine
->gcfactory_stringlists
)
207 ACOGC_STACK_PTR (MalaStringList
, list
);
208 list
.ptr
= mala_stringlist_new_macrosubst (mala_action_stringlist (act
),
210 mala_stringlist_insert_after_stringlist (p
, list
.ptr
);
219 mala_program_action_done (prg
, max_arg
);
220 return MALA_CONTINUE
;
224 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10])
226 LLIST_FOREACH (&list
->node
, itr
)
228 MalaStringList l
= LLIST_TO_STRUCTP(itr
, mala_stringlist
, node
);
229 mala_string_macrocheck (mala_stringlist_string (l
), max_arg
, argt
);
230 if (*max_arg
== INT_MAX
)
236 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10])
239 for (c
= mala_string_cstr (string
); *c
; ++c
)
249 if (*c
>= '0' && *c
<= '9')
251 if (argt
[*c
- '0'] < MALA_REMOVE
&& argt
[*c
- '0'] != MALA_START
)
253 if (*c
> (char) *max_arg
+ '0')
255 argt
[*c
- '0'] = MALA_START
;
260 else if (*c
>= '0' && *c
<= '9')
262 if (argt
[*c
- '0'] != MALA_REMOVE
&& argt
[*c
- '0'] != MALA_LITERAL
)
264 if (*c
> (char) *max_arg
+ '0')
266 argt
[*c
- '0'] = MALA_LITERAL
;
281 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
)
284 size_t size
= mala_string_length (src
);
285 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
299 TODO ("Handle %%-0");
300 size
+= mala_string_length (args
[*c
- '0']);
304 // 2nd pass create string
306 acogc_alloc (&cstr
, size
+1, &eng
->gcroot
);
310 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
323 TODO ("Handle %%-0");
325 strcpy (p
, mala_string_cstr (args
[*c
- '0']));
326 p
+= mala_string_length (args
[*c
- '0']);
333 return mala_string_new_attach_cstr (cstr
, eng
->words
);
336 static MalaStringList
337 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
)
339 ACOGC_STACK_ENTER (&eng
->gcroot
);
340 ACOGC_STACK_PTR (MalaStringList
, ret
);
342 ret
.ptr
= mala_stringlist_new (eng
);
344 LLIST_FOREACH (&src
->node
, node
)
346 ACOGC_STACK_PTR (MalaString
, str
);
347 str
.ptr
= mala_string_new_macrosubst (mala_stringlist_string_from_llist(node
), args
, eng
);
348 MalaStringList n
= mala_stringlist_node_new (str
.ptr
, eng
);
349 mala_stringlist_insert_tail (ret
.ptr
, n
);
359 mala_begin_parser (MalaProgram prg
)
362 #if 0 // TODO --PROGRAM
365 //MalaStringList list;
367 MalaString name
= NULL
;
371 //TODO --PROGRAM if (mala_stringlist_is_tail (&eng->program, mala_program_pos (prg)))
372 // return mala_engine_exception (eng, pptr, mala_program_pos (prg),
373 // eng->common_string[MALA_STRING_ERROR_MISSING_END]);
375 // find matching --END
376 for (end
= mala_stringlist_next (mala_program_pos (prg
));
377 !mala_stringlist_is_end (&eng
->program
, end
);
378 mala_stringlist_fwd (&end
))
380 //TODO if (mala_string_same(mala_stringlist_string (end),
381 // eng->common_string[MALA_STRING_BEGIN]))
383 //else if (mala_string_same(mala_stringlist_string (end),
384 // eng->common_string[MALA_STRING_END]))
391 return mala_engine_exception (eng
, pptr
, mala_stringlist_prev (end
),
392 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
396 //list = mala_stringlist_new ();
398 // return MALA_EALLOC;
400 // copy the block content to list
401 for (itr
= mala_stringlist_next (mala_program_pos (prg
)); itr
!= end
; mala_stringlist_fwd (&itr
))
402 if (!mala_stringlist_tail_new (list
, mala_stringlist_string (itr
)))
406 MalaParserFunc parser
;
409 mala_macrocheck_list (list
, &max_arg
, argt
);
414 parser
= mala_expand_parser
;
417 else if (max_arg
> 0)
420 parser
= mala_macro_parser
;
425 mala_stringlist_free (list
);
426 //TODO review mala_string_free (name);
427 return mala_engine_exception (eng
, pptr
, end
,
428 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
431 // allocate new block name
432 do { /* ..while name is in use */
433 //mala_string_free (name); /*TODO review in case we need to loop*/
434 name
= mala_string_new_print (&eng
->words
, NULL
/*TODO refs*/, templ
, ++eng
->blockcnt
);
437 } while (0); // TODO (mala_actiondesc_top ((MalaActionDesc)mala_string_user_get (name)));
439 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
441 NULL
, NULL
/*TODO refs*/))
443 // insert new --X_nnn... in program
444 //if (!mala_stringlist_after_new (&eng->program, end, name))
446 // TODO review mala_string_free (name);
447 // TODO review mala_string_free (name); // once more since blocks are self-deleting after used
451 //TODO --PROGRAM if (!mala_stringlist_after_new (&eng->program,
453 // eng->common_string[MALA_STRING_PASS]))
458 // and remove definition
459 //TODO --PROGRAM while (mala_program_pos (prg) != end)
460 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
462 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
470 #if 0 //old block_parser
472 mala_block_parser (MalaProgram prg
,
480 end
= mala_stringlist_next (mala_program_pos (prg
));
482 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
483 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
484 mala_stringlist_rev (&itr
))
486 #if 0 // TODO --PROGRAM
487 if (!mala_stringlist_after_new (&eng
->program
, mala_program_pos (prg
),
488 mala_stringlist_string (itr
)))
495 mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_program_pos (prg
)));
496 mala_engine_command_done (eng
, pptr
, 0);
497 return MALA_CONTINUE
;
500 /* remove already added things */
502 for (itr
= mala_stringlist_next (mala_program_pos (prg
));
504 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
510 #if 0 // old macrodelete_parser
512 mala_macrodelete_parser (MalaProgram prg
, void * data
)
516 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
);
520 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
521 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
522 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
524 mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg
))));
528 mala_engine_command_done (eng
, pptr
, 1);
531 #endif // old macrodelete
534 mala_delete_parser (MalaProgram prg
)
536 //mala_engine_arg_eval (eng, pptr, 1, MALA_LITERAL);
540 #if 0 // TODO --PROGRAM
541 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
542 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
543 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
545 // TODO mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg))));
549 // mala_program_action_done (prg, 1);
556 mala_end_parser (MalaProgram prg
,
561 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
562 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
568 #if 0 // old macrodef parser
570 mala_macrodef_parser (MalaProgram prg
,
575 MalaStringList arg
[2];
581 // evaluate both args
582 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
))
584 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
, mala_block_parser
))
589 // test if 2 arguments left and assign them to arg[], else error
590 for (i
= 0, itr
= mala_program_pos (prg
); i
<2; ++i
, mala_stringlist_fwd(&itr
))
592 #if 0 // TODO --PROGRAM
593 if (mala_stringlist_is_tail (&eng
->program
, itr
))
594 return mala_engine_exception (eng
, pptr
, itr
,
595 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
598 arg
[i
] = mala_stringlist_next (itr
);
601 // if name is a block then error
602 name
= mala_stringlist_string (arg
[0]);
603 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
604 if (act
&& act
->parser
== mala_block_parser
)
605 return mala_engine_exception (eng
, pptr
, arg
[0],
606 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
608 //expansion check and optimize block
609 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
610 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
614 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
615 // convert block to expansion
620 desc
= mala_actiondesc_ensure (name
);
624 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
626 act
->parser
= mala_macro_parser
;
627 mala_actiondesc_push_action (desc
, act
);
629 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
633 subst
= mala_stringlist_head_string_copy ((MalaStringList
) act
->data
);
635 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
636 mala_substitute_parser
,
637 (MalaDataFactory
) mala_string_factory
,
641 mala_action_free(act
);
643 else if (max_arg
== 0)
647 desc
= mala_actiondesc_ensure (name
);
651 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
653 act
->parser
= mala_expand_parser
;
654 mala_actiondesc_push_action (desc
, act
);
657 return mala_engine_exception (eng
, pptr
, arg
[1],
658 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
660 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
665 mala_macrocheck_string (mala_stringlist_string (arg
[1]), &max_arg
, argt
);
669 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
670 mala_stringlist_string_copy (arg
[1]),
671 mala_substitute_parser
,
672 (MalaDataFactory
) mala_string_factory
,
676 else if (max_arg
> 0)
681 list
= mala_stringlist_new ();
685 mala_stringlist_tail_new (list
, mala_stringlist_string (arg
[1]));
687 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
689 (MalaDataFactory
) mala_stringlist_factory
,
694 return mala_engine_exception (eng
, pptr
, arg
[1],
695 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
700 mala_engine_command_done (eng
, pptr
, 2);
703 #endif //old macordef_parser
707 mala_def_parser (MalaProgram prg
,
711 MalaStringList subst
;
717 // evaluate both args
718 dest
= mala_engine_arg_eval (eng
, pptr
, 1, MALA_LITERAL
);
722 subst
= mala_engine_arg_eval (eng
, pptr
, 2, MALA_MACRO
);
728 info bei HELP/RESULT_TYPE ob was ein PREDICATE, EXPANSION, LITERAL oder BLOCK ist
736 mala_macrocheck_string (mala_stringlist_string (subst
), &max_arg
, argt
);
740 str
= NULL
; // TODO mala_stringlist_string_copy (subst);
742 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
743 mala_stringlist_string (dest
),
745 mala_substitute_parser
,
746 NULL
, //TODO (MalaDataFactory) mala_string_factory,
752 else if (max_arg
> 0)
755 list
= mala_stringlist_new ();
759 if (! mala_stringlist_tail_new (list
, mala_stringlist_string (subst
)))
763 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
764 mala_stringlist_string (dest
),
767 NULL
, NULL
/*TODO refs*/))
768 goto ealloc_list_action
;
772 return mala_engine_exception (eng
, pptr
, subst
,
773 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
777 mala_engine_command_done (eng
, pptr
, 2);
778 return MALA_CONTINUE
;
780 // ealloc_list_action:
782 mala_stringlist_free (list
);
786 // TODO review mala_string_free (str);
793 realloc a string to at least needed size
794 return the amount really reserved or 0 on error
796 #if 0 // TODO acogc reserve!
798 reserve_string (char ** s
, size_t actual
, size_t needed
)
803 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
808 /* that was to much, try conservatively */
809 r
= realloc (*s
, n
= needed
);
818 NOBUG_DEFINE_FLAG (mala_module_std_macros
);
821 mala_module_std_macros_init (MalaEngine self
)
823 NOBUG_INIT_FLAG (mala_module_std_macros
);
824 return mala_engine_actions_register (self
, std_macros
);
830 // c-file-style: "gnu"
832 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5