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.
27 reserve_string (char ** s
, size_t actual
, size_t needed
);
30 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10]);
33 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10]);
37 mala_substitute_parser (MalaEngine eng
,
38 MalaStringListNode_ref pptr
,
41 if (!mala_stringlist_after_new (&eng
->program
, *pptr
, (MalaString
) data
))
44 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
50 mala_expand_parser (MalaEngine eng
,
51 MalaStringListNode_ref pptr
,
54 MalaStringListNode itr
;
55 MalaStringListNode end
;
57 end
= mala_stringlist_next (*pptr
);
59 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
60 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
61 mala_stringlist_rev (&itr
))
63 if (!mala_stringlist_after_new (&eng
->program
, *pptr
, itr
->string
))
67 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
72 /* remove already added things */
73 for (itr
= mala_stringlist_next (*pptr
);
75 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
82 mala_macro_parser (MalaEngine eng
,
83 MalaStringListNode_ref pptr
,
86 MalaStringListNode itr
;
87 MalaStringListNode last
= NULL
;
95 MalaString str
= NULL
;
98 // scan how much args are needed
99 mala_macrocheck_list ((MalaStringList
) data
, &max_arg
, argt
);
101 // evaluate args, fill arg-array
102 args
[0] = (*pptr
)->string
;
104 for (i
= 1; i
<= max_arg
; ++i
)
106 if (!(last
= mala_engine_arg_eval (eng
, pptr
, i
, argt
[i
] == 1 ? -1 : 0, NULL
))
107 || eng
->state
> MALA_EFAULT
)
110 args
[i
] = last
->string
;
113 // build list with substitutions
114 list
= mala_stringlist_new ();
118 for (itr
= mala_stringlist_head ((MalaStringList
) data
);
119 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
120 mala_stringlist_fwd (&itr
))
123 if (!(p
= malloc (size
)))
126 for (c
= mala_string_cstr (itr
->string
), i
= 0; *c
; ++c
,++i
)
136 else if (*c
>= '0' && *c
<= '9')
139 if (size
<= i
+mala_string_length (args
[*c
-'0'])
140 && !(size
= reserve_string (&p
,
142 1 + i
+ mala_string_length (args
[*c
-'0']))))
144 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
145 i
+= (mala_string_length (args
[*c
-'0']) - 1);
150 if (*c
>= '0' && *c
<= '9')
153 if (size
<= i
+mala_string_length (args
[*c
-'0'])
154 && !(size
= reserve_string (&p
,
157 mala_string_length (args
[*c
-'0']))))
159 strcpy(p
+i
, mala_string_cstr (args
[*c
-'0']));
160 i
+= (mala_string_length (args
[*c
-'0']) - 1);
168 if (size
<= (size_t) i
&& !(size
= reserve_string (&p
, size
, (size_t) i
+1)))
177 if (!(ptmp
= realloc (p
, size
)))
180 str
= mala_string_new_cstr_attach (ptmp
, &eng
->words
); /*TODO try without bucket?*/
184 if (!mala_stringlist_tail_new (list
, str
))
187 mala_string_free (str
);
192 for (itr
= mala_stringlist_tail (list
);
193 !mala_stringlist_is_end (list
, itr
);
194 mala_stringlist_rev (&itr
))
196 if (!mala_stringlist_after_new (&eng
->program
, last
, itr
->string
))
201 mala_stringlist_free (list
);
204 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
211 mala_string_free (str
);
217 mala_stringlist_free (list
);
223 mala_null_parser (MalaEngine eng
,
224 MalaStringListNode_ref pptr
,
228 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
233 mala_printl_parser (MalaEngine eng
,
234 MalaStringListNode_ref pptr
,
239 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
241 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
242 return mala_engine_exception (eng
, pptr
, *pptr
,
243 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
245 if (eng
->state
> MALA_EFAULT
)
248 // TODO print blocks ?
250 printf("%s\n",mala_string_cstr (mala_stringlist_next (*pptr
)->string
));
252 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
253 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
258 mala_print_parser (MalaEngine eng
,
259 MalaStringListNode_ref pptr
,
264 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
266 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
267 return mala_engine_exception (eng
, pptr
, *pptr
,
268 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
270 if (eng
->state
> MALA_EFAULT
)
273 // TODO print blocks ?
275 printf("%s",mala_string_cstr (mala_stringlist_next (*pptr
)->string
));
277 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
278 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
283 mala_literal_parser (MalaEngine eng
,
284 MalaStringListNode_ref pptr
,
289 if (eng
->state
> MALA_EFAULT
)
292 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
293 return mala_engine_exception (eng
, pptr
, *pptr
,
294 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
296 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
301 mala_not_parser (MalaEngine eng
,
302 MalaStringListNode_ref pptr
,
307 if (eng
->state
> MALA_EFAULT
)
310 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
311 return mala_engine_exception (eng
, pptr
, *pptr
,
312 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
314 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
315 eng
->negated
= !eng
->negated
;
320 mala_begin_parser (MalaEngine eng
,
321 MalaStringListNode_ref pptr
,
324 MalaStringListNode itr
;
325 MalaStringListNode end
;
328 MalaString name
= NULL
;
332 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
333 return mala_engine_exception (eng
, pptr
, *pptr
,
334 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
336 // find matching --END
337 for (end
= mala_stringlist_next (*pptr
);
338 !mala_stringlist_is_end (&eng
->program
, end
);
339 mala_stringlist_fwd (&end
))
341 if (mala_string_same(end
->string
, eng
->common_string
[MALA_STRING_BEGIN
]))
343 else if (mala_string_same(end
->string
, eng
->common_string
[MALA_STRING_END
]))
350 return mala_engine_exception (eng
, pptr
, mala_stringlist_prev (end
),
351 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
353 list
= mala_stringlist_new ();
357 // copy the block content to list
358 for (itr
= mala_stringlist_next (*pptr
); itr
!= end
; mala_stringlist_fwd (&itr
))
359 if (!mala_stringlist_tail_new (list
, itr
->string
))
362 // allocate new block name
364 mala_string_free (name
);
365 name
= mala_string_new_print (&eng
->words
, "--BLOCK_%08X", ++eng
->blockcnt
);
368 } while (mala_actiondesc_top ((MalaActionDesc
)mala_string_user_get (name
)));
370 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
372 (MalaDataFactory
)mala_stringlist_factory
,
376 // insert new --BLOCK_... in program
377 mala_stringlist_after_new (&eng
->program
, end
, name
);
378 mala_string_free (name
);
379 // and remove its definition
381 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
382 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
387 mala_string_free (name
);
390 mala_stringlist_free (list
);
395 mala_block_parser (MalaEngine eng
,
396 MalaStringListNode_ref pptr
,
401 if (eng
->state
> MALA_EFAULT
)
404 mala_actiondesc_pop_delete (mala_string_user_get ((*pptr
)->string
));
406 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
411 mala_macrodelete_parser (MalaEngine eng
,
412 MalaStringListNode_ref pptr
,
417 if (eng
->state
> MALA_EFAULT
)
420 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
422 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
423 return mala_engine_exception (eng
, pptr
, *pptr
,
424 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
426 mala_actiondesc_pop_delete (mala_string_user_get (mala_stringlist_next (*pptr
)->string
));
428 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
429 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
434 mala_exception_parser (MalaEngine eng
,
435 MalaStringListNode_ref pptr
,
438 // TODO needs better semantics --EXCEPTION n error -> --ERROR-error 1 .. n --HERE
442 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
444 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
445 return mala_engine_exception (eng
, pptr
, *pptr
,
446 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
448 if (eng
->state
> MALA_EFAULT
)
451 MalaString ex
= mala_string_new_print (&eng
->words
, "--ERROR-%s",
452 mala_string_cstr (mala_stringlist_next (*pptr
)->string
));
454 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
455 int state
= mala_engine_exception (eng
, pptr
, *pptr
, ex
);
456 mala_stringlist_elem_delete (&eng
->program
, mala_stringlist_next (*pptr
));
458 mala_string_free (ex
);
464 mala_end_parser (MalaEngine eng
,
465 MalaStringListNode_ref pptr
,
470 return mala_engine_exception (eng
, pptr
, *pptr
,
471 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
475 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10])
477 MalaStringListNode itr
;
478 for (itr
= mala_stringlist_head (list
);
479 !mala_stringlist_is_end (list
, itr
);
480 mala_stringlist_fwd (&itr
))
482 mala_macrocheck_string (itr
->string
, max_arg
, argt
);
489 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10])
492 for (c
= mala_string_cstr (string
); *c
; ++c
)
506 if (*c
>= '0' && *c
<= '9')
509 if (argt
[*c
- '0'] == 1)
511 if (*c
> (char) *max_arg
+ '0')
518 else if (*c
>= '0' && *c
<= '9')
521 if (argt
[*c
- '0'] == -1)
523 if (*c
> (char) *max_arg
+ '0')
539 mala_macrodef_parser (MalaEngine eng
,
540 MalaStringListNode_ref pptr
,
544 MalaStringListNode itr
;
545 MalaStringListNode arg
[2];
552 // evaluate both args
553 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
))
555 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
))
558 // test if 2 arguments left and assign them to arg[], else error
559 for (i
= 0, itr
= *pptr
; i
<2; ++i
, mala_stringlist_fwd(&itr
))
561 if (mala_stringlist_is_tail (&eng
->program
, itr
))
562 return mala_engine_exception (eng
, pptr
, itr
,
563 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
564 arg
[i
] = mala_stringlist_next (itr
);
567 // if name is a block then error
568 name
= arg
[0]->string
;
569 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
570 if (act
&& act
->parser
== mala_block_parser
)
571 return mala_engine_exception (eng
, pptr
, arg
[0],
572 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
574 //expansion check and optimize block
575 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
576 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
580 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
581 // convert block to expansion
586 desc
= mala_actiondesc_ensure (name
);
590 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
592 act
->parser
= mala_macro_parser
;
593 mala_actiondesc_push_action (desc
, act
);
595 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
599 subst
= mala_string_copy (mala_stringlist_head((MalaStringList
) act
->data
)->string
);
601 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
602 mala_substitute_parser
,
603 (MalaDataFactory
) mala_string_factory
,
607 mala_action_free(act
);
609 else if (max_arg
== 0)
613 desc
= mala_actiondesc_ensure (name
);
617 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
619 act
->parser
= mala_expand_parser
;
620 mala_actiondesc_push_action (desc
, act
);
623 return mala_engine_exception (eng
, pptr
, arg
[1],
624 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
626 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
631 mala_macrocheck_string (arg
[1]->string
, &max_arg
, argt
);
635 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
636 mala_string_copy (arg
[1]->string
),
637 mala_substitute_parser
,
638 (MalaDataFactory
) mala_string_factory
,
642 else if (max_arg
> 0)
647 list
= mala_stringlist_new ();
651 mala_stringlist_tail_new (list
, arg
[1]->string
);
653 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
655 (MalaDataFactory
) mala_stringlist_factory
,
660 return mala_engine_exception (eng
, pptr
, arg
[1],
661 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
664 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
665 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
666 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
671 mala_foreach_word_parser (MalaEngine eng
,
672 MalaStringListNode_ref pptr
,
676 MalaStringListNode first
;
677 MalaStringListNode second
;
678 MalaStringListNode last
;
679 MalaStringListNode itr
;
682 first
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
685 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (first
->string
));
686 // TODO allow blocks as first arg (define macro and delete it at later)
687 if (act
&& act
->parser
== mala_block_parser
)
688 return mala_engine_exception (eng
, pptr
, first
,
689 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
691 second
= mala_engine_arg_eval (eng
, pptr
, 2, -1, (MalaDataFactory
) mala_stringlist_factory
);
695 last
= mala_stringlist_next (second
);
697 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (second
->string
));
700 if (eng
->state
!= MALA_LITERAL
)
701 for (itr
= mala_stringlist_tail ((MalaStringList
) act
->data
);
702 !mala_stringlist_is_end ((MalaStringList
) act
->data
, itr
);
703 mala_stringlist_rev (&itr
))
705 if (!mala_stringlist_after_new (&eng
->program
, second
, itr
->string
))
707 if (!mala_stringlist_after_new (&eng
->program
, second
, first
->string
))
712 if (!mala_stringlist_after_new (&eng
->program
, second
, second
->string
))
714 if (!mala_stringlist_after_new (&eng
->program
, second
, first
->string
))
719 // was a block? delete it
720 if (act
&& act
->parser
== mala_block_parser
)
721 mala_actiondesc_pop_delete (mala_string_user_get (second
->string
));
723 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
724 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
725 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
729 for (itr
= mala_stringlist_next (second
);
731 mala_stringlist_fwd (&itr
))
733 mala_stringlist_elem_delete (&eng
->program
, itr
);
736 return MALA_EALLOC
; // TODO exception instead (needs pools, no allocation possible further)
743 realloc a string to at least needed size
744 return the amount really reserved or 0 on error
747 reserve_string (char ** s
, size_t actual
, size_t needed
)
752 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
757 /* that was to much, try conservatively */
758 r
= realloc (*s
, n
= needed
);
770 // c-file-style: "gnu"
772 // arch-tag: 687e1195-8aad-4425-983d-9767a25c3793