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 reserve_string (char ** s
, size_t actual
, size_t needed
);
31 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10]);
34 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10]);
38 mala_substitute_parser (MalaEngine eng
,
39 MalaStringListNode_ref pptr
,
45 mala_stringlistnode_substitute_string (*pptr
, (MalaString
) data
);
52 mala_expand_parser (MalaEngine eng
,
53 MalaStringListNode_ref pptr
,
56 MalaStringListNode itr
;
57 MalaStringListNode end
;
61 end
= mala_stringlistnode_next (*pptr
);
63 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
64 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
65 mala_stringlistnode_rev (&itr
))
67 if (!mala_stringlist_after_new (&eng
->program
, *pptr
,
68 mala_stringlistnode_string (itr
)))
74 mala_engine_command_done (eng
, pptr
, 0);
78 /* remove already added things */
79 for (itr
= mala_stringlistnode_next (*pptr
);
81 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
88 mala_macro_parser (MalaEngine eng
,
89 MalaStringListNode_ref pptr
,
92 MalaStringListNode itr
;
93 MalaStringListNode last
= NULL
;
101 MalaString str
= NULL
;
103 // scan how much args are needed
104 mala_macrocheck_list ((MalaStringList
) data
, &max_arg
, argt
);
106 // evaluate args, fill arg-array
107 args
[0] = mala_stringlistnode_string (*pptr
);
109 for (i
= 1; i
<= max_arg
; ++i
)
111 if (!(last
= mala_engine_arg_eval (eng
, pptr
, i
, argt
[i
] == 1 ? -1 : 0, NULL
))
112 || eng
->state
> MALA_EFAULT
)
115 args
[i
] = mala_stringlistnode_string (last
);
118 MALA_SIDEEFFECT_BEGIN
120 // build list with substitutions
121 list
= mala_stringlist_new ();
125 for (itr
= mala_stringlist_head ((MalaStringList
) data
);
126 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
127 mala_stringlistnode_fwd (&itr
))
130 if (!(p
= malloc (size
)))
133 for (c
= mala_string_cstr (mala_stringlistnode_string (itr
)), i
= 0; *c
; ++c
,++i
)
143 else if (*c
>= '0' && *c
<= '9')
146 if (size
<= i
+mala_string_length (args
[*c
-'0'])
147 && !(size
= reserve_string (&p
,
149 1 + i
+ mala_string_length (args
[*c
-'0']))))
151 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
152 i
+= (mala_string_length (args
[*c
-'0']) - 1);
157 if (*c
>= '0' && *c
<= '9')
160 if (size
<= i
+mala_string_length (args
[*c
-'0'])
161 && !(size
= reserve_string (&p
,
164 mala_string_length (args
[*c
-'0']))))
166 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
167 i
+= (mala_string_length (args
[*c
-'0']) - 1);
175 if (size
<= (size_t) i
&& !(size
= reserve_string (&p
, size
, (size_t) i
+1)))
184 if (!(ptmp
= realloc (p
, size
)))
187 str
= mala_string_new_cstr_attach (ptmp
, &eng
->words
);
191 if (!mala_stringlist_tail_new (list
, str
))
194 mala_string_free (str
);
199 for (itr
= mala_stringlist_tail (list
);
200 !mala_stringlist_is_end (list
, itr
);
201 mala_stringlistnode_rev (&itr
))
203 if (!mala_stringlist_after_new (&eng
->program
, last
,
204 mala_stringlistnode_string (itr
)))
209 mala_stringlist_free (list
);
214 mala_engine_command_done (eng
, pptr
, max_arg
);
215 return MALA_CONTINUE
;
219 mala_string_free (str
);
225 mala_stringlist_free (list
);
231 mala_defined_parser (MalaEngine eng
,
232 MalaStringListNode_ref pptr
,
235 MalaStringListNode result
;
240 result
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
244 MALA_SIDEEFFECT_BEGIN
246 desc
= (MalaActionDesc
) mala_stringlistnode_user_get (result
);
248 mala_engine_command_done (eng
, pptr
, 1);
250 if (desc
&& mala_actiondesc_top (desc
))
265 mala_if_parser (MalaEngine eng
,
266 MalaStringListNode_ref pptr
,
269 MalaStringListNode result
;
271 /*TODO negated, blocks, parse long double 0.0 as false*/
275 result
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
279 MALA_SIDEEFFECT_BEGIN
281 if (eng
->state
== MALA_LITERAL
)
283 if (mala_engine_string_istrue (eng
, mala_stringlistnode_string (result
)))
284 eng
->state
= MALA_SUCCESS
;
286 eng
->state
= MALA_FAILURE
;
291 if (eng
->state
== MALA_FAILURE
)
292 eng
->state
= MALA_REMOVE
;
294 result
= mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
);
298 if (eng
->state
== MALA_REMOVE
)
299 eng
->state
= MALA_FAILURE
;
303 if (eng
->state
== MALA_LITERAL
)
304 mala_engine_command_done (eng
, pptr
, 1);
306 mala_engine_command_done (eng
, pptr
, 2);
311 mala_pass_parser (MalaEngine eng
,
312 MalaStringListNode_ref pptr
,
317 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
323 mala_trace_parser (MalaEngine eng
,
324 MalaStringListNode_ref pptr
,
329 MALA_SIDEEFFECT_BEGIN
330 eng
->trace
= !eng
->negated
;
333 mala_engine_command_done (eng
, pptr
, 0);
337 /*TODO to predicates*/
339 mala_predicate_greaterorequal_double (double * a
, double * b
)
345 mala_sleep_parser (MalaEngine eng
,
346 MalaStringListNode_ref pptr
,
355 if (mala_engine_arg_eval_fmt (eng
, pptr
, 1, "%lf", &duration
,
356 (MalaPredicate
) mala_predicate_greaterorequal_double
, &zero
360 MALA_SIDEEFFECT_BEGIN
362 req
.tv_sec
= (time_t) duration
;
363 req
.tv_nsec
= (long) 1000000000 * (duration
- ((double) req
.tv_sec
));
365 (void) nanosleep (&req
, NULL
);
369 mala_engine_command_done (eng
, pptr
, 1);
374 mala_literal_parser (MalaEngine eng
,
375 MalaStringListNode_ref pptr
,
380 MALA_SIDEEFFECT_BEGIN
382 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
383 return mala_engine_exception (eng
, pptr
, *pptr
,
384 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
388 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
393 mala_not_parser (MalaEngine eng
,
394 MalaStringListNode_ref pptr
,
399 MALA_SIDEEFFECT_BEGIN
401 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
402 return mala_engine_exception (eng
, pptr
, *pptr
,
403 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
404 } /*TODO remove unfinished*/
407 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
408 eng
->negated
= !eng
->negated
;
409 return MALA_SUCCESS
; /*TODO*/
413 mala_begin_parser (MalaEngine eng
,
414 MalaStringListNode_ref pptr
,
417 MalaStringListNode itr
;
418 MalaStringListNode end
;
421 MalaString name
= NULL
;
425 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
426 return mala_engine_exception (eng
, pptr
, *pptr
,
427 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
429 // find matching --END
430 for (end
= mala_stringlistnode_next (*pptr
);
431 !mala_stringlist_is_end (&eng
->program
, end
);
432 mala_stringlistnode_fwd (&end
))
434 if (mala_string_same(mala_stringlistnode_string (end
),
435 eng
->common_string
[MALA_STRING_BEGIN
]))
437 else if (mala_string_same(mala_stringlistnode_string (end
),
438 eng
->common_string
[MALA_STRING_END
]))
445 return mala_engine_exception (eng
, pptr
, mala_stringlistnode_prev (end
),
446 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
448 MALA_SIDEEFFECT_BEGIN
450 list
= mala_stringlist_new ();
454 // copy the block content to list
455 for (itr
= mala_stringlistnode_next (*pptr
); itr
!= end
; mala_stringlistnode_fwd (&itr
))
456 if (!mala_stringlist_tail_new (list
, mala_stringlistnode_string (itr
)))
459 // allocate new block name
461 mala_string_free (name
);
462 name
= mala_string_new_print (&eng
->words
, "--BLOCK_%08X", ++eng
->blockcnt
);
465 } while (mala_actiondesc_top ((MalaActionDesc
)mala_string_user_get (name
)));
467 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
469 (MalaDataFactory
)mala_stringlist_factory
,
473 // insert new --BLOCK_... in program
474 if (!mala_stringlist_after_new (&eng
->program
, end
, name
))
476 mala_string_free (name
);
480 if (!mala_stringlist_after_new (&eng
->program
,
482 eng
->common_string
[MALA_STRING_PASS
]))
487 // and remove definition
489 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
491 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
496 mala_string_free (name
);
499 mala_stringlist_free (list
);
505 mala_block_parser (MalaEngine eng
,
506 MalaStringListNode_ref pptr
,
510 /*TODO expand instead?*/
511 MALA_SIDEEFFECT_BEGIN
512 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (*pptr
));
515 mala_engine_command_done (eng
, pptr
, 0);
520 mala_macrodelete_parser (MalaEngine eng
,
521 MalaStringListNode_ref pptr
,
526 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
528 MALA_SIDEEFFECT_BEGIN
530 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
531 return mala_engine_exception (eng
, pptr
, *pptr
,
532 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
534 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_stringlistnode_next (*pptr
)));
538 mala_engine_command_done (eng
, pptr
, 1);
543 mala_exception_parser (MalaEngine eng
,
544 MalaStringListNode_ref pptr
,
547 // TODO needs better semantics --EXCEPTION n error -> --ERROR-error 1 .. n --HERE
551 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
553 //TODO MALA_SIDEEFFECT_BEGIN
555 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
556 return mala_engine_exception (eng
, pptr
, *pptr
,
557 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
559 if (eng
->state
> MALA_EFAULT
)
562 MalaString ex
= mala_string_new_print (&eng
->words
, "--ERROR-%s",
563 mala_stringlistnode_cstr (mala_stringlistnode_next (*pptr
)));
565 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
566 int state
= mala_engine_exception (eng
, pptr
, *pptr
, ex
);
567 mala_stringlist_elem_delete (&eng
->program
, mala_stringlistnode_next (*pptr
));
569 mala_string_free (ex
);
570 // MALA_SIDEEFFECT_END;
576 mala_end_parser (MalaEngine eng
,
577 MalaStringListNode_ref pptr
,
582 return mala_engine_exception (eng
, pptr
, *pptr
,
583 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
587 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10])
589 MalaStringListNode itr
;
590 for (itr
= mala_stringlist_head (list
);
591 !mala_stringlist_is_end (list
, itr
);
592 mala_stringlistnode_fwd (&itr
))
594 mala_macrocheck_string (mala_stringlistnode_string (itr
), max_arg
, argt
);
601 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10])
604 for (c
= mala_string_cstr (string
); *c
; ++c
)
618 if (*c
>= '0' && *c
<= '9')
621 if (argt
[*c
- '0'] == 1)
623 if (*c
> (char) *max_arg
+ '0')
630 else if (*c
>= '0' && *c
<= '9')
633 if (argt
[*c
- '0'] == -1)
635 if (*c
> (char) *max_arg
+ '0')
651 mala_macrodef_parser (MalaEngine eng
,
652 MalaStringListNode_ref pptr
,
656 MalaStringListNode itr
;
657 MalaStringListNode arg
[2];
663 // evaluate both args
664 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
))
666 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
))
669 MALA_SIDEEFFECT_BEGIN
671 // test if 2 arguments left and assign them to arg[], else error
672 for (i
= 0, itr
= *pptr
; i
<2; ++i
, mala_stringlistnode_fwd(&itr
))
674 if (mala_stringlist_is_tail (&eng
->program
, itr
))
675 return mala_engine_exception (eng
, pptr
, itr
,
676 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
677 arg
[i
] = mala_stringlistnode_next (itr
);
680 // if name is a block then error
681 name
= mala_stringlistnode_string (arg
[0]);
682 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
683 if (act
&& act
->parser
== mala_block_parser
)
684 return mala_engine_exception (eng
, pptr
, arg
[0],
685 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
687 //expansion check and optimize block
688 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
689 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
693 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
694 // convert block to expansion
699 desc
= mala_actiondesc_ensure (name
);
703 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
705 act
->parser
= mala_macro_parser
;
706 mala_actiondesc_push_action (desc
, act
);
708 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
712 subst
= mala_stringlist_head_string_copy ((MalaStringList
) act
->data
);
714 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
715 mala_substitute_parser
,
716 (MalaDataFactory
) mala_string_factory
,
720 mala_action_free(act
);
722 else if (max_arg
== 0)
726 desc
= mala_actiondesc_ensure (name
);
730 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
732 act
->parser
= mala_expand_parser
;
733 mala_actiondesc_push_action (desc
, act
);
736 return mala_engine_exception (eng
, pptr
, arg
[1],
737 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
739 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
744 mala_macrocheck_string (mala_stringlistnode_string (arg
[1]), &max_arg
, argt
);
748 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
749 mala_stringlistnode_string_copy (arg
[1]),
750 mala_substitute_parser
,
751 (MalaDataFactory
) mala_string_factory
,
755 else if (max_arg
> 0)
760 list
= mala_stringlist_new ();
764 mala_stringlist_tail_new (list
, mala_stringlistnode_string (arg
[1]));
766 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
768 (MalaDataFactory
) mala_stringlist_factory
,
773 return mala_engine_exception (eng
, pptr
, arg
[1],
774 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
779 mala_engine_command_done (eng
, pptr
, 2);
784 mala_foreach_word_parser (MalaEngine eng
,
785 MalaStringListNode_ref pptr
,
789 MalaStringListNode first
;
790 MalaStringListNode second
;
791 MalaStringListNode last
;
792 MalaStringListNode itr
;
795 /*TODO bugs, rename to --APPLY fixit etc*/
797 first
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
800 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (first
));
801 // TODO allow blocks as first arg (define macro and delete it at later)
802 if (act
&& act
->parser
== mala_block_parser
)
803 return mala_engine_exception (eng
, pptr
, first
,
804 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
806 second
= mala_engine_arg_eval (eng
, pptr
, 2, -1, (MalaDataFactory
) mala_stringlist_factory
);
810 last
= mala_stringlistnode_next (second
);
812 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (second
));
815 if (eng
->state
!= MALA_LITERAL
)
816 for (itr
= mala_stringlist_tail ((MalaStringList
) act
->data
);
817 !mala_stringlist_is_end ((MalaStringList
) act
->data
, itr
);
818 mala_stringlistnode_rev (&itr
))
820 if (!mala_stringlist_after_new (&eng
->program
,
822 mala_stringlistnode_string (itr
)))
824 if (!mala_stringlist_after_new (&eng
->program
,
826 mala_stringlistnode_string (first
)))
831 if (!mala_stringlist_after_new (&eng
->program
,
833 mala_stringlistnode_string (second
)))
835 if (!mala_stringlist_after_new (&eng
->program
,
837 mala_stringlistnode_string (first
)))
842 // was a block? delete it
843 if (act
&& act
->parser
== mala_block_parser
)
844 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (second
));
846 mala_engine_command_done (eng
, pptr
, 2);
850 for (itr
= mala_stringlistnode_next (second
);
852 mala_stringlistnode_fwd (&itr
))
854 mala_stringlist_elem_delete (&eng
->program
, itr
);
857 return MALA_EALLOC
; // TODO exception instead (needs pools, no allocation possible further)
864 realloc a string to at least needed size
865 return the amount really reserved or 0 on error
868 reserve_string (char ** s
, size_t actual
, size_t needed
)
873 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
878 /* that was to much, try conservatively */
879 r
= realloc (*s
, n
= needed
);
891 // c-file-style: "gnu"
893 // arch-tag: 687e1195-8aad-4425-983d-9767a25c3793