2 std_parsers.c - MaLa standard module parsers
4 Copyright (C) 2005, Christian Thaeter <chth@gmx.net>
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.
28 //mala_macrocheck_list (LList list, int * max_arg, int argt[10]);
31 //mala_macrocheck_string (MalaString string, int * max_arg, int argt[10]);
35 mala_actioninit std_macros
[] =
38 //MALA_PARSER_BRIEF("MACROS", "TODO"),
39 //MALA_PARSER_HELP("MACROS", ("TODO")),
42 MALA_PARSER("--", mala__parser, NULL, NULL, NULL),
43 MALA_PARSER_BRIEF("--", ""),
44 MALA_PARSER_HELP("--", ("TODO")),
45 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
46 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
47 MALA_PARSER_RESULT_TYPE("--", ("")),
48 MALA_PARSER_RESULT_USAGE("--", ("")),
50 MALA_PARSER("--FOREACH-WORD", mala_foreach_word_parser, NULL, NULL, NULL),
51 MALA_PARSER_BRIEF("--", ""),
52 MALA_PARSER_HELP("--", ("TODO")),
53 MALA_PARSER_SIGNATURE_TYPE("--", ("")),
54 MALA_PARSER_SIGNATURE_USAGE("--", ("")),
55 MALA_PARSER_RESULT_TYPE("--", ("")),
56 MALA_PARSER_RESULT_USAGE("--", ("")),
61 //MALA_SIMPLE_PARSER("--DEF", mala_def_parser),
62 MALA_PARSER_BRIEF("--DEF", "defines a substitution"),
63 MALA_PARSER_SIGNATURE_TYPE("--DEF", ("WORD", "WORD-OR-BLOCK")),
64 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEF", ("word to be substituted",
65 // "replaced with this")),
66 //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.")),
67 //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"),
70 //MALA_PARSER("--END", mala_end_parser, NULL, NULL, NULL),
71 // TODO MALA_PARSER_BRIEF("--END", "closes a block"),
72 //TODOMALA_PARSER_HELP("--END", ("an --END without a matching --BEGIN raises an error.")),
75 MALA_SIMPLE_PARSER("--DEL", mala_delete_parser
),
77 MALA_PARSER_BRIEF("--DEL", "deletes a macro"),
78 //TODO MALA_PARSER_SIGNATURE_TYPE("--DEL", ("WORD")),
79 //TODO MALA_PARSER_SIGNATURE_USAGE("--DEL", ("name of the Macro to delete")),
80 //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)")),
82 MALA_SIMPLE_PARSER("--BEGIN", mala_begin_parser
),
83 MALA_PARSER_BRIEF("--BEGIN", "defines a block or list"),
84 //TODO MALA_PARSER_SIGNATURE_TYPE("--BEGIN", ("SEQUENCE","END")),
85 //TODO MALA_PARSER_SIGNATURE_USAGE("--BEGIN", ("content of the block", "a --END which closes the block")),
86 //TODO MALA_PARSER_RESULT_TYPE("--BEGIN", ("BLOCK")),
87 //TODO MALA_PARSER_RESULT_USAGE("--BEGIN", ("a unique name of the block")),
88 //TODO MALA_PARSER_HELP("--BEGIN", ("Blocks can have % substitutions, Blocks are garbage collected, TODO")),
96 mala_substitute_parser (MalaProgram prg
, void * data
)
99 mala_stringlistnode_substitute_string (mala_program_pos (prg
), (MalaString
) data
);
102 return MALA_CONTINUE
;
106 mala_expand_parser (MalaProgram prg
, void * data
)
109 //MalaStringListNode itr;
110 // MalaStringListNode end;
112 MALA_SIDEEFFECT_BEGIN
116 end
= mala_stringlistnode_next (mala_program_pos (prg
));
118 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
119 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
120 mala_stringlistnode_rev (&itr
))
122 // TODO --PROGRAM if (!mala_stringlist_after_new (&eng->program, mala_program_pos (prg),
123 // mala_stringlistnode_string (itr)))
130 mala_program_action_done (prg
, 0);
131 return MALA_CONTINUE
;
136 mala_macro_parser (MalaProgram prg
, void * data
)
141 MalaStringListNode itr
;
142 MalaStringListNode last
= NULL
;
150 MalaString str
= NULL
;
151 // scan how much args are needed
152 mala_macrocheck_list ((LList
) data
, &max_arg
, argt
);
154 // evaluate args, fill arg-array
155 args
[0] = mala_stringlistnode_string (mala_program_pos (prg
));
157 MALA_SIDEEFFECT_BEGIN
159 for (i
= 1; i
<= max_arg
; ++i
)
161 // TODO %STATEn evaluated to STATE
162 if (!(last
= mala_engine_arg_eval (eng
, pptr
, i
,
163 argt
[i
] == 1 ? MALA_LITERAL
: MALA_EXCEPTION
))
164 || eng
->state
> MALA_EFAULT
)
167 args
[i
] = mala_stringlistnode_string (last
);
170 // build list with substitutions
171 list
= mala_stringlist_new ();
175 if (!mala_stringlist_tail_new (list
, eng
->common_string
[MALA_STRING_BEGIN
]))
178 for (itr
= mala_stringlist_head ((MalaStringList
) data
);
179 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
180 mala_stringlistnode_fwd (&itr
))
183 if (!(p
= malloc (size
)))
186 for (c
= mala_string_cstr (mala_stringlistnode_string (itr
)), i
= 0; *c
; ++c
,++i
)
196 else if (*c
>= '0' && *c
<= '9')
199 if (size
<= i
+mala_string_length (args
[*c
-'0'])
200 && !(size
= reserve_string (&p
,
202 1 + i
+ mala_string_length (args
[*c
-'0']))))
204 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
205 i
+= (mala_string_length (args
[*c
-'0']) - 1);
210 if (*c
>= '0' && *c
<= '9')
213 if (size
<= i
+mala_string_length (args
[*c
-'0'])
214 && !(size
= reserve_string (&p
,
217 mala_string_length (args
[*c
-'0']))))
219 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
220 i
+= (mala_string_length (args
[*c
-'0']) - 1);
228 if (size
<= (size_t) i
&& !(size
= reserve_string (&p
, size
, (size_t) i
+1)))
237 if (!(ptmp
= realloc (p
, size
)))
240 str
= mala_string_new_attach_cstr (ptmp
, &eng
->words
, NULL
/*TODO refs*/); // TODO review
242 if (!mala_stringlist_tail_new (list
, str
))
245 // TODO review mala_string_free (str);
248 if (!mala_stringlist_tail_new (list
, eng
->common_string
[MALA_STRING_END
]))
252 for (itr
= mala_stringlist_tail (list
);
253 !mala_stringlist_is_end (list
, itr
);
254 mala_stringlistnode_rev (&itr
))
256 // if (!mala_stringlist_after_new (&eng->program, last,
257 // mala_stringlistnode_string (itr)))
262 mala_stringlist_free (list
);
267 mala_engine_command_done (eng
, pptr
, max_arg
);
269 return MALA_CONTINUE
;
274 mala_begin_parser (MalaProgram prg
, void * data
)
278 #if 0 // TODO --PROGRAM
279 MalaStringListNode itr
;
280 MalaStringListNode end
;
281 //MalaStringList list;
283 MalaString name
= NULL
;
287 //TODO --PROGRAM if (mala_stringlist_is_tail (&eng->program, mala_program_pos (prg)))
288 // return mala_engine_exception (eng, pptr, mala_program_pos (prg),
289 // eng->common_string[MALA_STRING_ERROR_MISSING_END]);
291 // find matching --END
292 for (end
= mala_stringlistnode_next (mala_program_pos (prg
));
293 !mala_stringlist_is_end (&eng
->program
, end
);
294 mala_stringlistnode_fwd (&end
))
296 //TODO if (mala_string_same(mala_stringlistnode_string (end),
297 // eng->common_string[MALA_STRING_BEGIN]))
299 //else if (mala_string_same(mala_stringlistnode_string (end),
300 // eng->common_string[MALA_STRING_END]))
307 return mala_engine_exception (eng
, pptr
, mala_stringlistnode_prev (end
),
308 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
310 MALA_SIDEEFFECT_BEGIN
312 //list = mala_stringlist_new ();
314 // return MALA_EALLOC;
316 // copy the block content to list
317 for (itr
= mala_stringlistnode_next (mala_program_pos (prg
)); itr
!= end
; mala_stringlistnode_fwd (&itr
))
318 if (!mala_stringlist_tail_new (list
, mala_stringlistnode_string (itr
)))
322 MalaParserFunc parser
;
325 mala_macrocheck_list (list
, &max_arg
, argt
);
330 parser
= mala_expand_parser
;
333 else if (max_arg
> 0)
336 parser
= mala_macro_parser
;
341 mala_stringlist_free (list
);
342 //TODO review mala_string_free (name);
343 return mala_engine_exception (eng
, pptr
, end
,
344 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
347 // allocate new block name
348 do { /* ..while name is in use */
349 //mala_string_free (name); /*TODO review in case we need to loop*/
350 name
= mala_string_new_print (&eng
->words
, NULL
/*TODO refs*/, templ
, ++eng
->blockcnt
);
353 } while (0); // TODO (mala_actiondesc_top ((MalaActionDesc)mala_string_user_get (name)));
355 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
357 NULL
, NULL
/*TODO refs*/))
359 // insert new --X_nnn... in program
360 //if (!mala_stringlist_after_new (&eng->program, end, name))
362 // TODO review mala_string_free (name);
363 // TODO review mala_string_free (name); // once more since blocks are self-deleting after used
367 //TODO --PROGRAM if (!mala_stringlist_after_new (&eng->program,
369 // eng->common_string[MALA_STRING_PASS]))
374 // and remove definition
375 //TODO --PROGRAM while (mala_program_pos (prg) != end)
376 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
378 //mala_stringlist_elem_delete_fwd (&eng->program, pptr);
386 #if 0 //old block_parser
388 mala_block_parser (MalaProgram prg
,
391 MalaStringListNode itr
;
392 MalaStringListNode end
;
394 MALA_SIDEEFFECT_BEGIN
396 end
= mala_stringlistnode_next (mala_program_pos (prg
));
398 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
399 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
400 mala_stringlistnode_rev (&itr
))
402 #if 0 // TODO --PROGRAM
403 if (!mala_stringlist_after_new (&eng
->program
, mala_program_pos (prg
),
404 mala_stringlistnode_string (itr
)))
411 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_program_pos (prg
)));
412 mala_engine_command_done (eng
, pptr
, 0);
413 return MALA_CONTINUE
;
416 /* remove already added things */
418 for (itr
= mala_stringlistnode_next (mala_program_pos (prg
));
420 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
426 #if 0 // old macrodelete_parser
428 mala_macrodelete_parser (MalaProgram prg
, void * data
)
432 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
);
434 MALA_SIDEEFFECT_BEGIN
436 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
437 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
438 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
440 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_stringlistnode_next (mala_program_pos (prg
))));
444 mala_engine_command_done (eng
, pptr
, 1);
447 #endif // old macrodelete
450 mala_delete_parser (MalaProgram prg
, void * data
)
454 //mala_engine_arg_eval (eng, pptr, 1, MALA_LITERAL);
456 MALA_SIDEEFFECT_BEGIN
458 #if 0 // TODO --PROGRAM
459 if (mala_stringlist_is_tail (&eng
->program
, mala_program_pos (prg
)))
460 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
461 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
463 // TODO mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_stringlistnode_next (mala_program_pos (prg))));
467 mala_program_action_done (prg
, 1);
474 mala_end_parser (MalaProgram prg
,
479 return mala_engine_exception (eng
, pptr
, mala_program_pos (prg
),
480 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
486 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10])
488 MalaStringListNode itr
;
489 for (itr
= mala_stringlist_head (list
);
490 !mala_stringlist_is_end (list
, itr
);
491 mala_stringlistnode_fwd (&itr
))
493 mala_macrocheck_string (mala_stringlistnode_string (itr
), max_arg
, argt
);
500 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10])
503 for (c
= mala_string_cstr (string
); *c
; ++c
)
517 if (*c
>= '0' && *c
<= '9')
520 if (argt
[*c
- '0'] == 1)
522 if (*c
> (char) *max_arg
+ '0')
529 else if (*c
>= '0' && *c
<= '9')
532 if (argt
[*c
- '0'] == -1)
534 if (*c
> (char) *max_arg
+ '0')
550 #if 0 // old macrodef parser
552 mala_macrodef_parser (MalaProgram prg
,
556 MalaStringListNode itr
;
557 MalaStringListNode arg
[2];
563 // evaluate both args
564 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
, NULL
))
566 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
, mala_block_parser
))
569 MALA_SIDEEFFECT_BEGIN
571 // test if 2 arguments left and assign them to arg[], else error
572 for (i
= 0, itr
= mala_program_pos (prg
); i
<2; ++i
, mala_stringlistnode_fwd(&itr
))
574 #if 0 // TODO --PROGRAM
575 if (mala_stringlist_is_tail (&eng
->program
, itr
))
576 return mala_engine_exception (eng
, pptr
, itr
,
577 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
580 arg
[i
] = mala_stringlistnode_next (itr
);
583 // if name is a block then error
584 name
= mala_stringlistnode_string (arg
[0]);
585 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
586 if (act
&& act
->parser
== mala_block_parser
)
587 return mala_engine_exception (eng
, pptr
, arg
[0],
588 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
590 //expansion check and optimize block
591 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
592 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
596 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
597 // convert block to expansion
602 desc
= mala_actiondesc_ensure (name
);
606 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
608 act
->parser
= mala_macro_parser
;
609 mala_actiondesc_push_action (desc
, act
);
611 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
615 subst
= mala_stringlist_head_string_copy ((MalaStringList
) act
->data
);
617 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
618 mala_substitute_parser
,
619 (MalaDataFactory
) mala_string_factory
,
623 mala_action_free(act
);
625 else if (max_arg
== 0)
629 desc
= mala_actiondesc_ensure (name
);
633 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
635 act
->parser
= mala_expand_parser
;
636 mala_actiondesc_push_action (desc
, act
);
639 return mala_engine_exception (eng
, pptr
, arg
[1],
640 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
642 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
647 mala_macrocheck_string (mala_stringlistnode_string (arg
[1]), &max_arg
, argt
);
651 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
652 mala_stringlistnode_string_copy (arg
[1]),
653 mala_substitute_parser
,
654 (MalaDataFactory
) mala_string_factory
,
658 else if (max_arg
> 0)
663 list
= mala_stringlist_new ();
667 mala_stringlist_tail_new (list
, mala_stringlistnode_string (arg
[1]));
669 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
671 (MalaDataFactory
) mala_stringlist_factory
,
676 return mala_engine_exception (eng
, pptr
, arg
[1],
677 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
682 mala_engine_command_done (eng
, pptr
, 2);
685 #endif //old macordef_parser
689 mala_def_parser (MalaProgram prg
,
692 MalaStringListNode dest
;
693 MalaStringListNode subst
;
699 // evaluate both args
700 dest
= mala_engine_arg_eval (eng
, pptr
, 1, MALA_LITERAL
);
704 subst
= mala_engine_arg_eval (eng
, pptr
, 2, MALA_MACRO
);
710 info bei HELP/RESULT_TYPE ob was ein PREDICATE, EXPANSION, LITERAL oder BLOCK ist
713 MALA_SIDEEFFECT_BEGIN
718 mala_macrocheck_string (mala_stringlistnode_string (subst
), &max_arg
, argt
);
722 str
= NULL
; // TODO mala_stringlistnode_string_copy (subst);
724 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
725 mala_stringlistnode_string (dest
),
727 mala_substitute_parser
,
728 NULL
, //TODO (MalaDataFactory) mala_string_factory,
734 else if (max_arg
> 0)
737 list
= mala_stringlist_new ();
741 if (! mala_stringlist_tail_new (list
, mala_stringlistnode_string (subst
)))
745 if (MALA_SUCCESS
!= mala_engine_add_action (eng
,
746 mala_stringlistnode_string (dest
),
749 NULL
, NULL
/*TODO refs*/))
750 goto ealloc_list_action
;
754 return mala_engine_exception (eng
, pptr
, subst
,
755 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
759 mala_engine_command_done (eng
, pptr
, 2);
760 return MALA_CONTINUE
;
762 // ealloc_list_action:
764 mala_stringlist_free (list
);
768 // TODO review mala_string_free (str);
775 realloc a string to at least needed size
776 return the amount really reserved or 0 on error
778 #if 0 // TODO acogc reserve!
780 reserve_string (char ** s
, size_t actual
, size_t needed
)
785 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
790 /* that was to much, try conservatively */
791 r
= realloc (*s
, n
= needed
);
801 mala_module_std_macros_init (MalaEngine self
)
803 return mala_engine_actions_register (self
, std_macros
);
809 // c-file-style: "gnu"
811 // arch-tag: 4722e09b-a020-4206-9ecc-9442505826c5