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_SIMPLE("--END", mala_end_parser
),
48 // TODO MALA_PARSER_BRIEF("--END", "closes a block"),
49 //TODOMALA_PARSER_HELP("--END", ("an --END without a matching --BEGIN raises an error.")),
51 MALA_PARSER_SIMPLE("--DEF", mala_def_parser
),
52 //MALA_PARSER_BRIEF("--DEF", "defines a substitution"),
53 //MALA_PARSER_SIGNATURE_TYPE("--DEF", ("WORD", "WORD-OR-BLOCK")),
54 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEF", ("word to be substituted",
55 // "replaced with this")),
56 //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.")),
57 //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"),
58 //MALA_PARSER_BRIEF("MACROS", "TODO"),
59 //MALA_PARSER_HELP("MACROS", ("TODO")),
62 MALA_PARSER("--", mala__parser, NULL, NULL, NULL),
63 MALA_PARSER_BRIEF("--", ""),
64 MALA_PARSER_HELP("--", ("TODO")),
65 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
66 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
67 MALA_PARSER_RESULT_TYPE("--", ("")),
68 MALA_PARSER_RESULT_USAGE("--", ("")),
70 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
71 MALA_PARSER_BRIEF("--", ""),
72 MALA_PARSER_HELP("--", ("TODO")),
73 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
74 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
75 MALA_PARSER_RESULT_TYPE("--", ("")),
76 MALA_PARSER_RESULT_USAGE("--", ("")),
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")),
99 mala_begin_parser (MalaProgram prg
)
104 // find matching --END
105 MalaStringList begin
= mala_stringlist_next (prg
->pptr
);
107 !mala_stringlist_is_end (prg
->program
, end
);
108 mala_stringlist_fwd (&end
))
110 if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_BEGIN
])
112 else if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_END
])
120 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MISSING_END
);
122 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
123 ACOGC_STACK_PTR (MalaStringList
, list
);
124 ACOGC_STACK_PTR (MalaString
, name
);
126 list
.ptr
= mala_stringlist_new (prg
->engine
);
129 // move elements into destionation list
130 while (mala_stringlist_next (begin
) != end
)
132 mala_stringlist_insert_tail (list
.ptr
, mala_stringlist_next (begin
));
136 MalaParserFunc parser
;
138 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
146 // --BEGIN --END becomes --PASS
147 TODO ("direct --PASS substitute");
148 parser
= mala_pass_parser
;
149 templ
= "--BLOCK_%08X";
152 else if (length
== 1)
154 data
= mala_stringlist_string (mala_stringlist_head_get (list
.ptr
));
155 mala_string_macrocheck ((MalaString
) data
, &max_arg
, argt
);
156 if (max_arg
== INT_MAX
)
158 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
160 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
165 // --BEGIN FOO --END becomes FOO
166 TODO ("direct name substitute");
167 parser
= mala_substitute_parser
;
168 templ
= "--BLOCK_%08X";
173 parser
= mala_macro_parser
;
174 templ
= "--BLOCK_%08X";
181 mala_stringlist_macrocheck (list
.ptr
, &max_arg
, argt
);
182 if (max_arg
== INT_MAX
)
184 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
186 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
191 parser
= mala_expand_parser
;
192 templ
= "--BLOCK_%08X";
197 parser
= mala_macro_parser
;
198 templ
= "--BLOCK_%08X";
205 // insert new --nnn... in program
206 name
.ptr
= mala_engine_tmpname (prg
->engine
, templ
);
207 TRACE (mala_module_std_macros
, "Block %s", mala_string_cstr (name
.ptr
) );
208 mala_action_new (name
.ptr
, parser
, data
, data
?ACOGC_GC
:ACOGC_UNSET
, prg
->engine
);
209 ACOGC_STACK_PTR (MalaStringList
, node
);
210 node
.ptr
= mala_stringlist_node_new (name
.ptr
, prg
->engine
);
211 mala_stringlist_insert_after (end
, node
.ptr
);
216 mala_program_action_done (prg
, 1);
221 mala_substitute_parser (MalaProgram prg
)
225 REQUIRE (acogc_object_type (mala_program_pptr_action (prg
)->data
)
226 == &prg
->engine
->gcfactory_strings
);
228 mala_stringlist_next (prg
->pptr
)->string
= mala_action_string (mala_program_pptr_action (prg
));
232 return MALA_CONTINUE
;
236 mala_expand_parser (MalaProgram prg
)
240 MalaAction act
= mala_program_pptr_action (prg
);
241 REQUIRE (acogc_object_type (mala_action_dataptr (act
))
242 == &prg
->engine
->gcfactory_stringlists
);
244 MalaStringList pos
= mala_stringlist_next (prg
->pptr
);
247 for (itr
= mala_stringlist_tail_get (mala_action_stringlist (act
));
248 !mala_stringlist_is_end (mala_action_stringlist (act
), itr
);
249 mala_stringlist_rev (&itr
))
251 MalaStringList node
= mala_stringlist_node_new (mala_stringlist_string (itr
), prg
->engine
);
252 mala_stringlist_insert_after (pos
, node
);
257 mala_program_action_done (prg
, 0);
258 return MALA_CONTINUE
;
263 mala_macro_parser (MalaProgram prg
)
265 NOTICE (mala_module_std_macros
, "macro parser");
267 /* How much to eveluate the argument (for now, likely extended in future):
268 MALA_REMOVE is used as pseudo tag for unused arguments/initialization
269 MALA_START doesn't evaluate the argument
270 MALA_LITERAL will evaluate fully
271 .. other destination states are reserved for future
274 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
275 MalaAction act
= mala_program_pptr_action (prg
);
277 // scan for arguments
278 AcogcFactory type
= mala_action_data_type (act
);
279 if (type
== &prg
->engine
->gcfactory_strings
)
281 mala_string_macrocheck (mala_action_string (act
), &max_arg
, argt
);
283 else if (type
== &prg
->engine
->gcfactory_stringlists
)
285 mala_stringlist_macrocheck (mala_action_stringlist (act
), &max_arg
, argt
);
290 if (max_arg
== INT_MAX
)
291 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
294 return mala_expand_parser (prg
);
297 for (int i
=1; i
<= max_arg
; ++i
)
299 if (argt
[i
] < MALA_START
)
301 if (mala_program_eval_arg (prg
, i
, argt
[i
], NULL
) > MALA_EFAULT
)
302 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
303 TODO("use dst in arg_eval");
309 // construct result list
311 MalaStringList p
= mala_stringlist_next (prg
->pptr
);
312 for (int i
=1; i
<= max_arg
; ++i
)
314 mala_stringlist_fwd (&p
);
315 args
[i
] = mala_stringlist_string (p
);
318 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
320 if (type
== &prg
->engine
->gcfactory_strings
)
322 ACOGC_STACK_PTR (MalaString
, string
);
323 string
.ptr
= mala_string_new_macrosubst (mala_action_string (act
),
326 MalaStringList n
= mala_stringlist_node_new (string
.ptr
, prg
->engine
);
327 mala_stringlist_insert_after (p
, n
);
329 else if (type
== &prg
->engine
->gcfactory_stringlists
)
331 ACOGC_STACK_PTR (MalaStringList
, list
);
332 list
.ptr
= mala_stringlist_new_macrosubst (mala_action_stringlist (act
),
334 mala_stringlist_insert_after_stringlist (p
, list
.ptr
);
343 mala_program_action_done (prg
, max_arg
);
344 return MALA_CONTINUE
;
348 mala_end_parser (MalaProgram prg
)
350 return mala_program_commonexception (prg
, MALA_STRING_ERROR_END_WITHOUT_BEGIN
);
354 mala_def_parser (MalaProgram prg
)
360 // evaluate both args
361 if (mala_program_eval_arg (prg
, 1, MALA_LITERAL
, &dst
) > MALA_EFAULT
)
362 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
364 name
= mala_stringlist_string (dst
);
366 if (mala_program_eval_arg (prg
, 2, MALA_MACRO
, &dst
) > MALA_EFAULT
)
367 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
369 expand
= mala_stringlist_string (dst
);
373 TODO("optimize direct expansions");
375 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
376 mala_string_macrocheck (expand
, &max_arg
, argt
);
378 if (max_arg
== INT_MAX
)
379 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
380 else if (max_arg
== -1)
381 // register as simple substitute
382 mala_action_new (name
, mala_substitute_parser
, expand
, ACOGC_GC
, prg
->engine
);
385 mala_action_new (name
, mala_macro_parser
, expand
, ACOGC_GC
, prg
->engine
);
389 mala_program_action_done (prg
, 2);
390 return MALA_CONTINUE
;
394 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10])
396 LLIST_FOREACH (&list
->node
, itr
)
398 MalaStringList l
= LLIST_TO_STRUCTP(itr
, mala_stringlist
, node
);
399 mala_string_macrocheck (mala_stringlist_string (l
), max_arg
, argt
);
400 if (*max_arg
== INT_MAX
)
406 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10])
409 for (c
= mala_string_cstr (string
); *c
; ++c
)
423 if (*c
>= '0' && *c
<= '9')
425 if (argt
[*c
- '0'] < MALA_REMOVE
&& argt
[*c
- '0'] != MALA_START
)
427 if (*c
> (char) *max_arg
+ '0')
429 argt
[*c
- '0'] = MALA_START
;
434 else if (*c
>= '0' && *c
<= '9')
436 if (argt
[*c
- '0'] != MALA_REMOVE
&& argt
[*c
- '0'] != MALA_LITERAL
)
438 if (*c
> (char) *max_arg
+ '0')
440 argt
[*c
- '0'] = MALA_LITERAL
;
455 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
)
458 size_t size
= mala_string_length (src
);
459 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
473 TODO ("Handle %%-0");
474 size
+= mala_string_length (args
[*c
- '0']);
478 // 2nd pass create string
480 acogc_alloc (&cstr
, size
+1, &eng
->gcroot
);
484 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
497 TODO ("Handle %%-0");
499 strcpy (p
, mala_string_cstr (args
[*c
- '0']));
500 p
+= mala_string_length (args
[*c
- '0']);
507 return mala_string_new_attach_cstr (cstr
, eng
->words
);
510 static MalaStringList
511 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
)
513 ACOGC_STACK_ENTER (&eng
->gcroot
);
514 ACOGC_STACK_PTR (MalaStringList
, ret
);
516 ret
.ptr
= mala_stringlist_new (eng
);
518 LLIST_FOREACH (&src
->node
, node
)
520 ACOGC_STACK_PTR (MalaString
, str
);
521 str
.ptr
= mala_string_new_macrosubst (mala_stringlist_string_from_llist(node
), args
, eng
);
522 MalaStringList n
= mala_stringlist_node_new (str
.ptr
, eng
);
523 mala_stringlist_insert_tail (ret
.ptr
, n
);
535 #if 0 // old macrodelete_parser
537 mala_macrodelete_parser (MalaProgram prg
, void * data
)
541 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
);
545 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
546 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
547 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
549 mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg
))));
553 mala_engine_command_done (eng
, pptr
, 1);
556 #endif // old macrodelete
559 mala_delete_parser (MalaProgram prg
)
561 //mala_engine_arg_eval (eng, pptr, 1, MALA_LITERAL);
565 #if 0 // TODO --PROGRAM
566 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
567 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
568 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
570 // TODO mala_actiondesc_pop_delete (mala_stringlist_user_get (mala_stringlist_next (mala_program_pos (prg))));
574 // mala_program_action_done (prg, 1);
581 realloc a string to at least needed size
582 return the amount really reserved or 0 on error
584 #if 0 // TODO acogc reserve!
586 reserve_string (char ** s
, size_t actual
, size_t needed
)
591 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
596 /* that was to much, try conservatively */
597 r
= realloc (*s
, n
= needed
);
606 NOBUG_DEFINE_FLAG (mala_module_std_macros
);
609 mala_module_std_macros_init (MalaEngine self
)
611 NOBUG_INIT_FLAG (mala_module_std_macros
);
612 return mala_engine_actions_register (self
, std_macros
);
618 // c-file-style: "gnu"
620 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5