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
),
46 // MALA_PARSER_BRIEF("--BEGIN", "defines a block or list"),
47 //TODO MALA_PARSER_SIGNATURE_TYPE("--BEGIN", ("SEQUENCE","END")),
48 //TODO MALA_PARSER_SIGNATURE_USAGE("--BEGIN", ("content of the block", "a --END which closes the block")),
49 //TODO MALA_PARSER_RESULT_TYPE("--BEGIN", ("BLOCK")),
50 //TODO MALA_PARSER_RESULT_USAGE("--BEGIN", ("a unique name of the block")),
51 //TODO MALA_PARSER_HELP("--BEGIN", ("Blocks can have % substitutions, Blocks are garbage collected, TODO")),
54 MALA_PARSER_SIMPLE("--END", mala_end_parser
),
55 // TODO MALA_PARSER_BRIEF("--END", "closes a block"),
56 //TODOMALA_PARSER_HELP("--END", ("an --END without a matching --BEGIN raises an error.")),
58 MALA_PARSER_SIMPLE("--DEF", mala_def_parser
),
59 //MALA_PARSER_BRIEF("--DEF", "defines a substitution"),
60 //MALA_PARSER_SIGNATURE_TYPE("--DEF", ("WORD", "WORD-OR-BLOCK")),
61 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEF", ("word to be substituted",
62 // "replaced with this")),
63 //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.")),
64 //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"),
65 //MALA_PARSER_BRIEF("MACROS", "TODO"),
66 //MALA_PARSER_HELP("MACROS", ("TODO")),
69 MALA_PARSER("--", mala__parser, NULL, NULL, NULL),
70 MALA_PARSER_BRIEF("--", ""),
71 MALA_PARSER_HELP("--", ("TODO")),
72 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
73 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
74 MALA_PARSER_RESULT_TYPE("--", ("")),
75 MALA_PARSER_RESULT_USAGE("--", ("")),
77 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
78 MALA_PARSER_BRIEF("--", ""),
79 MALA_PARSER_HELP("--", ("TODO")),
80 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
81 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
82 MALA_PARSER_RESULT_TYPE("--", ("")),
83 MALA_PARSER_RESULT_USAGE("--", ("")),
89 //MALA_PARSER_BRIEF("--DEL", "deletes a macro"),
90 //TODO MALA_PARSER_SIGNATURE_TYPE("--DEL", ("WORD")),
91 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEL", ("name of the Macro to delete")),
92 //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)")),
100 mala_begin_parser (MalaProgram prg
)
105 // find matching --END
106 MalaStringList begin
= mala_stringlist_next (prg
->pptr
);
108 !mala_stringlist_is_end (prg
->program
, end
);
109 mala_stringlist_fwd (&end
))
111 if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_BEGIN
])
113 else if (mala_stringlist_string (end
) == prg
->engine
->common_string
[MALA_STRING_END
])
121 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MISSING_END
);
123 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
124 ACOGC_STACK_PTR (MalaStringList
, list
);
125 ACOGC_STACK_PTR (MalaString
, name
);
127 list
.ptr
= mala_stringlist_new (prg
->engine
);
130 // move elements into destionation list
131 while (mala_stringlist_next (begin
) != end
)
133 mala_stringlist_insert_tail (list
.ptr
, mala_stringlist_next (begin
));
137 MalaParserFunc parser
;
139 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
147 // --BEGIN --END becomes --PASS
148 TODO ("direct --PASS substitute");
149 parser
= mala_pass_parser
;
150 templ
= "--BLOCK_%08X";
153 else if (length
== 1)
155 data
= mala_stringlist_string (mala_stringlist_head_get (list
.ptr
));
156 mala_string_macrocheck ((MalaString
) data
, &max_arg
, argt
);
157 if (max_arg
== INT_MAX
)
159 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
161 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
166 // --BEGIN FOO --END becomes FOO
167 TODO ("direct name substitute");
168 parser
= mala_substitute_parser
;
169 templ
= "--BLOCK_%08X";
174 parser
= mala_macro_parser
;
175 templ
= "--BLOCK_%08X";
182 mala_stringlist_macrocheck (list
.ptr
, &max_arg
, argt
);
183 if (max_arg
== INT_MAX
)
185 mala_stringlist_insert_after_stringlist (begin
, list
.ptr
);
187 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
192 parser
= mala_expand_parser
;
193 templ
= "--BLOCK_%08X";
198 parser
= mala_macro_parser
;
199 templ
= "--BLOCK_%08X";
206 // insert new --nnn... in program
207 name
.ptr
= mala_engine_tmpname (prg
->engine
, templ
);
208 TRACE (mala_module_std_macros
, "Block %s", mala_string_cstr (name
.ptr
) );
209 mala_action_new (name
.ptr
, parser
, data
, data
?ACOGC_GC
:ACOGC_UNSET
, prg
->engine
);
210 ACOGC_STACK_PTR (MalaStringList
, node
);
211 node
.ptr
= mala_stringlist_node_new (name
.ptr
, prg
->engine
);
212 mala_stringlist_insert_after (end
, node
.ptr
);
217 mala_program_action_done (prg
, 1);
222 mala_substitute_parser (MalaProgram prg
)
226 REQUIRE (acogc_object_type (mala_program_pptr_action (prg
)->data
)
227 == &prg
->engine
->gcfactory_strings
);
229 mala_stringlist_next (prg
->pptr
)->string
= mala_action_string (mala_program_pptr_action (prg
));
233 return MALA_CONTINUE
;
237 mala_expand_parser (MalaProgram prg
)
241 MalaAction act
= mala_program_pptr_action (prg
);
242 REQUIRE (acogc_object_type (mala_action_dataptr (act
))
243 == &prg
->engine
->gcfactory_stringlists
);
245 MalaStringList pos
= mala_stringlist_next (prg
->pptr
);
248 for (itr
= mala_stringlist_tail_get (mala_action_stringlist (act
));
249 !mala_stringlist_is_end (mala_action_stringlist (act
), itr
);
250 mala_stringlist_rev (&itr
))
252 MalaStringList node
= mala_stringlist_node_new (mala_stringlist_string (itr
), prg
->engine
);
253 mala_stringlist_insert_after (pos
, node
);
258 mala_program_action_done (prg
, 0);
259 return MALA_CONTINUE
;
264 mala_macro_parser (MalaProgram prg
)
266 NOTICE (mala_module_std_macros
, "macro parser");
268 /* How much to eveluate the argument (for now, likely extended in future):
269 MALA_REMOVE is used as pseudo tag for unused arguments/initialization
270 MALA_START doesn't evaluate the argument
271 MALA_LITERAL will evaluate fully
272 .. other destination states are reserved for future
275 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
276 MalaAction act
= mala_program_pptr_action (prg
);
278 // scan for arguments
279 AcogcFactory type
= mala_action_data_type (act
);
280 if (type
== &prg
->engine
->gcfactory_strings
)
282 mala_string_macrocheck (mala_action_string (act
), &max_arg
, argt
);
284 else if (type
== &prg
->engine
->gcfactory_stringlists
)
286 mala_stringlist_macrocheck (mala_action_stringlist (act
), &max_arg
, argt
);
291 if (max_arg
== INT_MAX
)
292 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
295 return mala_expand_parser (prg
);
298 for (int i
=1; i
<= max_arg
; ++i
)
300 if (argt
[i
] < MALA_START
)
302 if (mala_program_eval_arg (prg
, i
, argt
[i
], NULL
) > MALA_EFAULT
)
303 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
304 TODO("use dst in arg_eval");
310 // construct result list
312 MalaStringList p
= mala_stringlist_next (prg
->pptr
);
313 for (int i
=1; i
<= max_arg
; ++i
)
315 mala_stringlist_fwd (&p
);
316 args
[i
] = mala_stringlist_string (p
);
319 ACOGC_STACK_ENTER (&prg
->engine
->gcroot
);
321 if (type
== &prg
->engine
->gcfactory_strings
)
323 ACOGC_STACK_PTR (MalaString
, string
);
324 string
.ptr
= mala_string_new_macrosubst (mala_action_string (act
),
327 MalaStringList n
= mala_stringlist_node_new (string
.ptr
, prg
->engine
);
328 mala_stringlist_insert_after (p
, n
);
330 else if (type
== &prg
->engine
->gcfactory_stringlists
)
332 ACOGC_STACK_PTR (MalaStringList
, list
);
333 list
.ptr
= mala_stringlist_new_macrosubst (mala_action_stringlist (act
),
335 mala_stringlist_insert_after_stringlist (p
, list
.ptr
);
344 mala_program_action_done (prg
, max_arg
);
345 return MALA_CONTINUE
;
349 mala_end_parser (MalaProgram prg
)
351 return mala_program_commonexception (prg
, MALA_STRING_ERROR_END_WITHOUT_BEGIN
);
355 mala_def_parser (MalaProgram prg
)
361 // evaluate both args
362 if (mala_program_eval_arg (prg
, 1, MALA_LITERAL
, &dst
) > MALA_EFAULT
)
363 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
365 name
= mala_stringlist_string (dst
);
367 if (mala_program_eval_arg (prg
, 2, MALA_MACRO
, &dst
) > MALA_EFAULT
)
368 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
370 expand
= mala_stringlist_string (dst
);
374 TODO("optimize direct expansions");
376 mala_state argt
[10] = {[0 ... 9] = MALA_REMOVE
};
377 mala_string_macrocheck (expand
, &max_arg
, argt
);
379 if (max_arg
== INT_MAX
)
380 return mala_program_commonexception (prg
, MALA_STRING_ERROR_MACRO_SYNTAX
);
381 else if (max_arg
== -1)
382 // register as simple substitute
383 mala_action_new (name
, mala_substitute_parser
, expand
, ACOGC_GC
, prg
->engine
);
386 mala_action_new (name
, mala_macro_parser
, expand
, ACOGC_GC
, prg
->engine
);
390 mala_program_action_done (prg
, 2);
391 return MALA_CONTINUE
;
396 mala_delete_parser (MalaProgram prg
)
400 if (mala_program_eval_arg (prg
, 1, MALA_LITERAL
, &dst
) > MALA_EFAULT
)
401 return mala_program_commonexception (prg
, MALA_STRING_ERROR
);
405 MalaAction act
= mala_string_action (mala_stringlist_string (dst
));
407 mala_action_delete (mala_string_action (mala_stringlist_string (dst
)));
409 return mala_program_commonexception (prg
, MALA_STRING_ERROR_ACTION_NOT_DEFINED
);
413 mala_program_action_done (prg
, 1);
414 return MALA_CONTINUE
;
419 mala_stringlist_macrocheck (MalaStringList list
, int * max_arg
, mala_state argt
[10])
421 LLIST_FOREACH (&list
->node
, itr
)
423 MalaStringList l
= LLIST_TO_STRUCTP(itr
, mala_stringlist
, node
);
424 mala_string_macrocheck (mala_stringlist_string (l
), max_arg
, argt
);
425 if (*max_arg
== INT_MAX
)
431 mala_string_macrocheck (MalaString string
, int * max_arg
, mala_state argt
[10])
434 for (c
= mala_string_cstr (string
); *c
; ++c
)
448 if (*c
>= '0' && *c
<= '9')
450 if (argt
[*c
- '0'] < MALA_REMOVE
&& argt
[*c
- '0'] != MALA_START
)
452 if (*c
> (char) *max_arg
+ '0')
454 argt
[*c
- '0'] = MALA_START
;
459 else if (*c
>= '0' && *c
<= '9')
461 if (argt
[*c
- '0'] != MALA_REMOVE
&& argt
[*c
- '0'] != MALA_LITERAL
)
463 if (*c
> (char) *max_arg
+ '0')
465 argt
[*c
- '0'] = MALA_LITERAL
;
480 mala_string_new_macrosubst (MalaString src
, MalaString args
[10], MalaEngine eng
)
483 size_t size
= mala_string_length (src
);
484 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
498 TODO ("Handle %%-0");
499 size
+= mala_string_length (args
[*c
- '0']);
503 // 2nd pass create string
505 acogc_alloc (&cstr
, size
+1, &eng
->gcroot
);
509 for (const char *c
= mala_string_cstr (src
); *c
; ++c
)
522 TODO ("Handle %%-0");
524 strcpy (p
, mala_string_cstr (args
[*c
- '0']));
525 p
+= mala_string_length (args
[*c
- '0']);
532 return mala_string_new_attach_cstr (cstr
, eng
->words
);
535 static MalaStringList
536 mala_stringlist_new_macrosubst (MalaStringList src
, MalaString args
[10], MalaEngine eng
)
538 ACOGC_STACK_ENTER (&eng
->gcroot
);
539 ACOGC_STACK_PTR (MalaStringList
, ret
);
540 ACOGC_STACK_PTR (MalaString
, str
);
542 ret
.ptr
= mala_stringlist_new (eng
);
544 LLIST_FOREACH (&src
->node
, node
)
546 str
.ptr
= mala_string_new_macrosubst (mala_stringlist_string_from_llist(node
), args
, eng
);
547 MalaStringList n
= mala_stringlist_node_new (str
.ptr
, eng
);
548 mala_stringlist_insert_tail (ret
.ptr
, n
);
561 realloc a string to at least needed size
562 return the amount really reserved or 0 on error
564 #if 0 // TODO acogc reserve!
566 reserve_string (char ** s
, size_t actual
, size_t needed
)
571 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
576 /* that was to much, try conservatively */
577 r
= realloc (*s
, n
= needed
);
586 NOBUG_DEFINE_FLAG (mala_module_std_macros
);
589 mala_module_std_macros_init (MalaEngine self
)
591 NOBUG_INIT_FLAG (mala_module_std_macros
);
592 return mala_engine_actions_register (self
, std_macros
);
598 // c-file-style: "gnu"
600 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5