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_newline_parser (MalaEngine eng
,
234 MalaStringListNode_ref pptr
,
239 if (eng
->state
> MALA_EFAULT
)
244 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
249 mala_print_parser (MalaEngine eng
,
250 MalaStringListNode_ref pptr
,
255 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
257 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
258 return mala_engine_exception (eng
, pptr
, *pptr
,
259 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
261 if (eng
->state
> MALA_EFAULT
)
264 // TODO print blocks ?
266 printf("%s",mala_string_cstr (mala_stringlist_next (*pptr
)->string
));
268 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
269 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
274 mala_literal_parser (MalaEngine eng
,
275 MalaStringListNode_ref pptr
,
280 if (eng
->state
> MALA_EFAULT
)
283 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
284 return mala_engine_exception (eng
, pptr
, *pptr
,
285 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
287 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
292 mala_not_parser (MalaEngine eng
,
293 MalaStringListNode_ref pptr
,
298 if (eng
->state
> MALA_EFAULT
)
301 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
302 return mala_engine_exception (eng
, pptr
, *pptr
,
303 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
305 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
306 eng
->negated
= !eng
->negated
;
311 mala_begin_parser (MalaEngine eng
,
312 MalaStringListNode_ref pptr
,
315 MalaStringListNode itr
;
316 MalaStringListNode end
;
319 MalaString name
= NULL
;
323 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
324 return mala_engine_exception (eng
, pptr
, *pptr
,
325 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
327 // find matching --END
328 for (end
= mala_stringlist_next (*pptr
);
329 !mala_stringlist_is_end (&eng
->program
, end
);
330 mala_stringlist_fwd (&end
))
332 if (mala_string_same(end
->string
, eng
->common_string
[MALA_STRING_BEGIN
]))
334 else if (mala_string_same(end
->string
, eng
->common_string
[MALA_STRING_END
]))
341 return mala_engine_exception (eng
, pptr
, mala_stringlist_prev (end
),
342 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
344 list
= mala_stringlist_new ();
348 // copy the block content to list
349 for (itr
= mala_stringlist_next (*pptr
); itr
!= end
; mala_stringlist_fwd (&itr
))
350 if (!mala_stringlist_tail_new (list
, itr
->string
))
353 // allocate new block name
355 mala_string_free (name
);
356 name
= mala_string_new_print (&eng
->words
, "--BLOCK_%08X", ++eng
->blockcnt
);
359 } while (mala_actiondesc_top ((MalaActionDesc
)mala_string_user_get (name
)));
361 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
363 (MalaDataFactory
)mala_stringlist_factory
,
367 // insert new --BLOCK_... in program
368 mala_stringlist_after_new (&eng
->program
, end
, name
);
369 mala_string_free (name
);
370 // and remove its definition
372 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
373 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
378 mala_string_free (name
);
381 mala_stringlist_free (list
);
386 mala_block_parser (MalaEngine eng
,
387 MalaStringListNode_ref pptr
,
392 if (eng
->state
> MALA_EFAULT
)
395 mala_actiondesc_pop_delete (mala_string_user_get ((*pptr
)->string
));
397 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
402 mala_macrodelete_parser (MalaEngine eng
,
403 MalaStringListNode_ref pptr
,
408 if (eng
->state
> MALA_EFAULT
)
411 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
413 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
414 return mala_engine_exception (eng
, pptr
, *pptr
,
415 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
417 mala_actiondesc_pop_delete (mala_string_user_get (mala_stringlist_next (*pptr
)->string
));
419 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
420 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
425 mala_exception_parser (MalaEngine eng
,
426 MalaStringListNode_ref pptr
,
429 // TODO needs better semantics --EXCEPTION n error -> --ERROR-error 1 .. n --HERE
433 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
435 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
436 return mala_engine_exception (eng
, pptr
, *pptr
,
437 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
439 if (eng
->state
> MALA_EFAULT
)
442 MalaString ex
= mala_string_new_print (&eng
->words
, "--ERROR-%s",
443 mala_string_cstr (mala_stringlist_next (*pptr
)->string
));
445 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
446 int state
= mala_engine_exception (eng
, pptr
, *pptr
, ex
);
447 mala_stringlist_elem_delete (&eng
->program
, mala_stringlist_next (*pptr
));
449 mala_string_free (ex
);
455 mala_end_parser (MalaEngine eng
,
456 MalaStringListNode_ref pptr
,
461 return mala_engine_exception (eng
, pptr
, *pptr
,
462 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
466 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10])
468 MalaStringListNode itr
;
469 for (itr
= mala_stringlist_head (list
);
470 !mala_stringlist_is_end (list
, itr
);
471 mala_stringlist_fwd (&itr
))
473 mala_macrocheck_string (itr
->string
, max_arg
, argt
);
480 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10])
483 for (c
= mala_string_cstr (string
); *c
; ++c
)
497 if (*c
>= '0' && *c
<= '9')
500 if (argt
[*c
- '0'] == 1)
502 if (*c
> (char) *max_arg
+ '0')
509 else if (*c
>= '0' && *c
<= '9')
512 if (argt
[*c
- '0'] == -1)
514 if (*c
> (char) *max_arg
+ '0')
530 mala_macrodef_parser (MalaEngine eng
,
531 MalaStringListNode_ref pptr
,
535 MalaStringListNode itr
;
536 MalaStringListNode arg
[2];
543 // evaluate both args
544 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
))
546 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
))
549 // test if 2 arguments left and assign them to arg[], else error
550 for (i
= 0, itr
= *pptr
; i
<2; ++i
, mala_stringlist_fwd(&itr
))
552 if (mala_stringlist_is_tail (&eng
->program
, itr
))
553 return mala_engine_exception (eng
, pptr
, itr
,
554 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
555 arg
[i
] = mala_stringlist_next (itr
);
558 // if name is a block then error
559 name
= arg
[0]->string
;
560 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
561 if (act
&& act
->parser
== mala_block_parser
)
562 return mala_engine_exception (eng
, pptr
, arg
[0],
563 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
565 //expansion check and optimize block
566 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
567 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
571 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
572 // convert block to expansion
577 desc
= mala_actiondesc_ensure (name
);
581 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
583 act
->parser
= mala_macro_parser
;
584 mala_actiondesc_push_action (desc
, act
);
586 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
590 subst
= mala_string_copy (mala_stringlist_head((MalaStringList
) act
->data
)->string
);
592 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
593 mala_substitute_parser
,
594 (MalaDataFactory
) mala_string_factory
,
598 mala_action_free(act
);
600 else if (max_arg
== 0)
604 desc
= mala_actiondesc_ensure (name
);
608 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_string_user_get (arg
[1]->string
));
610 act
->parser
= mala_expand_parser
;
611 mala_actiondesc_push_action (desc
, act
);
614 return mala_engine_exception (eng
, pptr
, arg
[1],
615 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
617 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
622 mala_macrocheck_string (arg
[1]->string
, &max_arg
, argt
);
626 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
627 mala_string_copy (arg
[1]->string
),
628 mala_substitute_parser
,
629 (MalaDataFactory
) mala_string_factory
,
633 else if (max_arg
> 0)
638 list
= mala_stringlist_new ();
642 mala_stringlist_tail_new (list
, arg
[1]->string
);
644 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
646 (MalaDataFactory
) mala_stringlist_factory
,
651 return mala_engine_exception (eng
, pptr
, arg
[1],
652 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
655 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
656 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
657 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
662 mala_foreach_word_parser (MalaEngine eng
,
663 MalaStringListNode_ref pptr
,
667 MalaStringListNode first
;
668 MalaStringListNode second
;
669 MalaStringListNode last
;
670 MalaStringListNode itr
;
673 first
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
676 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (first
->string
));
677 // TODO allow blocks as first arg (define macro and delete it at later)
678 if (act
&& act
->parser
== mala_block_parser
)
679 return mala_engine_exception (eng
, pptr
, first
,
680 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
682 second
= mala_engine_arg_eval (eng
, pptr
, 2, -1, (MalaDataFactory
) mala_stringlist_factory
);
686 last
= mala_stringlist_next (second
);
688 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (second
->string
));
691 if (eng
->state
!= MALA_LITERAL
)
692 for (itr
= mala_stringlist_tail ((MalaStringList
) act
->data
);
693 !mala_stringlist_is_end ((MalaStringList
) act
->data
, itr
);
694 mala_stringlist_rev (&itr
))
696 if (!mala_stringlist_after_new (&eng
->program
, second
, itr
->string
))
698 if (!mala_stringlist_after_new (&eng
->program
, second
, first
->string
))
703 if (!mala_stringlist_after_new (&eng
->program
, second
, second
->string
))
705 if (!mala_stringlist_after_new (&eng
->program
, second
, first
->string
))
710 // was a block? delete it
711 if (act
&& act
->parser
== mala_block_parser
)
712 mala_actiondesc_pop_delete (mala_string_user_get (second
->string
));
714 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
715 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
716 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
720 for (itr
= mala_stringlist_next (second
);
722 mala_stringlist_fwd (&itr
))
724 mala_stringlist_elem_delete (&eng
->program
, itr
);
727 return MALA_EALLOC
; // TODO exception instead (needs pools, no allocation possible further)
734 realloc a string to at least needed size
735 return the amount really reserved or 0 on error
738 reserve_string (char ** s
, size_t actual
, size_t needed
)
743 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
748 /* that was to much, try conservatively */
749 r
= realloc (*s
, n
= needed
);
761 // c-file-style: "gnu"
763 // arch-tag: 687e1195-8aad-4425-983d-9767a25c3793