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
[] =
44 MALA_PARSER_SIMPLE("--DEL", mala_delete_parser
),
45 MALA_PARSER_SIMPLE("--BEGIN", mala_begin_parser
),
47 //MALA_PARSER_BRIEF("MACROS", "TODO"),
48 //MALA_PARSER_HELP("MACROS", ("TODO")),
51 MALA_PARSER("--", mala__parser, NULL, NULL, NULL),
52 MALA_PARSER_BRIEF("--", ""),
53 MALA_PARSER_HELP("--", ("TODO")),
54 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
55 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
56 MALA_PARSER_RESULT_TYPE("--", ("")),
57 MALA_PARSER_RESULT_USAGE("--", ("")),
59 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
60 MALA_PARSER_BRIEF("--", ""),
61 MALA_PARSER_HELP("--", ("TODO")),
62 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
63 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
64 MALA_PARSER_RESULT_TYPE("--", ("")),
65 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_BRIEF("--DEL", "deletes a macro"),
83 //TODO MALA_PARSER_SIGNATURE_TYPE("--DEL", ("WORD")),
84 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEL", ("name of the Macro to delete")),
85 //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)")),
87 // MALA_PARSER_BRIEF("--BEGIN", "defines a block or list"),
88 //TODO MALA_PARSER_SIGNATURE_TYPE("--BEGIN", ("SEQUENCE","END")),
89 //TODO MALA_PARSER_SIGNATURE_USAGE("--BEGIN", ("content of the block", "a --END which closes the block")),
90 //TODO MALA_PARSER_RESULT_TYPE("--BEGIN", ("BLOCK")),
91 //TODO MALA_PARSER_RESULT_USAGE("--BEGIN", ("a unique name of the block")),
92 //TODO MALA_PARSER_HELP("--BEGIN", ("Blocks can have % substitutions, Blocks are garbage collected, TODO")),
100 mala_substitute_parser (MalaProgram prg
)
104 REQUIRE (acogc_object_type (mala_program_pptr_action (prg
)->data
)
105 == &prg
->engine
->gcfactory_strings
);
107 mala_stringlist_next (prg
->pptr
)->string
= mala_action_string (mala_program_pptr_action (prg
));
111 return MALA_CONTINUE
;
115 mala_expand_parser (MalaProgram prg
)
119 MalaAction act
= mala_program_pptr_action (prg
);
120 REQUIRE (acogc_object_type (mala_action_dataptr (act
))
121 == &prg
->engine
->gcfactory_stringlists
);
123 MalaStringList pos
= mala_stringlist_next (prg
->pptr
);
126 for (itr
= mala_stringlist_tail_get (mala_action_stringlist (act
));
127 !mala_stringlist_is_end (mala_action_stringlist (act
), itr
);
128 mala_stringlist_rev (&itr
))
130 MalaStringList node
= mala_stringlist_node_new (mala_stringlist_string (itr
), prg
->engine
);
131 mala_stringlist_insert_after (pos
, node
);
136 mala_program_action_done (prg
, 0);
137 return MALA_CONTINUE
;
142 mala_macro_parser (MalaProgram prg
)
144 NOTICE (mala_module_std_macros
, "macro parser");
147 /* How much to eveluate the argument (for now, likely extended in future):
148 MALA_REMOVE is used as pseudo tag for unused arguments/initialization
149 MALA_START doesn't evaluate the argument
150 MALA_LITERAL will evaluate fully
151 .. other destination states are reserved for future
153 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
154 MalaAction act
= mala_program_pptr_action (prg
);
156 // scan for arguments
157 AcogcFactory type
= mala_action_data_type (act
);
158 if (type
== &prg
->engine
->gcfactory_strings
)
160 mala_string_macrocheck (mala_action_string (act
), &max_arg
, argt
);
162 else if (type
== &prg
->engine
->gcfactory_stringlists
)
164 mala_stringlist_macrocheck (mala_action_stringlist (act
), &max_arg
, argt
);
169 if (max_arg
== INT_MAX
)
170 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
173 return mala_expand_parser (prg
);
178 for (int i
=1; i
<= max_arg
; ++i
)
180 if (argt
[i
] < MALA_START
)
182 if (mala_program_eval_arg (prg
, i
, argt
[i
]) > MALA_EFAULT
)
183 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
187 // construct result list
189 MalaStringList p
= mala_stringlist_next (prg
->pptr
);
190 for (int i
=1; i
<= max_arg
; ++i
)
192 mala_stringlist_fwd (&p
);
193 args
[i
] = mala_stringlist_string (p
);
196 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
198 if (type
== &prg
->engine
->gcfactory_strings
)
200 ACOGC_STACK_PTR (MalaString
, string
);
201 string
.ptr
= mala_string_new_macrosubst (mala_action_string (act
),
204 MalaStringList n
= mala_stringlist_node_new (string
.ptr
, prg
->engine
);
205 mala_stringlist_insert_after (p
, n
);
207 else if (type
== &prg
->engine
->gcfactory_stringlists
)
209 ACOGC_STACK_PTR (MalaStringList
, list
);
210 list
.ptr
= mala_stringlist_new_macrosubst (mala_action_stringlist (act
),
212 mala_stringlist_insert_after_stringlist (p
, list
.ptr
);
221 mala_program_action_done (prg
, max_arg
);
222 return MALA_CONTINUE
;
226 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10])
228 LLIST_FOREACH (&list
->node
, itr
)
230 MalaStringList l
= LLIST_TO_STRUCTP(itr
, mala_stringlist
, node
);
231 mala_string_macrocheck (mala_stringlist_string (l
), max_arg
, argt
);
232 if (*max_arg
== INT_MAX
)
238 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10])
241 for (c
= mala_string_cstr (string
); *c
; ++c
)
251 if (*c
>= '0' && *c
<= '9')
253 if (argt
[*c
- '0'] < MALA_REMOVE
&& argt
[*c
- '0'] != MALA_START
)
255 if (*c
> (char) *max_arg
+ '0')
257 argt
[*c
- '0'] = MALA_START
;
262 else if (*c
>= '0' && *c
<= '9')
264 if (argt
[*c
- '0'] != MALA_REMOVE
&& argt
[*c
- '0'] != MALA_LITERAL
)
266 if (*c
> (char) *max_arg
+ '0')
268 argt
[*c
- '0'] = MALA_LITERAL
;
283 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
)
286 size_t size
= mala_string_length (src
);
287 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
301 TODO ("Handle %%-0");
302 size
+= mala_string_length (args
[*c
- '0']);
306 // 2nd pass create string
308 acogc_alloc (&cstr
, size
+1, &eng
->gcroot
);
312 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
325 TODO ("Handle %%-0");
327 strcpy (p
, mala_string_cstr (args
[*c
- '0']));
328 p
+= mala_string_length (args
[*c
- '0']);
335 return mala_string_new_attach_cstr (cstr
, eng
->words
);
338 static MalaStringList
339 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
)
341 ACOGC_STACK_ENTER (&eng
->gcroot
);
342 ACOGC_STACK_PTR (MalaStringList
, ret
);
344 ret
.ptr
= mala_stringlist_new (eng
);
346 LLIST_FOREACH (&src
->node
, node
)
348 ACOGC_STACK_PTR (MalaString
, str
);
349 str
.ptr
= mala_string_new_macrosubst (mala_stringlist_string_from_llist(node
), args
, eng
);
350 MalaStringList n
= mala_stringlist_node_new (str
.ptr
, eng
);
351 mala_stringlist_insert_tail (ret
.ptr
, n
);
361 mala_begin_parser (MalaProgram prg
)
364 #if 0 // TODO --PROGRAM
367 //MalaStringList list;
369 MalaString name
= NULL
;
373 //TODO --PROGRAM if (mala_stringlist_is_tail (&eng->program, mala_program_pos (prg)))
374 // return mala_engine_exception (eng, pptr, mala_program_pos (prg),
375 // eng->common_string[MALA_STRING_ERROR_MISSING_END]);
377 // find matching --END
378 for (end
= mala_stringlist_next (mala_program_pos (prg
));
379 !mala_stringlist_is_end (&eng
->program
, end
);
380 mala_stringlist_fwd (&end
))
382 //TODO if (mala_string_same(mala_stringlist_string (end),
383 // eng->common_string[MALA_STRING_BEGIN]))
385 //else if (mala_string_same(mala_stringlist_string (end),
386 // eng->common_string[MALA_STRING_END]))
393 return mala_engine_exception (eng
, pptr
, mala_stringlist_prev (end
),
394 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
398 //list = mala_stringlist_new ();
400 // return MALA_EALLOC;
402 // copy the block content to list
403 for (itr
= mala_stringlist_next (mala_program_pos (prg
)); itr
!= end
; mala_stringlist_fwd (&itr
))
404 if (!mala_stringlist_tail_new (list
, mala_stringlist_string (itr
)))
408 MalaParserFunc parser
;
411 mala_macrocheck_list (list
, &max_arg
, argt
);
416 parser
= mala_expand_parser
;
419 else if (max_arg
> 0)
422 parser
= mala_macro_parser
;
427 mala_stringlist_free (list
);
428 //TODO review mala_string_free (name);
429 return mala_engine_exception (eng
, pptr
, end
,
430 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
433 // allocate new block name
434 do { /* ..while name is in use */
435 //mala_string_free (name); /*TODO review in case we need to loop*/
436 name
= mala_string_new_print (&eng
->words
, NULL
/*TODO refs*/, templ
, ++eng
->blockcnt
);
439 } while (0); // TODO (mala_actiondesc_top ((MalaActionDesc)mala_string_user_get (name)));
441 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
443 NULL
, NULL
/*TODO refs*/))
445 // insert new --X_nnn... in program
446 //if (!mala_stringlist_after_new (&eng->program, end, name))
448 // TODO review mala_string_free (name);
449 // TODO review mala_string_free (name); // once more since blocks are self-deleting after used
453 //TODO --PROGRAM if (!mala_stringlist_after_new (&eng->program,
455 // eng->common_string[MALA_STRING_PASS]))
460 // and remove definition
461 //TODO --PROGRAM while (mala_program_pos (prg) != end)
462 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
464 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
472 #if 0 //old block_parser
474 mala_block_parser (MalaProgram prg
,
482 end
= mala_stringlist_next (mala_program_pos (prg
));
484 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
485 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
486 mala_stringlist_rev (&itr
))
488 #if 0 // TODO --PROGRAM
489 if (!mala_stringlist_after_new (&eng
->program
, mala_program_pos (prg
),
490 mala_stringlist_string (itr
)))
497 mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_program_pos (prg
)));
498 mala_engine_command_done (eng
, pptr
, 0);
499 return MALA_CONTINUE
;
502 /* remove already added things */
504 for (itr
= mala_stringlist_next (mala_program_pos (prg
));
506 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
512 #if 0 // old macrodelete_parser
514 mala_macrodelete_parser (MalaProgram prg
, void * data
)
518 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
);
522 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
523 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
524 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
526 mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg
))));
530 mala_engine_command_done (eng
, pptr
, 1);
533 #endif // old macrodelete
536 mala_delete_parser (MalaProgram prg
)
538 //mala_engine_arg_eval (eng, pptr, 1, MALA_LITERAL);
542 #if 0 // TODO --PROGRAM
543 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
544 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
545 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
547 // TODO mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg))));
551 // mala_program_action_done (prg, 1);
558 mala_end_parser (MalaProgram prg
,
563 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
564 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
570 #if 0 // old macrodef parser
572 mala_macrodef_parser (MalaProgram prg
,
577 MalaStringList arg
[2];
583 // evaluate both args
584 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
))
586 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
, mala_block_parser
))
591 // test if 2 arguments left and assign them to arg[], else error
592 for (i
= 0, itr
= mala_program_pos (prg
); i
<2; ++i
, mala_stringlist_fwd(&itr
))
594 #if 0 // TODO --PROGRAM
595 if (mala_stringlist_is_tail (&eng
->program
, itr
))
596 return mala_engine_exception (eng
, pptr
, itr
,
597 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
600 arg
[i
] = mala_stringlist_next (itr
);
603 // if name is a block then error
604 name
= mala_stringlist_string (arg
[0]);
605 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
606 if (act
&& act
->parser
== mala_block_parser
)
607 return mala_engine_exception (eng
, pptr
, arg
[0],
608 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
610 //expansion check and optimize block
611 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
612 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
616 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
617 // convert block to expansion
622 desc
= mala_actiondesc_ensure (name
);
626 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
628 act
->parser
= mala_macro_parser
;
629 mala_actiondesc_push_action (desc
, act
);
631 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
635 subst
= mala_stringlist_head_string_copy ((MalaStringList
) act
->data
);
637 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
638 mala_substitute_parser
,
639 (MalaDataFactory
) mala_string_factory
,
643 mala_action_free(act
);
645 else if (max_arg
== 0)
649 desc
= mala_actiondesc_ensure (name
);
653 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlist_user_get (arg
[1]));
655 act
->parser
= mala_expand_parser
;
656 mala_actiondesc_push_action (desc
, act
);
659 return mala_engine_exception (eng
, pptr
, arg
[1],
660 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
662 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
667 mala_macrocheck_string (mala_stringlist_string (arg
[1]), &max_arg
, argt
);
671 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
672 mala_stringlist_string_copy (arg
[1]),
673 mala_substitute_parser
,
674 (MalaDataFactory
) mala_string_factory
,
678 else if (max_arg
> 0)
683 list
= mala_stringlist_new ();
687 mala_stringlist_tail_new (list
, mala_stringlist_string (arg
[1]));
689 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
691 (MalaDataFactory
) mala_stringlist_factory
,
696 return mala_engine_exception (eng
, pptr
, arg
[1],
697 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
702 mala_engine_command_done (eng
, pptr
, 2);
705 #endif //old macordef_parser
709 mala_def_parser (MalaProgram prg
,
713 MalaStringList subst
;
719 // evaluate both args
720 dest
= mala_engine_arg_eval (eng
, pptr
, 1, MALA_LITERAL
);
724 subst
= mala_engine_arg_eval (eng
, pptr
, 2, MALA_MACRO
);
730 info bei HELP/RESULT_TYPE ob was ein PREDICATE, EXPANSION, LITERAL oder BLOCK ist
738 mala_macrocheck_string (mala_stringlist_string (subst
), &max_arg
, argt
);
742 str
= NULL
; // TODO mala_stringlist_string_copy (subst);
744 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
745 mala_stringlist_string (dest
),
747 mala_substitute_parser
,
748 NULL
, //TODO (MalaDataFactory) mala_string_factory,
754 else if (max_arg
> 0)
757 list
= mala_stringlist_new ();
761 if (! mala_stringlist_tail_new (list
, mala_stringlist_string (subst
)))
765 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
766 mala_stringlist_string (dest
),
769 NULL
, NULL
/*TODO refs*/))
770 goto ealloc_list_action
;
774 return mala_engine_exception (eng
, pptr
, subst
,
775 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
779 mala_engine_command_done (eng
, pptr
, 2);
780 return MALA_CONTINUE
;
782 // ealloc_list_action:
784 mala_stringlist_free (list
);
788 // TODO review mala_string_free (str);
795 realloc a string to at least needed size
796 return the amount really reserved or 0 on error
798 #if 0 // TODO acogc reserve!
800 reserve_string (char ** s
, size_t actual
, size_t needed
)
805 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
810 /* that was to much, try conservatively */
811 r
= realloc (*s
, n
= needed
);
820 NOBUG_DEFINE_FLAG (mala_module_std_macros
);
823 mala_module_std_macros_init (MalaEngine self
)
825 NOBUG_INIT_FLAG (mala_module_std_macros
);
826 return mala_engine_actions_register (self
, std_macros
);
832 // c-file-style: "gnu"
834 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5