macrodelete_parser
[mala.git] / engine / engine.c
blob119fea71b8244a7e8e410771eee3c582481d1b24
1 /*
2 engine.c - MaLa core engine
4 Copyright (C) 2004, 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 <stdlib.h>
21 #include <ctype.h>
22 #include <stdio.h>
23 #include "mala_types.h"
24 #include "engine.h"
25 #include "actiondesc.h"
26 #include "action.h"
27 #include "stringlist.h"
28 #include "std/std.h"
31 static const char * mala_common_strings []=
33 "--FALSE",
34 "--TRUE",
35 "0",
36 "--NULL",
37 "!",
38 "=",
39 "`",
40 "--NOT",
41 "--LITERAL",
42 "--ENVSUBST",
43 "--SETENV",
44 "--SECTION",
45 "--HERE",
46 "--BEGIN",
47 "--END",
48 "--DEL",
49 "--FLAG-LITERAL-EXPANSION",
50 "--FLAG-EXCLAM-EXPANSION",
51 "--FLAG-NO-EXPANSION",
52 "--FLAG-NUMSPLIT-EXPANSION",
53 "--FLAG-CHAR-EXPANSION",
54 "--FLAG-ASSIGN-EXPANSION",
55 "--FLAG-SETENV-EXPANSION",
56 "--FLAG-ENVVAR-EXPANSION",
57 "--FLAG-UNDERSCORE-EXPANSION",
58 "--FLAG-BRACKET-EXPANSION",
59 "--FLAG-ASSIGN-CONTRACTION",
60 "--ERROR-MISSING-ARGUMENT",
61 "--ERROR-MISSING-END",
62 NULL
69 * function definitions
72 MalaEngine
73 mala_engine_new ()
75 MalaEngine self;
76 int i;
78 self = malloc (sizeof(mala_engine));
79 if (!self)
80 return NULL;
82 self->negated = 0;
83 self->blockcnt = 0;
85 self->state = MALA_SUCCESS;
87 mala_stringbucket_init (&self->words, MALA_STRING_FWD, (void(*)(void*)) mala_actiondesc_free);
89 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
91 self->common_string[i] = mala_string_new (mala_common_strings[i], &self->words);
92 if (!self->common_string[i])
93 goto ealloc_strings;
96 mala_stringlist_init (&self->program);
97 mala_stringlist_init (&self->arguments);
99 return self;
101 ealloc_strings:
102 while (--i >= 0)
103 mala_string_free (self->common_string[i]);
104 free (self);
105 return NULL;
108 #if 0
109 MalaEngine
110 mala_engine_new_main (int (*initfunc) (MalaEngine),
111 int argc, char **argv,
112 mala_actioninit * actions_init)
114 /*TODO convinience function*/
116 #endif
119 mala_engine_macro_define (MalaEngine self, const char * name, int argc, char ** argv)
121 int i;
122 MalaStringList list;
123 MalaStringListNode itr;
124 int mexp = 0;
125 mala_stringlist pre;
127 if(!self)
128 return MALA_EINVALID;
129 if(self->state > MALA_EFAULT)
130 return self->state;
132 mala_stringlist_init (&pre);
134 for (i = 0; i != argc && *argv; ++i ,++argv)
136 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
137 goto ealloc_node;
140 list = mala_stringlist_new ();
141 if (!list)
142 goto ealloc_list;
144 /*TODO preprocess in own function*/
145 while (!mala_stringlist_is_empty (&pre))
147 int putaway;
149 itr = mala_stringlist_head (&pre);
151 putaway = mala_engine_expand (self, &pre, &itr);
153 if (self->state > MALA_EFAULT)
154 return self->state;
156 while (putaway--)
158 mala_stringlist_node_remove (&pre, itr);
159 mala_stringlist_tail_insert (list, itr);
160 if (putaway && mala_stringlist_is_empty (&pre))
161 goto eunderrun;
162 itr = mala_stringlist_head (&pre);
166 if (mala_stringlist_is_empty (list))
168 /* empty substituted by --NULL, TODO use empty string instead? */
169 mala_stringlist_free (list);
170 return mala_engine_add_action_cstr (self, name,
171 mala_string_copy (self->common_string[MALA_STRING_NULL]),
172 mala_substitute_parser,
173 (MalaDataFactory)mala_string_factory,
174 NULL);
178 for (itr = mala_stringlist_head (list);
179 !mala_stringlist_is_end (list, itr);
180 mala_stringlist_fwd(&itr))
181 if (mala_string_char_find (itr->string, '%') != SIZE_MAX)
183 mexp = 1;
184 break;
187 if (mexp)
189 /* macro */
190 return mala_engine_add_action_cstr (self, name, list,
191 mala_macro_parser,
192 (MalaDataFactory)mala_stringlist_factory,
193 NULL);
195 else if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
197 /* substitute */
198 MalaString subst;
200 subst = mala_string_copy (mala_stringlist_head (list) -> string);
201 mala_stringlist_free (list);
203 return mala_engine_add_action_cstr (self, name, subst,
204 mala_substitute_parser,
205 (MalaDataFactory)mala_string_factory,
206 NULL);
208 else
210 /* expand */
211 return mala_engine_add_action_cstr (self, name, list,
212 mala_expand_parser,
213 (MalaDataFactory) mala_stringlist_factory,
214 NULL);
217 eunderrun:
218 mala_stringlist_free (list);
219 mala_stringlist_erase (&pre);
220 return self->state = MALA_ESYNTAX;
222 ealloc_list:
223 ealloc_node:
224 mala_stringlist_erase (&pre);
225 return self->state = MALA_EALLOC;
229 mala_engine_pushback_word (MalaEngine self, const char * word)
231 if(!self)
232 return MALA_EINVALID;
233 if(self->state > MALA_EFAULT)
234 return self->state;
236 if (!mala_stringlist_tail_new_cstr (&self->program, word, &self->words))
237 return self->state = MALA_EALLOC;
239 return MALA_SUCCESS;
243 mala_engine_add_action_cstr (MalaEngine self, const char * cname, void * data,
244 MalaParserFunc parser, MalaDataFactory factory,
245 MalaAction parent)
247 MalaString name;
248 MalaAction action;
250 /*TODO such checks everywhere*/
251 if(!self)
252 return MALA_EINVALID;
253 if(self->state > MALA_EFAULT)
254 return self->state;
256 name = mala_string_new (cname, &self->words);
257 if (!name)
258 goto ealloc_name;
260 action = mala_action_new (name, data, parser, factory, parent);
261 if (!action)
262 goto ealloc_action;
264 if (mala_action_attach (action) != MALA_SUCCESS)
265 goto ealloc_attach;
267 mala_string_free (name);
268 return MALA_SUCCESS;
270 ealloc_attach:
271 mala_action_free (action);
272 ealloc_action:
273 mala_string_free (name);
274 ealloc_name:
275 return self->state = MALA_EALLOC;
279 mala_engine_add_action (MalaEngine self, MalaString name, void * data,
280 MalaParserFunc parser, MalaDataFactory factory,
281 MalaAction parent)
283 MalaAction action;
285 /*TODO such checks everywhere*/
286 if(!self)
287 return MALA_EINVALID;
288 if(self->state > MALA_EFAULT)
289 return self->state;
291 action = mala_action_new (name, data, parser, factory, parent);
292 if (!action)
293 goto ealloc_action;
295 if (mala_action_attach (action) != MALA_SUCCESS)
296 goto ealloc_attach;
298 return MALA_SUCCESS;
300 ealloc_attach:
301 mala_action_free (action);
302 ealloc_action:
303 return self->state = MALA_EALLOC;
307 MalaEngine
308 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
310 MalaEngine self;
312 self = mala_engine_new ();
313 if (!self)
314 return 0;
316 self->state = initfunc (self);
317 return self;
320 void
321 mala_engine_free (MalaEngine self)
323 int i;
325 if (!self)
326 return;
328 mala_stringlist_erase (&self->program);
329 mala_stringlist_erase (&self->arguments);
331 mala_stringbucket_erase (&self->words);
333 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
334 mala_string_free (self->common_string[i]);
336 free (self);
340 mala_engine_actions_register (MalaEngine self, mala_actioninit * actioninit)
342 MalaAction action;
344 if (!self)
345 return MALA_EINVALID;
347 if (self->state > MALA_EFAULT)
348 return self->state;
350 while (actioninit->command)
352 action = mala_action_new_actioninit (actioninit, &self->words);
353 if (!action)
354 goto ealloc;
356 if (mala_action_attach (action) != MALA_SUCCESS)
357 goto ealloc;
359 ++actioninit;
362 return MALA_SUCCESS;
364 ealloc:
365 return self->state = MALA_EINIT;
369 /*TODO make some inlines { */
371 MalaStringList
372 mala_engine_getprogram (MalaEngine self)
374 return &self->program;
377 mala_state
378 mala_engine_state_get (MalaEngine self)
380 return self->state;
383 void
384 mala_engine_clearstate (MalaEngine self)
386 self->state = MALA_SUCCESS;
390 mala_engine_negated (MalaEngine self)
392 return self->negated;
395 void
396 mala_engine_clear_negated (MalaEngine self)
398 self->negated = 0;
400 /* } TODO make some inlines */
403 void
404 mala_engine_dumpprogram (MalaEngine self, const char * prefix, const char * suffix)
406 MalaStringListNode node;
408 for (node = mala_stringlist_head (&self->program);
409 node != (void *)&self->program;
410 mala_stringlist_fwd (&node))
412 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
416 void
417 mala_engine_dumpargs (MalaEngine self, const char * prefix, const char * suffix)
419 MalaStringListNode node;
421 for (node = mala_stringlist_head (&self->arguments);
422 node != (void *)&self->arguments;
423 mala_stringlist_fwd (&node))
425 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
430 MalaEngine
431 mala_engine_run (MalaEngine self)
433 MalaStringListNode pptr;
435 while (self->state < MALA_EFAULT &&
436 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
438 if (self->state == MALA_LITERAL)
440 mala_stringlist_elem_remove (&self->program, pptr);
441 mala_stringlist_tail_insert (&self->arguments, pptr);
442 self->state = MALA_SUCCESS;
444 else
445 mala_engine_eval (self, &pptr);
447 return self;
451 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
453 MalaAction act;
454 MalaActionDesc desc;
456 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
457 if (!desc)
458 return self->state = MALA_LITERAL;
460 act = mala_actiondesc_top (desc);
462 if (act)
463 self->state = mala_action_execute (act, pptr, self);
465 if (self->state == MALA_EXCEPTION)
466 self->state = MALA_ENOACTION;
468 return self->state;
471 void
472 mala_engine_try_eval_arg_n (MalaEngine self, MalaStringListNode_ref pptr, unsigned n)
474 MalaStringListNode next;
475 for (next = *pptr;
476 n && !mala_stringlist_is_tail (&self->program, next);
477 mala_stringlist_fwd (&next), --n);
479 while (!mala_stringlist_is_tail (&self->program, *pptr) && self->state < MALA_EXCEPTION)
481 mala_engine_eval (self, &next);
486 mala_engine_exception (MalaEngine self,
487 MalaStringListNode_ref pptr,
488 MalaStringListNode here,
489 MalaString except)
491 MalaStringListNode tmp;
493 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
494 if (!tmp)
495 return self->state = MALA_EALLOC;
497 if (!mala_stringlist_after_new (&self->program, here,
498 self->common_string[MALA_STRING_HERE]))
499 return self->state = MALA_EALLOC;
501 *pptr = tmp;
503 /*TODO self-state needs to be preserved somehow?*/
504 return self->state = MALA_EXCEPTION;
509 mala_engine_expand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
511 int ret = 0;
513 if (self->state > MALA_EFAULT)
514 return MALA_EXPANSION_ERROR;
516 #define mala_run_expansion(name) \
517 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
519 mala_run_expansion (literal_expansion);
520 mala_run_expansion (numsplit_expansion);
521 mala_run_expansion (exclam_expansion);
522 mala_run_expansion (no_expansion);
523 mala_run_expansion (assign_expansion);
524 mala_run_expansion (char_expansion);
525 mala_run_expansion (underscore_expansion);
526 mala_run_expansion (bracket_expansion);
527 mala_run_expansion (assign_contraction);
528 mala_run_expansion (envvar_expansion);
529 mala_run_expansion (setenv_expansion);
530 mala_run_expansion (backquote_expansion);
531 #undef mala_run_expansion
533 return 1;
537 mala_engine_literal_expansion (MalaEngine self,
538 MalaStringList list,
539 MalaStringListNode_ref pptr)
541 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
542 && mala_string_check_prefix ((*pptr)->string, "`")
543 && !mala_string_check_prefix ((*pptr)->string, "``"))
545 MalaString nstr;
546 MalaStringListNode newnode1;
547 MalaStringListNode newnode2;
549 newnode1 = mala_stringlist_after_new (list,
550 *pptr,
551 self->common_string[MALA_STRING_LITERAL]);
552 if (!newnode1)
553 goto ealloc_newnode1;
555 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
556 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
557 if (!newnode2)
558 goto ealloc_newnode2;
560 mala_stringlist_elem_delete (list, pptr);
561 *pptr = newnode1;
563 return 2;
565 ealloc_newnode2:
566 mala_stringlist_elem_delete (list, &newnode1);
567 ealloc_newnode1:
568 self->state = MALA_EALLOC;
569 return MALA_EXPANSION_ERROR;
571 return MALA_NO_EXPANSION;
576 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
578 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
579 && mala_string_check_prefix ((*pptr)->string, "``"))
581 MalaString nstr;
582 MalaStringListNode newnode;
584 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
585 newnode = mala_stringlist_after_new (list, *pptr, nstr);
586 if (!newnode)
587 goto ealloc_newnode;
589 mala_stringlist_elem_delete (list, pptr);
590 *pptr = newnode;
592 return 1;
594 ealloc_newnode:
595 self->state = MALA_EALLOC;
596 return MALA_EXPANSION_ERROR;
598 return MALA_NO_EXPANSION;
602 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
604 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
605 && mala_string_length ((*pptr)->string) > 2
606 && mala_string_at ((*pptr)->string, 0) == '-'
607 && isalpha (mala_string_at ((*pptr)->string, 1))
610 size_t i;
612 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
614 if (isdigit (mala_string_at ((*pptr)->string, i)))
616 MalaString a;
617 MalaString b;
619 MalaStringListNode na;
620 MalaStringListNode nb;
622 a = mala_string_new_substr ((*pptr)->string, 0, i);
623 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
624 if (!a || !b)
625 goto ealloc_str;
627 na = mala_stringlist_after_new (list, *pptr, a);
628 if (!na)
629 goto ealloc_nodea;
631 nb = mala_stringlist_after_new (list, na, b);
632 if (!nb)
633 goto ealloc_nodeb;
635 mala_stringlist_elem_delete (list, pptr);
636 *pptr = na;
638 mala_string_free (a);
639 mala_string_free (b);
641 return 0;
643 ealloc_nodeb:
644 mala_stringlist_elem_delete (list, &na);
645 ealloc_nodea:
646 ealloc_str:
647 mala_string_free (a);
648 mala_string_free (b);
649 self->state = MALA_EALLOC;
650 return MALA_EXPANSION_ERROR;
654 return MALA_NO_EXPANSION;
659 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
661 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
662 && mala_string_length ((*pptr)->string) == 1
663 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
665 MalaStringListNode newnode;
667 newnode = mala_stringlist_after_new (list,
668 *pptr,
669 self->common_string[MALA_STRING_NOT]);
670 if (!newnode)
671 return self->state = MALA_EALLOC;
673 mala_stringlist_elem_delete (list, pptr);
674 *pptr= newnode;
675 return 1;
677 return MALA_NO_EXPANSION;
682 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
684 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
685 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
686 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
688 MalaString a;
689 MalaString aa;
690 MalaStringListNode n1;
691 MalaStringListNode n2;
693 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
694 aa = mala_string_new_prefix ("--", a);
695 if (!a || !aa)
696 goto ealloc_a;
698 n1 = mala_stringlist_after_new (list,
699 *pptr, self->common_string[MALA_STRING_NOT]);
700 if (!n1)
701 goto ealloc_n1;
703 n2 = mala_stringlist_after_new (list, n1, aa);
704 if (!n2)
705 goto ealloc_n2;
707 mala_string_free (a);
708 mala_string_free (aa);
709 mala_stringlist_elem_delete (list, pptr);
710 *pptr = n1;
711 return 1;
713 ealloc_n2:
714 mala_stringlist_elem_delete (list, &n1);
715 ealloc_n1:
716 mala_string_free (a);
717 mala_string_free (aa);
718 ealloc_a:
719 self->state = MALA_EALLOC;
720 return MALA_EXPANSION_ERROR;
722 return MALA_NO_EXPANSION;
727 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
729 size_t eq;
731 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
732 && mala_string_check_prefix ((*pptr)->string, "--")
733 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
734 && mala_string_length ((*pptr)->string) > eq + 1)
736 MalaString a;
737 MalaString b;
739 MalaStringListNode na;
740 MalaStringListNode nb;
742 a = mala_string_new_substr ((*pptr)->string, 0, eq);
743 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
744 if (!a || !b)
745 goto ealloc_str;
747 na = mala_stringlist_after_new (list, *pptr, a);
748 if (!na)
749 goto ealloc_nodea;
751 nb = mala_stringlist_after_new (list, na, b);
752 if (!nb)
753 goto ealloc_nodeb;
755 mala_stringlist_elem_delete (list, pptr);
756 *pptr = na;
758 mala_string_free (a);
759 mala_string_free (b);
762 return 0;
764 ealloc_nodeb:
765 mala_stringlist_elem_delete (list, &na);
766 ealloc_nodea:
767 ealloc_str:
768 mala_string_free (a);
769 mala_string_free (b);
770 self->state = MALA_EALLOC;
771 return MALA_EXPANSION_ERROR;
773 return MALA_NO_EXPANSION;
778 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
780 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
781 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
783 MalaStringListNode newnode;
785 newnode = mala_stringlist_before_new (list,
786 *pptr,
787 self->common_string[MALA_STRING_ENVSUBST]);
788 if (!newnode)
789 goto ealloc_node;
791 *pptr= newnode;
792 return 2;
794 ealloc_node:
795 self->state = MALA_EALLOC;
796 return MALA_EXPANSION_ERROR;
799 return MALA_NO_EXPANSION;
804 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
806 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
807 && mala_string_length ((*pptr)->string) > 2
808 && ( mala_string_at ((*pptr)->string, 0) == '-'
809 || mala_string_at ((*pptr)->string, 0) == '+')
810 && isalpha (mala_string_at ((*pptr)->string, 1)))
812 char prefix[2] = "-";
813 char current[2] = " ";
814 const char * i;
815 int cnt = 0;
817 MalaString str;
818 MalaStringListNode node = NULL;
819 MalaStringListNode pred = *pptr;
822 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
824 if (*i == '-' || *i == '+')
825 prefix[0] = *i;
826 else if (isalpha (*i))
828 ++cnt;
829 current[0] = *i;
830 str = mala_string_new_cat2 (prefix, current,
831 mala_string_bucket_get ((*pptr)->string));
832 if (!str)
833 goto ealloc;
835 node = mala_stringlist_after_new (list,
836 pred, str);
837 if (!node)
838 goto ealloc;
840 pred = node;
841 mala_string_free (str);
843 else
844 break;
847 pred = *pptr;
848 mala_stringlist_fwd (&pred);
849 mala_stringlist_elem_delete (list, pptr);
850 *pptr= pred;
851 return cnt;
853 ealloc:
854 mala_string_free (str);
855 /* cleanup from pred downto pptr */
856 while (pred != *pptr)
858 // TODO use stringlist func
859 MalaStringListNode tmp = pred->node.cqe_prev;
860 mala_stringlist_elem_delete (list, &pred);
861 pred = tmp;
863 self->state = MALA_EALLOC;
864 return MALA_EXPANSION_ERROR;
866 return MALA_NO_EXPANSION;
871 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
873 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
874 && mala_string_check_prefix ((*pptr)->string, "--")
875 && strchr (mala_string_cstr ((*pptr)->string), '_'))
877 MalaString str;
878 MalaStringListNode node;
879 char * cstr;
880 char * i;
882 cstr = strdup (mala_string_cstr ((*pptr)->string));
883 if (!cstr)
884 goto ealloc_cstr;
886 for (i = cstr + 2; *i; ++i)
888 if (*i == '_')
889 *i = '-';
892 str = mala_string_new (cstr, &self->words);
893 if (!str)
894 goto ealloc_str;
896 node = mala_stringlist_after_new (list,
897 *pptr,
898 str);
899 if (!node)
900 goto ealloc_node;
902 free (cstr);
903 mala_string_free (str);
905 mala_stringlist_elem_delete (list, pptr);
906 *pptr= node;
907 return 0;
909 ealloc_node:
910 mala_string_free (str);
911 ealloc_str:
912 free (cstr);
913 ealloc_cstr:
914 self->state = MALA_EALLOC;
915 return MALA_EXPANSION_ERROR;
917 return MALA_NO_EXPANSION;
922 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
924 unsigned eq;
926 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
927 && mala_string_length ((*pptr)->string) > 1
928 && (eq = mala_string_char_find ((*pptr)->string, '='))
929 && eq > 0
930 && eq < SIZE_MAX
931 && !mala_string_check_prefix ((*pptr)->string, "-"))
933 MalaString key;
934 MalaString value;
935 MalaStringListNode n1;
936 MalaStringListNode n2;
937 MalaStringListNode n3;
939 key = mala_string_new_substr ((*pptr)->string, 0, eq);
940 if (!key)
941 goto ealloc_key;
943 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
944 if (!value)
945 goto ealloc_value;
947 n1 = mala_stringlist_after_new (list,
948 *pptr, self->common_string[MALA_STRING_SETENV]);
949 if (!n1)
950 goto ealloc_n1;
952 n2 = mala_stringlist_after_new (list, n1, key);
953 if (!n2)
954 goto ealloc_n2;
956 n3 = mala_stringlist_after_new (list, n2, value);
957 if (!n3)
958 goto ealloc_n3;
960 mala_string_free (key);
961 mala_string_free (value);
962 mala_stringlist_elem_delete (list, pptr);
963 *pptr = n1;
964 return 3;
966 ealloc_n3:
967 mala_stringlist_elem_delete (list, &n2);
968 ealloc_n2:
969 mala_stringlist_elem_delete (list, &n1);
970 ealloc_n1:
971 mala_string_free (value);
972 ealloc_value:
973 mala_string_free (key);
974 ealloc_key:
975 self->state = MALA_EALLOC;
976 return MALA_EXPANSION_ERROR;
978 return MALA_NO_EXPANSION;
983 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
985 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
986 && mala_string_at ((*pptr)->string, 0) == '[')
988 MalaStringListNode nitr;
989 MalaStringListNode node;
991 MalaString str1 = NULL;
992 MalaStringListNode node1;
994 MalaString str2 = NULL;
995 MalaStringListNode node2;
997 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
998 if (!node)
999 goto ealloc_node;
1001 if (mala_string_length((*pptr)->string) > 1)
1003 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
1004 node1 = mala_stringlist_after_new (list, node, str1);
1005 if (!node1)
1006 goto ealloc_node1;
1008 else
1010 node1 = node;
1011 mala_stringlist_fwd (&node1);
1014 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlist_fwd (&nitr))
1016 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1017 break;
1020 if ((void*)nitr != (void*)list)
1022 if (mala_string_length(nitr->string) > 1)
1024 str2 = mala_string_new_substr (nitr->string, 0,
1025 mala_string_length(nitr->string) - 1);
1026 node2 = mala_stringlist_after_new (list, nitr, str2);
1027 if (!node2)
1028 goto ealloc_node2;
1031 else
1032 goto esyntax;
1035 mala_string_free (str1);
1036 mala_string_free (str2);
1037 mala_stringlist_elem_delete (list, pptr);
1038 mala_stringlist_elem_delete (list, &nitr);
1039 *pptr = node;
1041 return 0;
1043 esyntax:
1044 mala_string_free (str1);
1045 mala_stringlist_elem_delete (list, &node1);
1046 mala_stringlist_elem_delete (list, &node);
1047 self->state = MALA_ESYNTAX;
1048 return MALA_EXPANSION_ERROR;
1050 ealloc_node2:
1051 mala_string_free (str1);
1052 mala_stringlist_elem_delete (list, &node1);
1053 ealloc_node1:
1054 mala_stringlist_elem_delete (list, &node);
1055 ealloc_node:
1056 self->state = MALA_EALLOC;
1057 return MALA_EXPANSION_ERROR;
1059 return MALA_NO_EXPANSION;
1064 mala_engine_assign_contraction (MalaEngine self,
1065 MalaStringList list,
1066 MalaStringListNode_ref pptr)
1068 MalaStringListNode assign;
1069 MalaStringListNode value ;
1071 assign = *pptr;
1072 mala_stringlist_fwd (&assign);
1073 value = assign;
1075 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1076 && !mala_stringlist_is_tail (list, *pptr)
1077 && !mala_stringlist_is_tail (list, assign)
1078 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1080 MalaString str;
1081 MalaStringListNode node;
1083 mala_stringlist_fwd (&value);
1085 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1086 "%s=%s",
1087 mala_string_cstr ((*pptr)->string),
1088 mala_string_cstr (value->string));
1091 node = mala_stringlist_after_new (list,
1092 value,
1093 str);
1094 if (!node)
1095 goto ealloc_node;
1097 mala_string_free (str);
1098 mala_stringlist_elem_delete (list, pptr);
1099 mala_stringlist_elem_delete (list, &assign);
1100 mala_stringlist_elem_delete (list, &value);
1101 *pptr = node;
1102 return 0;
1104 ealloc_node:
1105 mala_string_free (str);
1106 self->state = MALA_EALLOC;
1107 return MALA_EXPANSION_ERROR;
1109 return MALA_NO_EXPANSION;
1116 mala_engine_string_istrue (MalaEngine self, MalaString str)
1118 if (!str
1119 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1120 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1121 return 0;
1123 return 1;
1127 mala_engine_check_expansionflag (MalaEngine self, int flag)
1129 MalaActionDesc desc;
1130 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1131 if (!desc)
1132 return 0;
1134 /*only enabled when the topmost action is a subtitution to --TRUE*/
1135 if (desc->actions.lh_first)
1136 return desc->actions.lh_first->data == self->common_string[MALA_STRING_TRUE];
1138 return 0;
1153 #if 0 /*TODO*/
1155 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1157 MalaAction act;
1159 if (self->state > MALA_EFAULT)
1160 return self->state;
1162 act = mala_actiondict_lookupaction (self->actions, key);
1163 if (!act)
1164 goto enoact;
1166 mala_actiondict_destroy_action (self->actions, act);
1168 return MALA_SUCCESS;
1170 enoact:
1171 self->state = MALA_ENOACTION;
1172 return self->state;
1178 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1180 MalaStringListNode base = llist_get_prev (pptr);
1181 while (mala_engine_eval (self, llist_get_next (base)) < MALA_EVAL)
1182 if (llist_get_next (base) == &self->program)
1183 return MALA_ENOACTION;
1185 return self->state;
1190 void
1191 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1193 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1199 mala_engine_argc (MalaEngine self)
1201 return llist_count (&self->arguments) + 1;
1204 const char*
1205 mala_engine_argv (MalaEngine self, int n)
1207 MalaStringListNode p;
1208 p = llist_get_next (&self->arguments);
1210 if (n==0)
1211 return self->argv_0;
1213 while (--n)
1215 if (p == &self->arguments)
1216 return 0;
1217 p = llist_get_next (p);
1219 return (const char *)(p)->data;
1224 MalaAction
1225 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1226 MalaParserFunc parser, MalaDataDestructor destructor)
1228 MalaAction act;
1230 act = mala_action_new (name, data, parser, destructor);
1231 if (!act)
1232 goto ealloc;
1234 self->state = mala_actiondict_push (self->actions, act);
1235 if (self->state)
1236 goto epush;
1238 return act;
1240 epush:
1241 mala_action_destroy (act);
1242 ealloc:
1243 return 0;
1247 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1249 MalaAction act;
1251 act = mala_actiondict_lookupaction (self->actions, name);
1252 if (!act)
1253 return MALA_NO_EXPANSION;
1255 if (act->parser != mala_substitute_parser)
1256 return MALA_EPARSER;
1258 return mala_string_check ((t_uchar*) act->data);
1262 MalaAction
1263 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1265 return mala_actiondict_lookupaction (self->actions, name);
1268 MalaAction
1269 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1271 return mala_actiondict_lookupprevaction (self->actions, name);
1274 #endif /*TODO*/
1281 // Local Variables:
1282 // mode: C
1283 // c-file-style: "gnu"
1284 // End:
1285 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1286 // end_of_file