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("--BEGIN", "defines a block or list"),
48 //TODO MALA_PARSER_SIGNATURE_TYPE("--BEGIN", ("SEQUENCE","END")),
49 //TODO MALA_PARSER_SIGNATURE_USAGE("--BEGIN", ("content of the block", "a --END which closes the block")),
50 //TODO MALA_PARSER_RESULT_TYPE("--BEGIN", ("BLOCK")),
51 //TODO MALA_PARSER_RESULT_USAGE("--BEGIN", ("a unique name of the block")),
52 //TODO MALA_PARSER_HELP("--BEGIN", ("Blocks can have % substitutions, Blocks are garbage collected, TODO")),
55 MALA_PARSER_SIMPLE("--END", mala_end_parser
),
56 // TODO MALA_PARSER_BRIEF("--END", "closes a block"),
57 //TODOMALA_PARSER_HELP("--END", ("an --END without a matching --BEGIN raises an error.")),
59 MALA_PARSER_SIMPLE("--DEF", mala_def_parser
),
60 //MALA_PARSER_BRIEF("--DEF", "defines a substitution"),
61 //MALA_PARSER_SIGNATURE_TYPE("--DEF", ("WORD", "WORD-OR-BLOCK")),
62 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEF", ("word to be substituted",
63 // "replaced with this")),
64 //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.")),
65 //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"),
66 //MALA_PARSER_BRIEF("MACROS", "TODO"),
67 //MALA_PARSER_HELP("MACROS", ("TODO")),
70 MALA_PARSER("--", mala__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("--", ("")),
78 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
79 MALA_PARSER_BRIEF("--", ""),
80 MALA_PARSER_HELP("--", ("TODO")),
81 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
82 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
83 MALA_PARSER_RESULT_TYPE("--", ("")),
84 MALA_PARSER_RESULT_USAGE("--", ("")),
90 //MALA_PARSER_BRIEF("--DEL", "deletes a macro"),
91 //TODO MALA_PARSER_SIGNATURE_TYPE("--DEL", ("WORD")),
92 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEL", ("name of the Macro to delete")),
93 //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)")),
101 mala_begin_parser (MalaProgram prg
)
106 TRACE (mala_module_std
);
108 // find matching --END
109 MalaStringList begin
= mala_stringlist_next (prg
->pptr
);
111 !mala_stringlist_is_end (prg
->program
, end
);
112 mala_stringlist_fwd (&end
))
114 if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_BEGIN
])
116 else if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_END
])
124 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MISSING_END
);
126 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
127 ACOGC_STACK_PTR (MalaStringList
, list
);
128 ACOGC_STACK_PTR (MalaString
, name
);
130 list
.ptr
= mala_stringlist_new (prg
->engine
);
133 // move elements into destionation list
134 while (mala_stringlist_next (begin
) != end
)
136 mala_stringlist_insert_tail (list
.ptr
, mala_stringlist_next (begin
));
140 MalaParserFunc parser
;
142 mala_state argt
[10] = {[0 ... 9] = MALA_EXCEPTION
};
150 // --BEGIN --END becomes --PASS
151 TODO ("direct --PASS substitute");
152 parser
= mala_pass_parser
;
153 templ
= "--BLOCK_%08X";
156 else if (length
== 1)
158 data
= mala_stringlist_string (mala_stringlist_head_get (list
.ptr
));
159 mala_string_macrocheck ((MalaString
) data
, &max_arg
, argt
);
160 if (max_arg
== INT_MAX
)
162 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
164 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
169 // --BEGIN FOO --END becomes FOO
170 TODO ("direct name substitute");
171 parser
= mala_substitute_parser
;
172 templ
= "--BLOCK_%08X";
177 parser
= mala_macro_parser
;
178 templ
= "--BLOCK_%08X";
185 mala_stringlist_macrocheck (list
.ptr
, &max_arg
, argt
);
186 if (max_arg
== INT_MAX
)
188 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
190 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
195 parser
= mala_expand_parser
;
196 templ
= "--BLOCK_%08X";
201 parser
= mala_macro_parser
;
202 templ
= "--BLOCK_%08X";
207 mala_stringlist_remove (mala_stringlist_next (prg
->pptr
));
211 // insert new --nnn... in program
212 name
.ptr
= mala_engine_tmpname (prg
->engine
, templ
);
213 TRACE (mala_module_std
, "Block %s", mala_string_cstr (name
.ptr
) );
214 mala_action_new (name
.ptr
, parser
, data
, data
?ACOGC_GC
:ACOGC_UNSET
, prg
->engine
);
215 ACOGC_STACK_PTR (MalaStringList
, node
);
216 node
.ptr
= mala_stringlist_node_new (name
.ptr
, prg
->engine
);
217 mala_stringlist_insert_after (end
, node
.ptr
);
218 mala_stringlist_remove (mala_stringlist_next (prg
->pptr
));
222 mala_stringlist_next (prg
->pptr
)->string
= prg
->engine
->common_string
[MALA_STRING_PASS
];
231 mala_substitute_parser (MalaProgram prg
)
233 TRACE (mala_module_std
);
236 REQUIRE (acogc_object_type (mala_program_pptr_action (prg
)->data
)
237 == &prg
->engine
->gcfactory_strings
);
239 mala_stringlist_next (prg
->pptr
)->string
= mala_action_string (mala_program_pptr_action (prg
));
247 mala_expand_parser (MalaProgram prg
)
249 TRACE (mala_module_std
);
252 MalaAction act
= mala_program_pptr_action (prg
);
253 REQUIRE (acogc_object_type (mala_action_dataptr (act
))
254 == &prg
->engine
->gcfactory_stringlists
);
256 MalaStringList pos
= mala_stringlist_next (prg
->pptr
);
259 for (itr
= mala_stringlist_tail_get (mala_action_stringlist (act
));
260 !mala_stringlist_is_end (mala_action_stringlist (act
), itr
);
261 mala_stringlist_rev (&itr
))
263 MalaStringList node
= mala_stringlist_node_new (mala_stringlist_string (itr
), prg
->engine
);
264 mala_stringlist_insert_after (pos
, node
);
269 mala_program_action_done (prg
, 0);
275 mala_macro_parser (MalaProgram prg
)
277 TRACE (mala_module_std
);
279 /* How much to eveluate the argument (for now, likely extended in future):
280 MALA_EXCEPTION is used as pseudo tag for unused arguments/initialization
281 MALA_START doesn't evaluate the argument
282 MALA_LITERAL will evaluate fully
283 .. other destination states are reserved for future
286 mala_state argt
[10] = {[0 ... 9] = MALA_EXCEPTION
};
287 MalaAction act
= mala_program_pptr_action (prg
);
289 // scan for arguments
290 AcogcFactory type
= mala_action_data_type (act
);
291 if (type
== &prg
->engine
->gcfactory_strings
)
293 mala_string_macrocheck (mala_action_string (act
), &max_arg
, argt
);
295 else if (type
== &prg
->engine
->gcfactory_stringlists
)
297 mala_stringlist_macrocheck (mala_action_stringlist (act
), &max_arg
, argt
);
302 if (max_arg
== INT_MAX
)
303 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
306 return mala_expand_parser (prg
);
309 for (int i
=1; i
<= max_arg
; ++i
)
311 if (argt
[i
] <= MALA_START
)
313 if (mala_program_eval_arg (prg
, i
, argt
[i
], NULL
) > MALA_EFAULT
)
314 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
315 TODO("use dst in arg_eval");
321 // construct result list
323 MalaStringList p
= mala_stringlist_next (prg
->pptr
);
325 args
[0] = mala_stringlist_string (p
);
326 for (int i
=1; i
<= max_arg
; ++i
)
328 mala_stringlist_fwd (&p
);
329 args
[i
] = mala_stringlist_string (p
);
332 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
334 if (type
== &prg
->engine
->gcfactory_strings
)
336 ACOGC_STACK_PTR (MalaString
, string
);
337 string
.ptr
= mala_string_new_macrosubst (mala_action_string (act
),
340 MalaStringList n
= mala_stringlist_node_new (string
.ptr
, prg
->engine
);
341 mala_stringlist_insert_after (p
, n
);
343 else if (type
== &prg
->engine
->gcfactory_stringlists
)
345 ACOGC_STACK_PTR (MalaStringList
, list
);
346 list
.ptr
= mala_stringlist_new_macrosubst (mala_action_stringlist (act
),
348 mala_stringlist_insert_after_stringlist (p
, list
.ptr
);
357 mala_program_action_done (prg
, max_arg
);
362 mala_end_parser (MalaProgram prg
)
364 TRACE (mala_module_std
);
365 return mala_program_commonexception (prg
, MALA_STRING_ERROR_END_WITHOUT_BEGIN
);
369 mala_def_parser (MalaProgram prg
)
375 TRACE (mala_module_std
);
376 // evaluate both args
377 if (mala_program_eval_arg (prg
, 1, MALA_LITERAL
, &dst
) > MALA_EFAULT
)
378 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
380 name
= mala_stringlist_string (dst
);
382 if (mala_program_eval_arg (prg
, 2, MALA_BLOCK
, &dst
) > MALA_EFAULT
)
383 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
385 expand
= mala_stringlist_string (dst
);
387 TRACE (mala_module_std
, "def %s as %s", mala_string_cstr (name
), mala_string_cstr (expand
));
391 TODO("optimize direct expansions");
393 mala_state argt
[10] = {[0 ... 9] = MALA_EXCEPTION
};
394 mala_string_macrocheck (expand
, &max_arg
, argt
);
396 if (max_arg
== INT_MAX
)
397 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
398 else if (max_arg
== -1)
399 // register as simple substitute
400 mala_action_new (name
, mala_substitute_parser
, expand
, ACOGC_GC
, prg
->engine
);
403 mala_action_new (name
, mala_macro_parser
, expand
, ACOGC_GC
, prg
->engine
);
407 mala_program_action_done (prg
, 2);
408 return MALA_STATEMENT
;
413 mala_delete_parser (MalaProgram prg
)
415 TRACE (mala_module_std
);
418 if (mala_program_eval_arg (prg
, 1, MALA_LITERAL
, &dst
) > MALA_EFAULT
)
419 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
423 MalaAction act
= mala_string_action (mala_stringlist_string (dst
));
425 mala_action_delete (mala_string_action (mala_stringlist_string (dst
)));
427 return mala_program_commonexception (prg
, MALA_STRING_ERROR_ACTION_NOT_DEFINED
);
431 mala_program_action_done (prg
, 1);
432 return MALA_STATEMENT
;
437 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10])
439 LLIST_FOREACH (&list
->node
, itr
)
441 MalaStringList l
= LLIST_TO_STRUCTP(itr
, mala_stringlist
, node
);
442 mala_string_macrocheck (mala_stringlist_string (l
), max_arg
, argt
);
443 if (*max_arg
== INT_MAX
)
449 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10])
452 for (c
= mala_string_cstr (string
); *c
; ++c
)
466 if (*c
>= '0' && *c
<= '9')
468 if (argt
[*c
- '0'] < MALA_EXCEPTION
&& argt
[*c
- '0'] != MALA_START
)
470 if (*c
> (char) *max_arg
+ '0')
472 argt
[*c
- '0'] = MALA_START
;
477 else if (*c
>= '0' && *c
<= '9')
479 if (argt
[*c
- '0'] != MALA_EXCEPTION
&& argt
[*c
- '0'] != MALA_LITERAL
)
481 if (*c
> (char) *max_arg
+ '0')
483 argt
[*c
- '0'] = MALA_LITERAL
;
498 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
)
501 size_t size
= mala_string_length (src
);
502 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
516 TODO ("Handle %%^0");
517 size
+= mala_string_length (args
[*c
- '0']);
521 // 2nd pass create string
523 acogc_alloc (&cstr
, size
+1, &eng
->gcroot
);
527 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
540 TODO ("Handle %%^0");
542 strcpy (p
, mala_string_cstr (args
[*c
- '0']));
543 p
+= mala_string_length (args
[*c
- '0']);
550 return mala_string_new_attach_cstr (cstr
, eng
->words
);
553 static MalaStringList
554 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
)
556 ACOGC_STACK_ENTER (&eng
->gcroot
);
557 ACOGC_STACK_PTR (MalaStringList
, ret
);
558 ACOGC_STACK_PTR (MalaString
, str
);
560 ret
.ptr
= mala_stringlist_new (eng
);
562 LLIST_FOREACH (&src
->node
, node
)
564 str
.ptr
= mala_string_new_macrosubst (mala_stringlist_string_from_llist(node
), args
, eng
);
565 MalaStringList n
= mala_stringlist_node_new (str
.ptr
, eng
);
566 mala_stringlist_insert_tail (ret
.ptr
, n
);
579 realloc a string to at least needed size
580 return the amount really reserved or 0 on error
582 #if 0 // TODO acogc reserve!
584 reserve_string (char ** s
, size_t actual
, size_t needed
)
589 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
594 /* that was to much, try conservatively */
595 r
= realloc (*s
, n
= needed
);
605 mala_module_std_macros_init (MalaEngine self
)
607 return mala_engine_actions_register (self
, std_macros
);
613 // c-file-style: "gnu"
615 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5