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_stringlistnode_next (*pptr
);
59 for (itr
= mala_stringlist_tail ((MalaStringList
) data
);
60 !mala_stringlist_is_end ((MalaStringList
) data
, itr
);
61 mala_stringlistnode_rev (&itr
))
63 if (!mala_stringlist_after_new (&eng
->program
, *pptr
,
64 mala_stringlistnode_string (itr
)))
68 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
73 /* remove already added things */
74 for (itr
= mala_stringlistnode_next (*pptr
);
76 mala_stringlist_elem_delete_fwd (&eng
->program
, &itr
));
83 mala_macro_parser (MalaEngine eng
,
84 MalaStringListNode_ref pptr
,
87 MalaStringListNode itr
;
88 MalaStringListNode last
= NULL
;
96 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] = mala_stringlistnode_string (*pptr
);
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
] = mala_stringlistnode_string (last
);
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_stringlistnode_fwd (&itr
))
123 if (!(p
= malloc (size
)))
126 for (c
= mala_string_cstr (mala_stringlistnode_string (itr
)), 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_stringlistnode_rev (&itr
))
196 if (!mala_stringlist_after_new (&eng
->program
, last
,
197 mala_stringlistnode_string (itr
)))
202 mala_stringlist_free (list
);
204 mala_stringlist_elem_delete_fwd_n (&eng
->program
, pptr
, max_arg
+ 1);
210 mala_string_free (str
);
216 mala_stringlist_free (list
);
222 mala_null_parser (MalaEngine eng
,
223 MalaStringListNode_ref pptr
,
227 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
232 mala_literal_parser (MalaEngine eng
,
233 MalaStringListNode_ref pptr
,
238 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
239 return mala_engine_exception (eng
, pptr
, *pptr
,
240 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
242 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
247 mala_not_parser (MalaEngine eng
,
248 MalaStringListNode_ref pptr
,
253 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
254 return mala_engine_exception (eng
, pptr
, *pptr
,
255 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
257 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
258 eng
->negated
= !eng
->negated
;
263 mala_begin_parser (MalaEngine eng
,
264 MalaStringListNode_ref pptr
,
267 MalaStringListNode itr
;
268 MalaStringListNode end
;
271 MalaString name
= NULL
;
275 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
276 return mala_engine_exception (eng
, pptr
, *pptr
,
277 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
279 // find matching --END
280 for (end
= mala_stringlistnode_next (*pptr
);
281 !mala_stringlist_is_end (&eng
->program
, end
);
282 mala_stringlistnode_fwd (&end
))
284 if (mala_string_same(mala_stringlistnode_string (end
),
285 eng
->common_string
[MALA_STRING_BEGIN
]))
287 else if (mala_string_same(mala_stringlistnode_string (end
),
288 eng
->common_string
[MALA_STRING_END
]))
295 return mala_engine_exception (eng
, pptr
, mala_stringlistnode_prev (end
),
296 eng
->common_string
[MALA_STRING_ERROR_MISSING_END
]);
298 list
= mala_stringlist_new ();
302 // copy the block content to list
303 for (itr
= mala_stringlistnode_next (*pptr
); itr
!= end
; mala_stringlistnode_fwd (&itr
))
304 if (!mala_stringlist_tail_new (list
, mala_stringlistnode_string (itr
)))
307 // allocate new block name
309 mala_string_free (name
);
310 name
= mala_string_new_print (&eng
->words
, "--BLOCK_%08X", ++eng
->blockcnt
);
313 } while (mala_actiondesc_top ((MalaActionDesc
)mala_string_user_get (name
)));
315 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
317 (MalaDataFactory
)mala_stringlist_factory
,
321 // insert new --BLOCK_... in program
322 mala_stringlist_after_new (&eng
->program
, end
, name
);
323 mala_string_free (name
);
324 // and remove its definition
326 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
327 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
332 mala_string_free (name
);
335 mala_stringlist_free (list
);
340 mala_block_parser (MalaEngine eng
,
341 MalaStringListNode_ref pptr
,
346 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (*pptr
));
348 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
353 mala_macrodelete_parser (MalaEngine eng
,
354 MalaStringListNode_ref pptr
,
359 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
361 if (mala_stringlist_is_tail (&eng
->program
, *pptr
))
362 return mala_engine_exception (eng
, pptr
, *pptr
,
363 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
365 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_stringlistnode_next (*pptr
)));
367 mala_stringlist_elem_delete_fwd_n (&eng
->program
, pptr
, 2);
372 mala_exception_parser (MalaEngine eng
,
373 MalaStringListNode_ref pptr
,
376 // TODO needs better semantics --EXCEPTION n error -> --ERROR-error 1 .. n --HERE
380 mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
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
]);
386 if (eng
->state
> MALA_EFAULT
)
389 MalaString ex
= mala_string_new_print (&eng
->words
, "--ERROR-%s",
390 mala_stringlistnode_cstr (mala_stringlistnode_next (*pptr
)));
392 mala_stringlist_elem_delete_fwd (&eng
->program
, pptr
);
393 int state
= mala_engine_exception (eng
, pptr
, *pptr
, ex
);
394 mala_stringlist_elem_delete (&eng
->program
, mala_stringlistnode_next (*pptr
));
396 mala_string_free (ex
);
402 mala_end_parser (MalaEngine eng
,
403 MalaStringListNode_ref pptr
,
408 return mala_engine_exception (eng
, pptr
, *pptr
,
409 eng
->common_string
[MALA_STRING_ERROR_END_WITHOUT_BEGIN
]);
413 mala_macrocheck_list (MalaStringList list
, int * max_arg
, int argt
[10])
415 MalaStringListNode itr
;
416 for (itr
= mala_stringlist_head (list
);
417 !mala_stringlist_is_end (list
, itr
);
418 mala_stringlistnode_fwd (&itr
))
420 mala_macrocheck_string (mala_stringlistnode_string (itr
), max_arg
, argt
);
427 mala_macrocheck_string (MalaString string
, int * max_arg
, int argt
[10])
430 for (c
= mala_string_cstr (string
); *c
; ++c
)
444 if (*c
>= '0' && *c
<= '9')
447 if (argt
[*c
- '0'] == 1)
449 if (*c
> (char) *max_arg
+ '0')
456 else if (*c
>= '0' && *c
<= '9')
459 if (argt
[*c
- '0'] == -1)
461 if (*c
> (char) *max_arg
+ '0')
477 mala_macrodef_parser (MalaEngine eng
,
478 MalaStringListNode_ref pptr
,
482 MalaStringListNode itr
;
483 MalaStringListNode arg
[2];
490 // evaluate both args
491 if (!mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
))
493 if (!mala_engine_arg_eval (eng
, pptr
, 2, -1, NULL
))
496 // test if 2 arguments left and assign them to arg[], else error
497 for (i
= 0, itr
= *pptr
; i
<2; ++i
, mala_stringlistnode_fwd(&itr
))
499 if (mala_stringlist_is_tail (&eng
->program
, itr
))
500 return mala_engine_exception (eng
, pptr
, itr
,
501 eng
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
502 arg
[i
] = mala_stringlistnode_next (itr
);
505 // if name is a block then error
506 name
= mala_stringlistnode_string (arg
[0]);
507 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (name
));
508 if (act
&& act
->parser
== mala_block_parser
)
509 return mala_engine_exception (eng
, pptr
, arg
[0],
510 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
512 //expansion check and optimize block
513 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
514 if (act
&& act
->factory
== (MalaDataFactory
) mala_stringlist_factory
)
518 mala_macrocheck_list ((MalaStringList
) act
->data
, &max_arg
, argt
);
519 // convert block to expansion
524 desc
= mala_actiondesc_ensure (name
);
528 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
530 act
->parser
= mala_macro_parser
;
531 mala_actiondesc_push_action (desc
, act
);
533 else if (mala_stringlist_is_single ((MalaStringList
) act
->data
))
537 subst
= mala_stringlist_head_string_copy ((MalaStringList
) act
->data
);
539 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, subst
,
540 mala_substitute_parser
,
541 (MalaDataFactory
) mala_string_factory
,
545 mala_action_free(act
);
547 else if (max_arg
== 0)
551 desc
= mala_actiondesc_ensure (name
);
555 act
= mala_actiondesc_pop ((MalaActionDesc
) mala_stringlistnode_user_get (arg
[1]));
557 act
->parser
= mala_expand_parser
;
558 mala_actiondesc_push_action (desc
, act
);
561 return mala_engine_exception (eng
, pptr
, arg
[1],
562 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
564 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
569 mala_macrocheck_string (mala_stringlistnode_string (arg
[1]), &max_arg
, argt
);
573 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
,
574 mala_stringlistnode_string_copy (arg
[1]),
575 mala_substitute_parser
,
576 (MalaDataFactory
) mala_string_factory
,
580 else if (max_arg
> 0)
585 list
= mala_stringlist_new ();
589 mala_stringlist_tail_new (list
, mala_stringlistnode_string (arg
[1]));
591 if (MALA_SUCCESS
!= mala_engine_add_action (eng
, name
, list
,
593 (MalaDataFactory
) mala_stringlist_factory
,
598 return mala_engine_exception (eng
, pptr
, arg
[1],
599 eng
->common_string
[MALA_STRING_ERROR_PARAMETER_SYNTAX
]);
602 mala_stringlist_elem_delete_fwd_n (&eng
->program
, pptr
, 3);
607 mala_foreach_word_parser (MalaEngine eng
,
608 MalaStringListNode_ref pptr
,
612 MalaStringListNode first
;
613 MalaStringListNode second
;
614 MalaStringListNode last
;
615 MalaStringListNode itr
;
618 first
= mala_engine_arg_eval (eng
, pptr
, 1, -1, NULL
);
621 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (first
));
622 // TODO allow blocks as first arg (define macro and delete it at later)
623 if (act
&& act
->parser
== mala_block_parser
)
624 return mala_engine_exception (eng
, pptr
, first
,
625 eng
->common_string
[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED
]);
627 second
= mala_engine_arg_eval (eng
, pptr
, 2, -1, (MalaDataFactory
) mala_stringlist_factory
);
631 last
= mala_stringlistnode_next (second
);
633 act
= mala_actiondesc_top ((MalaActionDesc
) mala_stringlistnode_user_get (second
));
636 if (eng
->state
!= MALA_LITERAL
)
637 for (itr
= mala_stringlist_tail ((MalaStringList
) act
->data
);
638 !mala_stringlist_is_end ((MalaStringList
) act
->data
, itr
);
639 mala_stringlistnode_rev (&itr
))
641 if (!mala_stringlist_after_new (&eng
->program
,
643 mala_stringlistnode_string (itr
)))
645 if (!mala_stringlist_after_new (&eng
->program
,
647 mala_stringlistnode_string (first
)))
652 if (!mala_stringlist_after_new (&eng
->program
,
654 mala_stringlistnode_string (second
)))
656 if (!mala_stringlist_after_new (&eng
->program
,
658 mala_stringlistnode_string (first
)))
663 // was a block? delete it
664 if (act
&& act
->parser
== mala_block_parser
)
665 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (second
));
667 mala_stringlist_elem_delete_fwd_n (&eng
->program
, pptr
, 3);
671 for (itr
= mala_stringlistnode_next (second
);
673 mala_stringlistnode_fwd (&itr
))
675 mala_stringlist_elem_delete (&eng
->program
, itr
);
678 return MALA_EALLOC
; // TODO exception instead (needs pools, no allocation possible further)
685 realloc a string to at least needed size
686 return the amount really reserved or 0 on error
689 reserve_string (char ** s
, size_t actual
, size_t needed
)
694 for (n
= actual
>64?actual
:64; n
<= needed
; n
+= (n
>>1)); /*n = n * 1.5*/
699 /* that was to much, try conservatively */
700 r
= realloc (*s
, n
= needed
);
712 // c-file-style: "gnu"
714 // arch-tag: 687e1195-8aad-4425-983d-9767a25c3793