mark function returns collection state
[mala.git] / std / std_functional.c
blobad33cd3928f31fd751d74fa12f485908ca94f696
1 /*
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.
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
24 #include "mala.h"
25 #include "std.h"
27 static size_t
28 reserve_string (char ** s, size_t actual, size_t needed);
30 static void
31 mala_macrocheck_list (MalaStringList list, int * max_arg, int argt[10]);
33 static void
34 mala_macrocheck_string (MalaString string, int * max_arg, int argt[10]);
37 #if 0
38 MALA_PARSER("--MAP", mala_map_parser, NULL, NULL, NULL),
39 MALA_PARSER_BRIEF("--MAP", "TODO applies an action to each element of a nested list"),
40 MALA_PARSER_HELP("--MAP", ("TODO")),
41 MALA_PARSER_SIGNATURE_TYPE("--FOREACH-WORD", ("DEFINED-ACTION", "MACRO-LIST")),
42 MALA_PARSER_SIGNATURE_USAGE("--FOREACH-WORD", ("Action to be applied",
43 "list of lists")),
44 MALA_PARSER_RESULT_TYPE("--MAP", ("SEQUENCE")),
45 MALA_PARSER_RESULT_USAGE("--MAP", ("Resulting Sequence")),
48 MALA_PARSER("--LENGTH", mala_length_parser, NULL, NULL, NULL),
49 MALA_PARSER_BRIEF("--LENGTH", "returns the length of a sequence"),
50 MALA_PARSER_HELP("--LENGTH", ("TODO")),
51 MALA_PARSER_SIGNATURE_TYPE("--LENGTH", ("SEQUENCE")),
52 MALA_PARSER_SIGNATURE_USAGE("--LENGTH", ("list of lists")),
53 MALA_PARSER_RESULT_TYPE("--LENGTH", ("INTEGER")),
54 MALA_PARSER_RESULT_USAGE("--LENGTH", ("Length of the Sequence")),
55 #endif
57 int
58 mala_substitute_parser (MalaEngine eng,
59 MalaStringListNode_ref pptr,
60 void * data)
62 (void) eng;
64 MALA_SIDEEFFECT_BEGIN
65 mala_stringlistnode_substitute_string (*pptr, (MalaString) data);
66 MALA_SIDEEFFECT_END;
68 return MALA_CONTINUE;
71 int
72 mala_expand_parser (MalaEngine eng,
73 MalaStringListNode_ref pptr,
74 void * data)
76 MalaStringListNode itr;
77 MalaStringListNode end;
79 MALA_SIDEEFFECT_BEGIN
81 end = mala_stringlistnode_next (*pptr);
83 for (itr = mala_stringlist_tail ((MalaStringList) data);
84 !mala_stringlist_is_end ((MalaStringList) data, itr);
85 mala_stringlistnode_rev (&itr))
87 if (!mala_stringlist_after_new (&eng->program, *pptr,
88 mala_stringlistnode_string (itr)))
89 goto ealloc_node;
92 MALA_SIDEEFFECT_END;
94 mala_engine_command_done (eng, pptr, 0);
95 return MALA_CONTINUE;
97 ealloc_node:
98 /* remove already added things */
99 for (itr = mala_stringlistnode_next (*pptr);
100 itr != end;
101 mala_stringlist_elem_delete_fwd (&eng->program, &itr));
103 return MALA_EALLOC;
108 mala_macro_parser (MalaEngine eng,
109 MalaStringListNode_ref pptr,
110 void * data)
112 MalaStringListNode itr;
113 MalaStringListNode last = NULL;
114 MalaStringList list;
115 const char* c;
116 int i;
117 int max_arg = 0;
118 int argt[10] = {0};
119 char *p;
120 MalaString args[10];
121 MalaString str = NULL;
123 // scan how much args are needed
124 mala_macrocheck_list ((MalaStringList) data, &max_arg, argt);
126 // evaluate args, fill arg-array
127 args[0] = mala_stringlistnode_string (*pptr);
129 for (i = 1; i <= max_arg; ++i)
131 if (!(last = mala_engine_arg_eval (eng, pptr, i, argt[i] == 1 ? -1 : 0, NULL, NULL))
132 || eng->state > MALA_EFAULT)
133 return eng->state;
135 args[i] = mala_stringlistnode_string (last);
138 MALA_SIDEEFFECT_BEGIN
140 // build list with substitutions
141 list = mala_stringlist_new ();
142 if (!list)
143 goto ealloc_list;
145 for (itr = mala_stringlist_head ((MalaStringList) data);
146 !mala_stringlist_is_end ((MalaStringList) data, itr);
147 mala_stringlistnode_fwd (&itr))
149 size_t size = 64;
150 if (!(p = malloc (size)))
151 goto ealloc_cstr;
153 for (c = mala_string_cstr (mala_stringlistnode_string (itr)), i = 0; *c; ++c,++i)
155 if (*c == '%')
157 ++c;
158 if (*c == '%')
160 // %% -> %
161 goto normal_char;
163 else if (*c >= '0' && *c <= '9')
165 // %0..%9
166 if (size <= i+mala_string_length (args[*c-'0'])
167 && !(size = reserve_string (&p,
168 size,
169 1 + i + mala_string_length (args[*c-'0']))))
170 goto ealloc_reserve;
171 strcpy(p+i, mala_string_cstr (args[*c-'0']));
172 i += (mala_string_length (args[*c-'0']) - 1);
174 else if (*c == '-')
176 ++c;
177 if (*c >= '0' && *c <= '9')
179 // %0..%9
180 if (size <= i+mala_string_length (args[*c-'0'])
181 && !(size = reserve_string (&p,
182 size,
183 1 + i +
184 mala_string_length (args[*c-'0']))))
185 goto ealloc_reserve;
186 strcpy(p+i, mala_string_cstr (args[*c-'0']));
187 i += (mala_string_length (args[*c-'0']) - 1);
191 else
193 normal_char:
194 // normal char
195 if (size <= (size_t) i && !(size = reserve_string (&p, size, (size_t) i+1)))
196 goto ealloc_reserve;
197 p[i] = *c;
201 p[i] = '\0';
203 char* ptmp;
204 if (!(ptmp = realloc (p, size)))
205 goto ealloc_realloc;
207 str = mala_string_new_cstr_attach (ptmp, &eng->words);
208 if (!str)
209 goto ealloc_string;
211 if (!mala_stringlist_tail_new (list, str))
212 goto ealloc_node;
214 mala_string_free (str);
218 // insert list
219 for (itr = mala_stringlist_tail (list);
220 !mala_stringlist_is_end (list, itr);
221 mala_stringlistnode_rev (&itr))
223 if (!mala_stringlist_after_new (&eng->program, last,
224 mala_stringlistnode_string (itr)))
225 goto ealloc_program;
228 // cleanup
229 mala_stringlist_free (list);
232 MALA_SIDEEFFECT_END;
234 mala_engine_command_done (eng, pptr, max_arg);
235 return MALA_CONTINUE;
237 ealloc_program:
238 ealloc_node:
239 mala_string_free (str);
240 ealloc_string:
241 ealloc_realloc:
242 ealloc_reserve:
243 free (p);
244 ealloc_cstr:
245 mala_stringlist_free (list);
246 ealloc_list:
247 return MALA_EALLOC;
251 mala_defined_parser (MalaEngine eng,
252 MalaStringListNode_ref pptr,
253 void * data)
255 MalaStringListNode result;
256 MalaActionDesc desc;
258 (void) data;
260 result = mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
261 if (!result)
262 return eng->state;
264 MALA_SIDEEFFECT_BEGIN
266 desc = (MalaActionDesc) mala_stringlistnode_user_get (result);
268 mala_engine_command_done (eng, pptr, 1);
270 if (desc && mala_actiondesc_top (desc))
272 return MALA_SUCCESS;
274 else
276 return MALA_FAILURE;
279 MALA_SIDEEFFECT_END;
281 return MALA_REMOVE;
284 #if 0
286 mala_map_parser (MalaEngine eng,
287 MalaStringListNode_ref pptr,
288 void * data)
290 MalaStringListNode function;
291 MalaStringListNode list_of_lists;
293 (void) data;
295 result = mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
296 if (!result)
297 return eng->state;
299 MALA_SIDEEFFECT_BEGIN
301 desc = (MalaActionDesc) mala_stringlistnode_user_get (result);
303 mala_engine_command_done (eng, pptr, 1);
305 if (desc && mala_actiondesc_top (desc))
307 return MALA_SUCCESS;
309 else
311 return MALA_FAILURE;
314 MALA_SIDEEFFECT_END;
316 return MALA_REMOVE;
318 #endif
321 mala_if_parser (MalaEngine eng,
322 MalaStringListNode_ref pptr,
323 void * data)
325 MalaStringListNode result;
326 (void) data;
327 /*TODO negated, blocks, parse long double 0.0 as false*/
328 /* what with syntax errors like --IF foo --ELSE .. (missing 'then' part)*/
329 int state;
331 result = mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
332 if (!result)
333 return eng->state;
335 MALA_SIDEEFFECT_BEGIN
337 if (eng->state == MALA_LITERAL)
339 if (mala_engine_string_istrue (eng, mala_stringlistnode_string (result)))
340 eng->state = MALA_SUCCESS;
341 else
342 eng->state = MALA_FAILURE;
345 state = eng->state;
347 if (eng->state == MALA_FAILURE)
348 eng->state = MALA_REMOVE;
350 result = mala_engine_arg_eval (eng, pptr, 2, -1, NULL, NULL);
351 if (!result)
352 return eng->state;
354 if (eng->state == MALA_REMOVE)
355 eng->state = MALA_FAILURE;
357 MALA_SIDEEFFECT_END;
359 if (eng->state == MALA_LITERAL)
360 mala_engine_command_done (eng, pptr, 1);
361 else
362 mala_engine_command_done (eng, pptr, 2);
363 return state;
367 mala_else_parser (MalaEngine eng,
368 MalaStringListNode_ref pptr,
369 void * data)
371 MalaStringListNode result;
372 (void) data;
373 /*TODO blocks*/
375 MALA_SIDEEFFECT_BEGIN
377 if (eng->state == MALA_SUCCESS)
378 eng->state = MALA_REMOVE;
380 result = mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
381 if (!result)
382 return eng->state;
384 if (eng->state == MALA_REMOVE)
385 eng->state = MALA_SUCCESS;
387 MALA_SIDEEFFECT_END;
389 if (eng->state == MALA_LITERAL)
390 mala_engine_command_done (eng, pptr, 0);
391 else
392 mala_engine_command_done (eng, pptr, 0);
393 return eng->state;
397 mala_pass_parser (MalaEngine eng,
398 MalaStringListNode_ref pptr,
399 void * data)
401 (void) data;
403 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
405 return eng->state;
409 mala_trace_parser (MalaEngine eng,
410 MalaStringListNode_ref pptr,
411 void * data)
413 (void) data;
415 MALA_SIDEEFFECT_BEGIN
416 eng->trace = !eng->negated;
417 MALA_SIDEEFFECT_END;
419 mala_engine_command_done (eng, pptr, 0);
420 return MALA_SUCCESS;
423 /*TODO to predicates*/
424 static int
425 mala_predicate_greaterorequal_double (double * a, double * b)
427 return *a >= *b;
431 mala_sleep_parser (MalaEngine eng,
432 MalaStringListNode_ref pptr,
433 void * data)
435 double duration;
436 double zero = 0.0;
437 struct timespec req;
439 (void) data;
441 if (mala_engine_arg_eval_fmt (eng, pptr, 1, "%lf", &duration,
442 (MalaPredicate) mala_predicate_greaterorequal_double, &zero
443 ) >= MALA_EXCEPTION)
444 return eng->state;
446 MALA_SIDEEFFECT_BEGIN
448 req.tv_sec = (time_t) duration;
449 req.tv_nsec = (long) 1000000000 * (duration - ((double) req.tv_sec));
451 (void) nanosleep (&req, NULL);
453 MALA_SIDEEFFECT_END;
455 mala_engine_command_done (eng, pptr, 1);
456 return MALA_SUCCESS;
460 mala_literal_parser (MalaEngine eng,
461 MalaStringListNode_ref pptr,
462 void * data)
464 (void) data;
466 MALA_SIDEEFFECT_BEGIN
468 if (mala_stringlist_is_tail (&eng->program, *pptr))
469 return mala_engine_exception (eng, pptr, *pptr,
470 eng->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
472 MALA_SIDEEFFECT_END;
474 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
475 return MALA_LITERAL;
479 mala_not_parser (MalaEngine eng,
480 MalaStringListNode_ref pptr,
481 void * data)
483 (void) data;
484 /*TODO evaluate %1*/
485 MALA_SIDEEFFECT_BEGIN
487 if (mala_stringlist_is_tail (&eng->program, *pptr))
488 return mala_engine_exception (eng, pptr, *pptr,
489 eng->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
490 } /*TODO remove unfinished*/
491 MALA_SIDEEFFECT_END;
493 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
494 eng->negated = !eng->negated;
495 return MALA_SUCCESS; /*TODO*/
499 mala_begin_parser (MalaEngine eng,
500 MalaStringListNode_ref pptr,
501 void * data)
503 MalaStringListNode itr;
504 MalaStringListNode end;
505 MalaStringList list;
506 unsigned depth = 1;
507 MalaString name = NULL;
509 (void) data;
511 if (mala_stringlist_is_tail (&eng->program, *pptr))
512 return mala_engine_exception (eng, pptr, *pptr,
513 eng->common_string[MALA_STRING_ERROR_MISSING_END]);
515 // find matching --END
516 for (end = mala_stringlistnode_next (*pptr);
517 !mala_stringlist_is_end (&eng->program, end);
518 mala_stringlistnode_fwd (&end))
520 if (mala_string_same(mala_stringlistnode_string (end),
521 eng->common_string[MALA_STRING_BEGIN]))
522 ++depth;
523 else if (mala_string_same(mala_stringlistnode_string (end),
524 eng->common_string[MALA_STRING_END]))
525 --depth;
526 if (!depth)
527 break;
530 if (depth)
531 return mala_engine_exception (eng, pptr, mala_stringlistnode_prev (end),
532 eng->common_string[MALA_STRING_ERROR_MISSING_END]);
534 MALA_SIDEEFFECT_BEGIN
536 list = mala_stringlist_new ();
537 if (!list)
538 return MALA_EALLOC;
540 // copy the block content to list
541 for (itr = mala_stringlistnode_next (*pptr); itr != end; mala_stringlistnode_fwd (&itr))
542 if (!mala_stringlist_tail_new (list, mala_stringlistnode_string (itr)))
543 goto ealloc_node;
545 // allocate new block name
546 do {
547 mala_string_free (name);
548 name = mala_string_new_print (&eng->words, "--BLOCK_%08X", ++eng->blockcnt);
549 if (!name)
550 goto ealloc_name;
551 } while (mala_actiondesc_top ((MalaActionDesc)mala_string_user_get (name)));
553 if (MALA_SUCCESS != mala_engine_add_action (eng, name, list,
554 mala_block_parser,
555 (MalaDataFactory)mala_stringlist_factory,
556 NULL))
557 goto ealloc_action;
559 // insert new --BLOCK_... in program
560 if (!mala_stringlist_after_new (&eng->program, end, name))
561 goto ealloc_node;
562 mala_string_free (name);
564 else
566 if (!mala_stringlist_after_new (&eng->program,
567 end,
568 eng->common_string[MALA_STRING_PASS]))
569 goto ealloc_pass;
571 MALA_SIDEEFFECT_END;
573 // and remove definition
574 while (*pptr != end)
575 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
577 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
579 return MALA_CONTINUE;
581 ealloc_action:
582 mala_string_free (name);
583 ealloc_name:
584 ealloc_node:
585 mala_stringlist_free (list);
586 ealloc_pass:
587 return MALA_EALLOC;
591 mala_block_parser (MalaEngine eng,
592 MalaStringListNode_ref pptr,
593 void * data)
595 MalaStringListNode itr;
596 MalaStringListNode end;
598 MALA_SIDEEFFECT_BEGIN
600 end = mala_stringlistnode_next (*pptr);
602 for (itr = mala_stringlist_tail ((MalaStringList) data);
603 !mala_stringlist_is_end ((MalaStringList) data, itr);
604 mala_stringlistnode_rev (&itr))
606 if (!mala_stringlist_after_new (&eng->program, *pptr,
607 mala_stringlistnode_string (itr)))
608 goto ealloc_node;
611 MALA_SIDEEFFECT_END;
613 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (*pptr));
614 mala_engine_command_done (eng, pptr, 0);
615 return MALA_CONTINUE;
617 ealloc_node:
618 /* remove already added things */
619 for (itr = mala_stringlistnode_next (*pptr);
620 itr != end;
621 mala_stringlist_elem_delete_fwd (&eng->program, &itr));
623 return MALA_EALLOC;
627 mala_macrodelete_parser (MalaEngine eng,
628 MalaStringListNode_ref pptr,
629 void * data)
631 (void) data;
633 mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
635 MALA_SIDEEFFECT_BEGIN
637 if (mala_stringlist_is_tail (&eng->program, *pptr))
638 return mala_engine_exception (eng, pptr, *pptr,
639 eng->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
641 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (mala_stringlistnode_next (*pptr)));
643 MALA_SIDEEFFECT_END;
645 mala_engine_command_done (eng, pptr, 1);
646 return MALA_SUCCESS;
650 mala_exception_parser (MalaEngine eng,
651 MalaStringListNode_ref pptr,
652 void * data)
654 // TODO needs better semantics --EXCEPTION n error -> --ERROR-error 1 .. n --HERE
656 (void) data;
658 mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
660 //TODO MALA_SIDEEFFECT_BEGIN
661 // {
662 if (mala_stringlist_is_tail (&eng->program, *pptr))
663 return mala_engine_exception (eng, pptr, *pptr,
664 eng->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
666 if (eng->state > MALA_EFAULT)
667 return eng->state;
669 MalaString ex = mala_string_new_print (&eng->words, "--ERROR-%s",
670 mala_stringlistnode_cstr (mala_stringlistnode_next (*pptr)));
672 mala_stringlist_elem_delete_fwd (&eng->program, pptr);
673 int state = mala_engine_exception (eng, pptr, *pptr, ex);
674 mala_stringlist_elem_delete (&eng->program, mala_stringlistnode_next (*pptr));
676 mala_string_free (ex);
677 // MALA_SIDEEFFECT_END;
679 return state;
683 mala_end_parser (MalaEngine eng,
684 MalaStringListNode_ref pptr,
685 void * data)
687 (void) data;
689 return mala_engine_exception (eng, pptr, *pptr,
690 eng->common_string[MALA_STRING_ERROR_END_WITHOUT_BEGIN]);
693 static void
694 mala_macrocheck_list (MalaStringList list, int * max_arg, int argt[10])
696 MalaStringListNode itr;
697 for (itr = mala_stringlist_head (list);
698 !mala_stringlist_is_end (list, itr);
699 mala_stringlistnode_fwd (&itr))
701 mala_macrocheck_string (mala_stringlistnode_string (itr), max_arg, argt);
702 if (*max_arg == -1)
703 return;
707 static void
708 mala_macrocheck_string (MalaString string, int * max_arg, int argt[10])
710 const char * c;
711 for (c = mala_string_cstr (string); *c; ++c)
713 // "foo%1%-2"
714 if (*c == '%')
716 // %
717 ++c;
718 if (*c == '%')
719 // %%
720 continue;
721 if (*c == '-')
723 // %-
724 ++c;
725 if (*c >= '0' && *c <= '9')
727 // %-0 .. %-9
728 if (argt[*c - '0'] == 1)
729 goto esyntax;
730 if (*c > (char) *max_arg + '0')
731 *max_arg = *c - '0';
732 argt[*c - '0'] = -1;
734 else
735 goto esyntax;
737 else if (*c >= '0' && *c <= '9')
739 // %0 .. %9
740 if (argt[*c - '0'] == -1)
741 goto esyntax;
742 if (*c > (char) *max_arg + '0')
743 *max_arg = *c - '0';
744 argt[*c - '0'] = 1;
746 else
747 goto esyntax;
750 return;
752 esyntax:
753 *max_arg = -1;
754 return;
758 mala_macrodef_parser (MalaEngine eng,
759 MalaStringListNode_ref pptr,
760 void * data)
762 int i;
763 MalaStringListNode itr;
764 MalaStringListNode arg[2];
765 MalaString name;
766 MalaAction act;
768 (void) data;
770 // evaluate both args
771 if (!mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL))
772 return eng->state;
773 if (!mala_engine_arg_eval (eng, pptr, 2, -1, NULL, mala_block_parser))
774 return eng->state;
776 MALA_SIDEEFFECT_BEGIN
778 // test if 2 arguments left and assign them to arg[], else error
779 for (i = 0, itr = *pptr; i<2; ++i, mala_stringlistnode_fwd(&itr))
781 if (mala_stringlist_is_tail (&eng->program, itr))
782 return mala_engine_exception (eng, pptr, itr,
783 eng->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
784 arg[i] = mala_stringlistnode_next (itr);
787 // if name is a block then error
788 name = mala_stringlistnode_string (arg[0]);
789 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (name));
790 if (act && act->parser == mala_block_parser)
791 return mala_engine_exception (eng, pptr, arg[0],
792 eng->common_string[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED]);
794 //expansion check and optimize block
795 act = mala_actiondesc_top ((MalaActionDesc) mala_stringlistnode_user_get (arg[1]));
796 if (act && act->factory == (MalaDataFactory) mala_stringlist_factory)
798 int max_arg = 0;
799 int argt[10] = {0};
800 mala_macrocheck_list ((MalaStringList) act->data, &max_arg, argt);
801 // convert block to expansion
802 if (max_arg > 0)
804 //macro
805 MalaActionDesc desc;
806 desc = mala_actiondesc_ensure (name);
807 if (!desc)
808 return MALA_EALLOC;
810 act = mala_actiondesc_pop ((MalaActionDesc) mala_stringlistnode_user_get (arg[1]));
811 act->name = name;
812 act->parser = mala_macro_parser;
813 mala_actiondesc_push_action (desc, act);
815 else if (mala_stringlist_is_single ((MalaStringList) act->data))
817 //substitute
818 MalaString subst;
819 subst = mala_stringlist_head_string_copy ((MalaStringList) act->data);
821 if (MALA_SUCCESS != mala_engine_add_action (eng, name, subst,
822 mala_substitute_parser,
823 (MalaDataFactory) mala_string_factory,
824 NULL))
825 return MALA_EALLOC;
827 mala_action_free(act);
829 else if (max_arg == 0)
831 //expand
832 MalaActionDesc desc;
833 desc = mala_actiondesc_ensure (name);
834 if (!desc)
835 return MALA_EALLOC;
837 act = mala_actiondesc_pop ((MalaActionDesc) mala_stringlistnode_user_get (arg[1]));
838 act->name = name;
839 act->parser = mala_expand_parser;
840 mala_actiondesc_push_action (desc, act);
842 else
843 return mala_engine_exception (eng, pptr, arg[1],
844 eng->common_string[MALA_STRING_ERROR_PARAMETER_SYNTAX]);
846 else //if (act && act->factory == (MalaDataFactory)mala_string_factory)
848 // single word
849 int max_arg = 0;
850 int argt[10] = {0};
851 mala_macrocheck_string (mala_stringlistnode_string (arg[1]), &max_arg, argt);
852 if (max_arg == 0)
854 // substitute
855 if (MALA_SUCCESS != mala_engine_add_action (eng, name,
856 mala_stringlistnode_string_copy (arg[1]),
857 mala_substitute_parser,
858 (MalaDataFactory) mala_string_factory,
859 NULL))
860 return MALA_EALLOC;
862 else if (max_arg > 0)
864 // macro
865 MalaStringList list;
867 list = mala_stringlist_new ();
868 if (!list)
869 return MALA_EALLOC;
871 mala_stringlist_tail_new (list, mala_stringlistnode_string (arg[1]));
873 if (MALA_SUCCESS != mala_engine_add_action (eng, name, list,
874 mala_macro_parser,
875 (MalaDataFactory) mala_stringlist_factory,
876 NULL))
877 return MALA_EALLOC;
879 else // syntax error
880 return mala_engine_exception (eng, pptr, arg[1],
881 eng->common_string[MALA_STRING_ERROR_PARAMETER_SYNTAX]);
884 MALA_SIDEEFFECT_END;
886 mala_engine_command_done (eng, pptr, 2);
887 return MALA_SUCCESS;
891 mala_foreach_word_parser (MalaEngine eng,
892 MalaStringListNode_ref pptr,
893 void * data)
895 MalaAction act;
896 MalaStringListNode first;
897 MalaStringListNode second;
898 MalaStringListNode last;
899 MalaStringListNode itr;
900 (void) data;
902 /*TODO bugs, rename to --APPLY fixit etc*/
904 first = mala_engine_arg_eval (eng, pptr, 1, -1, NULL, NULL);
905 if (!first)
906 return eng->state;
907 act = mala_actiondesc_top ((MalaActionDesc) mala_stringlistnode_user_get (first));
908 // TODO allow blocks as first arg (define macro and delete it at later)
909 if (act && act->parser == mala_block_parser)
910 return mala_engine_exception (eng, pptr, first,
911 eng->common_string[MALA_STRING_ERROR_BLOCK_NOT_ALLOWED]);
913 second = mala_engine_arg_eval (eng, pptr, 2, -1, (MalaDataFactory) mala_stringlist_factory, NULL);
914 if (!second)
915 return eng->state;
917 last = mala_stringlistnode_next (second);
919 act = mala_actiondesc_top ((MalaActionDesc) mala_stringlistnode_user_get (second));
921 // expand second
922 if (eng->state != MALA_LITERAL)
923 for (itr = mala_stringlist_tail ((MalaStringList) act->data);
924 !mala_stringlist_is_end ((MalaStringList) act->data, itr);
925 mala_stringlistnode_rev (&itr))
927 if (!mala_stringlist_after_new (&eng->program,
928 second,
929 mala_stringlistnode_string (itr)))
930 goto ealloc_node;
931 if (!mala_stringlist_after_new (&eng->program,
932 second,
933 mala_stringlistnode_string (first)))
934 goto ealloc_node;
936 else
938 if (!mala_stringlist_after_new (&eng->program,
939 second,
940 mala_stringlistnode_string (second)))
941 goto ealloc_node;
942 if (!mala_stringlist_after_new (&eng->program,
943 second,
944 mala_stringlistnode_string (first)))
945 goto ealloc_node;
949 // was a block? delete it
950 if (act && act->parser == mala_block_parser)
951 mala_actiondesc_pop_delete (mala_stringlistnode_user_get (second));
953 mala_engine_command_done (eng, pptr, 2);
954 return MALA_SUCCESS;
956 ealloc_node:
957 for (itr = mala_stringlistnode_next (second);
958 itr != last;
959 mala_stringlistnode_fwd (&itr))
961 mala_stringlist_elem_delete (&eng->program, itr);
964 return MALA_EALLOC; // TODO exception instead (needs pools, no allocation possible further)
971 realloc a string to at least needed size
972 return the amount really reserved or 0 on error
974 static size_t
975 reserve_string (char ** s, size_t actual, size_t needed)
977 size_t n;
978 char * r;
980 for (n = actual>64?actual:64; n <= needed; n += (n>>1)); /*n = n * 1.5*/
982 r = realloc (*s, n);
983 if (!r)
985 /* that was to much, try conservatively */
986 r = realloc (*s, n = needed);
987 if (!r)
988 return 0;
990 *s = r;
991 return n;
996 // Local Variables:
997 // mode: C
998 // c-file-style: "gnu"
999 // End:
1000 // arch-tag: 195047fd-d18b-4af6-a627-43e5655162ed
1001 // end_of_file