new startup scheme, *breaks tests until we have the first parsers*
[mala.git] / engine / engine.c
blobb1b4c124a94f8a47041badaaf7a7b68526d92610
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"
30 static const char * mala_common_strings []=
32 "--FALSE",
33 "--TRUE",
34 "0",
35 "!",
36 "=",
37 "`",
38 "--NOT",
39 "--LITERAL",
40 "--ENVSUBST",
41 "--SETENV",
42 "--SECTION",
43 "--FLAG-LITERAL-EXPANSION",
44 "--FLAG-EXCLAM-EXPANSION",
45 "--FLAG-NO-EXPANSION",
46 "--FLAG-NUMSPLIT-EXPANSION",
47 "--FLAG-CHAR-EXPANSION",
48 "--FLAG-ASSIGN-EXPANSION",
49 "--FLAG-SETENV-EXPANSION",
50 "--FLAG-ENVVAR-EXPANSION",
51 "--FLAG-UNDERSCORE-EXPANSION",
52 "--FLAG-BRACKET-EXPANSION",
53 "--FLAG-ASSIGN-CONTRACTION",
54 NULL
61 * function definitions
64 MalaEngine
65 mala_engine_new ()
67 MalaEngine self;
68 int i;
70 self = malloc (sizeof(mala_engine));
71 if (!self)
72 return 0;
75 self->negated = 0;
77 self->state = MALA_SUCCESS;
79 mala_stringbucket_init (&self->words, MALA_STRING_FWD, (void(*)(void*)) mala_actiondesc_free);
81 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
83 self->common_string[i] = mala_string_new (mala_common_strings[i], &self->words);
84 if (!self->common_string[i])
85 goto ealloc_strings;
88 mala_stringlist_init (&self->program);
89 mala_stringlist_init (&self->arguments);
91 return self;
93 ealloc_strings:
94 while (--i >= 0)
95 mala_string_free (self->common_string[i]);
96 free (self);
97 return NULL;
100 #if 0
101 MalaEngine
102 mala_engine_new_main (int (*initfunc) (MalaEngine),
103 int argc, char **argv,
104 mala_actioninit * actions_init)
106 /*TODO convinience function*/
108 #endif
111 mala_engine_macro_define (MalaEngine self, const char * name, int argc, char ** argv)
113 int i;
114 MalaStringList list;
115 MalaStringListNode itr;
116 int mexp = 0;
117 mala_stringlist pre;
119 if(!self)
120 return MALA_EINVALID;
121 if(self->state > MALA_EFAULT)
122 return self->state;
124 mala_stringlist_init (&pre);
126 for (i = 0; i != argc && *argv; ++i ,++argv)
128 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
129 goto ealloc_node;
132 list = mala_stringlist_new ();
133 if (!list)
134 goto ealloc_list;
136 /*TODO preprocess in own function*/
137 while (!mala_stringlist_is_empty (&pre))
139 int putaway;
141 itr = mala_stringlist_head (&pre);
143 putaway = mala_engine_expand (self, &pre, &itr);
145 if (self->state > MALA_EFAULT)
146 return self->state;
148 while (putaway--)
150 mala_stringlist_node_remove (&pre, itr);
151 mala_stringlist_tail_insert (list, itr);
152 if (putaway && mala_stringlist_is_empty (&pre))
153 goto eunderrun;
154 itr = mala_stringlist_head (&pre);
158 for (itr = mala_stringlist_head (list);
159 mala_stringlist_is_end (list, itr);
160 mala_stringlist_fwd(&itr))
161 if (mala_string_char_find (itr->string, '%') != SIZE_MAX)
163 mexp = 1;
164 break;
167 if (mexp)
169 /* macro */
170 return mala_engine_add_action (self, name, list,
171 mala_macro_parser,
172 (MalaDataFactory)mala_stringlist_factory,
173 NULL);
175 else if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
177 /* substitute */
178 MalaString subst;
180 subst = mala_string_copy (mala_stringlist_head (list) -> string);
181 mala_stringlist_free (list);
183 return mala_engine_add_action (self, name, subst,
184 mala_substitute_parser,
185 (MalaDataFactory)mala_string_factory,
186 NULL);
188 else
190 /* expand */
191 return mala_engine_add_action (self, name, list,
192 mala_expand_parser,
193 (MalaDataFactory) mala_stringlist_factory,
194 NULL);
197 eunderrun:
198 mala_stringlist_free (list);
199 mala_stringlist_erase (&pre);
200 return self->state = MALA_ESYNTAX;
202 ealloc_list:
203 ealloc_node:
204 mala_stringlist_erase (&pre);
205 return self->state = MALA_EALLOC;
209 mala_engine_pushback (MalaEngine self, const char * word)
211 if(!self)
212 return MALA_EINVALID;
213 if(self->state > MALA_EFAULT)
214 return self->state;
216 if (!mala_stringlist_tail_new_cstr (&self->program, word, &self->words))
217 return self->state = MALA_EALLOC;
219 return MALA_SUCCESS;
223 mala_engine_add_action (MalaEngine self, const char * cname, void * data,
224 MalaParserFunc parser, MalaDataFactory factory,
225 MalaAction parent)
227 MalaString name;
228 MalaAction action;
230 /*TODO such checks everywhere*/
231 if(!self)
232 return MALA_EINVALID;
233 if(self->state > MALA_EFAULT)
234 return self->state;
236 name = mala_string_new (cname, &self->words);
237 if (!name)
238 goto ealloc_name;
240 action = mala_action_new (name, data, parser, factory, parent);
241 if (!action)
242 goto ealloc_action;
244 if (mala_action_attach (action) != MALA_SUCCESS)
245 goto ealloc_attach;
247 mala_string_free (name);
248 return MALA_SUCCESS;
250 ealloc_attach:
251 mala_action_free (action);
252 ealloc_action:
253 mala_string_free (name);
254 ealloc_name:
255 return self->state = MALA_EALLOC;
259 MalaEngine
260 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
262 MalaEngine self;
264 self = mala_engine_new ();
265 if (!self)
266 return 0;
268 self->state = initfunc (self);
269 return self;
272 void
273 mala_engine_free (MalaEngine self)
275 int i;
277 if (!self)
278 return;
280 mala_stringlist_erase (&self->program);
281 mala_stringlist_erase (&self->arguments);
283 mala_stringbucket_erase (&self->words);
285 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
286 mala_string_free (self->common_string[i]);
288 free (self);
292 mala_engine_register_actions (MalaEngine self, mala_actioninit * actioninit)
294 MalaAction action;
296 if (self->state > MALA_EFAULT)
297 return self->state;
299 while (actioninit->command)
301 action = mala_action_new_actioninit (actioninit, &self->words);
302 if (!action)
303 goto ealloc;
305 if (mala_action_attach (action) != MALA_SUCCESS)
306 goto ealloc;
308 ++actioninit;
311 return MALA_SUCCESS;
313 ealloc:
314 return self->state = MALA_EINIT;
318 /*TODO make some inlines { */
320 MalaStringList
321 mala_engine_getprogram (MalaEngine self)
323 return &self->program;
326 mala_state
327 mala_engine_state_get (MalaEngine self)
329 return self->state;
332 void
333 mala_engine_clearstate (MalaEngine self)
335 self->state = MALA_SUCCESS;
339 mala_engine_negated (MalaEngine self)
341 return self->negated;
344 void
345 mala_engine_clear_negated (MalaEngine self)
347 self->negated = 0;
349 /* } TODO make some inlines */
352 void
353 mala_engine_dumpprogram (MalaEngine self, const char * prefix, const char * suffix)
355 MalaStringListNode node;
357 for (node = mala_stringlist_head (&self->program);
358 node != (void *)&self->program;
359 mala_stringlist_fwd (&node))
361 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
365 void
366 mala_engine_dumpargs (MalaEngine self, const char * prefix, const char * suffix)
368 MalaStringListNode node;
370 for (node = mala_stringlist_head (&self->arguments);
371 node != (void *)&self->arguments;
372 mala_stringlist_fwd (&node))
374 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
379 MalaEngine
380 mala_engine_run (MalaEngine self)
382 MalaStringListNode pptr;
384 while (self->state < MALA_EFAULT &&
385 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
387 if (self->state == MALA_LITERAL)
389 self->state = mala_engine_string_istrue (self, pptr->string)?
390 MALA_SUCCESS : MALA_FAILURE;
391 mala_stringlist_elem_remove (&self->program, pptr);
392 mala_stringlist_tail_insert (&self->arguments, pptr);
394 else
395 mala_engine_eval (self, &pptr);
397 return self;
401 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
403 MalaAction act;
404 (void) pptr;
406 act = NULL;
409 TODO
410 if (act)
411 self->state = mala_action_execute(act, pptr, self);
412 else if (self->state == MALA_EXCEPTION)
413 self->state = MALA_ENOACTION;
414 else
416 self->state = MALA_LITERAL;
417 return self->state;
421 mala_engine_expand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
423 int ret = 0;
425 MALA_DEBUG("start");
427 if (self->state > MALA_EFAULT)
428 return MALA_EXPANSION_ERROR;
430 #define mala_run_expansion(name) \
431 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
433 mala_run_expansion (literal_expansion);
434 //if (mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_LITERAL]))
435 // return 2;
437 mala_run_expansion (numsplit_expansion);
438 mala_run_expansion (exclam_expansion);
439 mala_run_expansion (no_expansion);
440 mala_run_expansion (assign_expansion);
441 mala_run_expansion (char_expansion);
442 mala_run_expansion (underscore_expansion);
443 mala_run_expansion (bracket_expansion);
444 mala_run_expansion (assign_contraction);
445 mala_run_expansion (envvar_expansion);
446 mala_run_expansion (setenv_expansion);
447 mala_run_expansion (backquote_expansion);
448 #undef mala_run_expansion
450 return 1;
454 mala_engine_literal_expansion (MalaEngine self,
455 MalaStringList list,
456 MalaStringListNode_ref pptr)
458 MALA_DEBUG("start");
459 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
460 && mala_string_check_prefix ((*pptr)->string, "`")
461 && !mala_string_check_prefix ((*pptr)->string, "``"))
463 MalaString nstr;
464 MalaStringListNode newnode1;
465 MalaStringListNode newnode2;
467 newnode1 = mala_stringlist_after_new (list,
468 *pptr,
469 self->common_string[MALA_STRING_LITERAL]);
470 if (!newnode1)
471 goto ealloc_newnode1;
473 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
474 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
475 if (!newnode2)
476 goto ealloc_newnode2;
478 mala_stringlist_elem_delete (list, pptr);
479 *pptr = newnode1;
481 return 2;
483 ealloc_newnode2:
484 mala_stringlist_elem_delete (list, &newnode1);
485 ealloc_newnode1:
486 self->state = MALA_EALLOC;
487 return MALA_EXPANSION_ERROR;
489 return MALA_NO_EXPANSION;
494 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
496 MALA_DEBUG("start");
497 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
498 && mala_string_check_prefix ((*pptr)->string, "``"))
500 MalaString nstr;
501 MalaStringListNode newnode;
503 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
504 newnode = mala_stringlist_after_new (list, *pptr, nstr);
505 if (!newnode)
506 goto ealloc_newnode;
508 mala_stringlist_elem_delete (list, pptr);
509 *pptr = newnode;
511 return 1;
513 ealloc_newnode:
514 self->state = MALA_EALLOC;
515 return MALA_EXPANSION_ERROR;
517 return MALA_NO_EXPANSION;
521 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
523 MALA_DEBUG("start");
524 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
525 && mala_string_length ((*pptr)->string) > 2
526 && mala_string_at ((*pptr)->string, 0) == '-'
527 && isalpha (mala_string_at ((*pptr)->string, 1))
530 size_t i;
532 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
534 if (isdigit (mala_string_at ((*pptr)->string, i)))
536 MalaString a;
537 MalaString b;
539 MalaStringListNode na;
540 MalaStringListNode nb;
542 a = mala_string_new_substr ((*pptr)->string, 0, i);
543 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
544 if (!a || !b)
545 goto ealloc_str;
547 na = mala_stringlist_after_new (list, *pptr, a);
548 if (!na)
549 goto ealloc_nodea;
551 nb = mala_stringlist_after_new (list, na, b);
552 if (!nb)
553 goto ealloc_nodeb;
555 mala_stringlist_elem_delete (list, pptr);
556 *pptr = na;
558 mala_string_free (a);
559 mala_string_free (b);
561 return 0;
563 ealloc_nodeb:
564 mala_stringlist_elem_delete (list, &na);
565 ealloc_nodea:
566 ealloc_str:
567 mala_string_free (a);
568 mala_string_free (b);
569 self->state = MALA_EALLOC;
570 return MALA_EXPANSION_ERROR;
574 return MALA_NO_EXPANSION;
579 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
581 MALA_DEBUG("start");
583 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
584 && mala_string_length ((*pptr)->string) == 1
585 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
587 MalaStringListNode newnode;
589 newnode = mala_stringlist_after_new (list,
590 *pptr,
591 self->common_string[MALA_STRING_NOT]);
592 if (!newnode)
593 return self->state = MALA_EALLOC;
595 mala_stringlist_elem_delete (list, pptr);
596 *pptr= newnode;
597 return 1;
599 return MALA_NO_EXPANSION;
604 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
606 MALA_DEBUG("start");
607 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
608 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
609 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
611 MalaString a;
612 MalaString aa;
613 MalaStringListNode n1;
614 MalaStringListNode n2;
616 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
617 aa = mala_string_new_prefix ("--", a);
618 if (!a || !aa)
619 goto ealloc_a;
621 n1 = mala_stringlist_after_new (list,
622 *pptr, self->common_string[MALA_STRING_NOT]);
623 if (!n1)
624 goto ealloc_n1;
626 n2 = mala_stringlist_after_new (list, n1, aa);
627 if (!n2)
628 goto ealloc_n2;
630 mala_string_free (a);
631 mala_string_free (aa);
632 mala_stringlist_elem_delete (list, pptr);
633 *pptr = n1;
634 return 1;
636 ealloc_n2:
637 mala_stringlist_elem_delete (list, &n1);
638 ealloc_n1:
639 mala_string_free (a);
640 mala_string_free (aa);
641 ealloc_a:
642 self->state = MALA_EALLOC;
643 return MALA_EXPANSION_ERROR;
645 return MALA_NO_EXPANSION;
650 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
652 size_t eq;
654 MALA_DEBUG("start");
656 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
657 && mala_string_check_prefix ((*pptr)->string, "--")
658 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
659 && mala_string_length ((*pptr)->string) > eq + 1)
661 MalaString a;
662 MalaString b;
664 MalaStringListNode na;
665 MalaStringListNode nb;
667 a = mala_string_new_substr ((*pptr)->string, 0, eq);
668 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
669 if (!a || !b)
670 goto ealloc_str;
672 na = mala_stringlist_after_new (list, *pptr, a);
673 if (!na)
674 goto ealloc_nodea;
676 nb = mala_stringlist_after_new (list, na, b);
677 if (!nb)
678 goto ealloc_nodeb;
680 mala_stringlist_elem_delete (list, pptr);
681 *pptr = na;
683 mala_string_free (a);
684 mala_string_free (b);
687 return 0;
689 ealloc_nodeb:
690 mala_stringlist_elem_delete (list, &na);
691 ealloc_nodea:
692 ealloc_str:
693 mala_string_free (a);
694 mala_string_free (b);
695 self->state = MALA_EALLOC;
696 return MALA_EXPANSION_ERROR;
698 return MALA_NO_EXPANSION;
703 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
705 MALA_DEBUG("start");
707 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
708 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
710 MalaStringListNode newnode;
712 newnode = mala_stringlist_before_new (list,
713 *pptr,
714 self->common_string[MALA_STRING_ENVSUBST]);
715 if (!newnode)
716 goto ealloc_node;
718 *pptr= newnode;
719 return 2;
721 ealloc_node:
722 self->state = MALA_EALLOC;
723 return MALA_EXPANSION_ERROR;
726 return MALA_NO_EXPANSION;
731 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
733 MALA_DEBUG("start");
734 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
735 && mala_string_length ((*pptr)->string) > 2
736 && ( mala_string_at ((*pptr)->string, 0) == '-'
737 || mala_string_at ((*pptr)->string, 0) == '+')
738 && isalpha (mala_string_at ((*pptr)->string, 1)))
740 char prefix[2] = "-";
741 char current[2] = " ";
742 const char * i;
743 int cnt = 0;
745 MalaString str;
746 MalaStringListNode node = NULL;
747 MalaStringListNode pred = *pptr;
750 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
752 if (*i == '-' || *i == '+')
753 prefix[0] = *i;
754 else if (isalpha (*i))
756 ++cnt;
757 current[0] = *i;
758 str = mala_string_new_cat2 (prefix, current,
759 mala_string_bucket_get ((*pptr)->string));
760 if (!str)
761 goto ealloc;
763 node = mala_stringlist_after_new (list,
764 pred, str);
765 if (!node)
766 goto ealloc;
768 pred = node;
769 mala_string_free (str);
771 else
772 break;
775 pred = *pptr;
776 mala_stringlist_fwd (&pred);
777 mala_stringlist_elem_delete (list, pptr);
778 *pptr= pred;
779 return cnt;
781 ealloc:
782 mala_string_free (str);
783 /* cleanup from pred downto pptr */
784 while (pred != *pptr)
786 // TODO use stringlist func
787 MalaStringListNode tmp = pred->node.cqe_prev;
788 mala_stringlist_elem_delete (list, &pred);
789 pred = tmp;
791 self->state = MALA_EALLOC;
792 return MALA_EXPANSION_ERROR;
794 return MALA_NO_EXPANSION;
799 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
801 MALA_DEBUG("start");
803 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
804 && mala_string_check_prefix ((*pptr)->string, "--")
805 && strchr (mala_string_cstr ((*pptr)->string), '_'))
807 MalaString str;
808 MalaStringListNode node;
809 char * cstr;
810 char * i;
812 cstr = strdup (mala_string_cstr ((*pptr)->string));
813 if (!cstr)
814 goto ealloc_cstr;
816 for (i = cstr + 2; *i; ++i)
818 if (*i == '_')
819 *i = '-';
822 str = mala_string_new (cstr, &self->words);
823 if (!str)
824 goto ealloc_str;
826 node = mala_stringlist_after_new (list,
827 *pptr,
828 str);
829 if (!node)
830 goto ealloc_node;
832 free (cstr);
833 mala_string_free (str);
835 mala_stringlist_elem_delete (list, pptr);
836 *pptr= node;
837 return 0;
839 ealloc_node:
840 mala_string_free (str);
841 ealloc_str:
842 free (cstr);
843 ealloc_cstr:
844 self->state = MALA_EALLOC;
845 return MALA_EXPANSION_ERROR;
847 return MALA_NO_EXPANSION;
852 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
854 unsigned eq;
856 MALA_DEBUG("start");
858 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
859 && mala_string_length ((*pptr)->string) > 1
860 && (eq = mala_string_char_find ((*pptr)->string, '='))
861 && eq > 0
862 && eq < SIZE_MAX
863 && !mala_string_check_prefix ((*pptr)->string, "-"))
865 MalaString key;
866 MalaString value;
867 MalaStringListNode n1;
868 MalaStringListNode n2;
869 MalaStringListNode n3;
871 key = mala_string_new_substr ((*pptr)->string, 0, eq);
872 if (!key)
873 goto ealloc_key;
875 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
876 if (!value)
877 goto ealloc_value;
879 n1 = mala_stringlist_after_new (list,
880 *pptr, self->common_string[MALA_STRING_SETENV]);
881 if (!n1)
882 goto ealloc_n1;
884 n2 = mala_stringlist_after_new (list, n1, key);
885 if (!n2)
886 goto ealloc_n2;
888 n3 = mala_stringlist_after_new (list, n2, value);
889 if (!n3)
890 goto ealloc_n3;
892 mala_string_free (key);
893 mala_string_free (value);
894 mala_stringlist_elem_delete (list, pptr);
895 *pptr = n1;
896 return 3;
898 ealloc_n3:
899 mala_stringlist_elem_delete (list, &n2);
900 ealloc_n2:
901 mala_stringlist_elem_delete (list, &n1);
902 ealloc_n1:
903 mala_string_free (value);
904 ealloc_value:
905 mala_string_free (key);
906 ealloc_key:
907 self->state = MALA_EALLOC;
908 return MALA_EXPANSION_ERROR;
910 return MALA_NO_EXPANSION;
915 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
917 MALA_DEBUG("start");
918 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
919 && mala_string_at ((*pptr)->string, 0) == '[')
921 MalaStringListNode nitr;
922 MalaStringListNode node;
924 MalaString str1 = NULL;
925 MalaStringListNode node1;
927 MalaString str2 = NULL;
928 MalaStringListNode node2;
930 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
931 if (!node)
932 goto ealloc_node;
934 if (mala_string_length((*pptr)->string) > 1)
936 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
937 node1 = mala_stringlist_after_new (list, node, str1);
938 if (!node1)
939 goto ealloc_node1;
941 else
943 node1 = node;
944 mala_stringlist_fwd (&node1);
947 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlist_fwd (&nitr))
949 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
950 break;
953 if ((void*)nitr != (void*)list)
955 if (mala_string_length(nitr->string) > 1)
957 str2 = mala_string_new_substr (nitr->string, 0,
958 mala_string_length(nitr->string) - 1);
959 node2 = mala_stringlist_after_new (list, nitr, str2);
960 if (!node2)
961 goto ealloc_node2;
964 else
965 goto esyntax;
968 mala_string_free (str1);
969 mala_string_free (str2);
970 mala_stringlist_elem_delete (list, pptr);
971 mala_stringlist_elem_delete (list, &nitr);
972 *pptr = node;
974 return 0;
976 esyntax:
977 mala_string_free (str1);
978 mala_stringlist_elem_delete (list, &node1);
979 mala_stringlist_elem_delete (list, &node);
980 self->state = MALA_ESYNTAX;
981 return MALA_EXPANSION_ERROR;
983 ealloc_node2:
984 mala_string_free (str1);
985 mala_stringlist_elem_delete (list, &node1);
986 ealloc_node1:
987 mala_stringlist_elem_delete (list, &node);
988 ealloc_node:
989 self->state = MALA_EALLOC;
990 return MALA_EXPANSION_ERROR;
992 return MALA_NO_EXPANSION;
997 mala_engine_assign_contraction (MalaEngine self,
998 MalaStringList list,
999 MalaStringListNode_ref pptr)
1001 MalaStringListNode assign;
1002 MalaStringListNode value ;
1004 MALA_DEBUG("start");
1006 assign = *pptr;
1007 mala_stringlist_fwd (&assign);
1008 value = assign;
1010 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1011 && !mala_stringlist_is_tail (list, *pptr)
1012 && !mala_stringlist_is_tail (list, assign)
1013 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1015 MalaString str;
1016 MalaStringListNode node;
1018 mala_stringlist_fwd (&value);
1020 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1021 "%s=%s",
1022 mala_string_cstr ((*pptr)->string),
1023 mala_string_cstr (value->string));
1026 node = mala_stringlist_after_new (list,
1027 value,
1028 str);
1029 if (!node)
1030 goto ealloc_node;
1032 mala_string_free (str);
1033 mala_stringlist_elem_delete (list, pptr);
1034 mala_stringlist_elem_delete (list, &assign);
1035 mala_stringlist_elem_delete (list, &value);
1036 *pptr = node;
1037 return 0;
1039 ealloc_node:
1040 mala_string_free (str);
1041 self->state = MALA_EALLOC;
1042 return MALA_EXPANSION_ERROR;
1044 return MALA_NO_EXPANSION;
1051 mala_engine_string_istrue (MalaEngine self, MalaString str)
1053 if (!str
1054 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1055 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1056 return 0;
1058 return 1;
1062 mala_engine_check_expansionflag (MalaEngine self, int flag)
1064 MalaActionDesc desc;
1065 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1066 if (!desc)
1067 return 0;
1069 /*only enabled when the topmost action is a subtitution to --TRUE*/
1070 if (desc->actions.lh_first)
1071 return desc->actions.lh_first->data == self->common_string[MALA_STRING_TRUE];
1073 return 0;
1088 #if 0 /*TODO*/
1090 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1092 MalaAction act;
1094 if (self->state > MALA_EFAULT)
1095 return self->state;
1097 act = mala_actiondict_lookupaction (self->actions, key);
1098 if (!act)
1099 goto enoact;
1101 mala_actiondict_destroy_action (self->actions, act);
1103 return MALA_SUCCESS;
1105 enoact:
1106 self->state = MALA_ENOACTION;
1107 return self->state;
1113 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1115 MalaStringListNode base = llist_get_prev (pptr);
1116 while (mala_engine_eval (self, llist_get_next (base)) < MALA_EVAL)
1117 if (llist_get_next (base) == &self->program)
1118 return MALA_ENOACTION;
1120 return self->state;
1125 void
1126 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1128 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1134 mala_engine_argc (MalaEngine self)
1136 return llist_count (&self->arguments) + 1;
1139 const char*
1140 mala_engine_argv (MalaEngine self, int n)
1142 MalaStringListNode p;
1143 p = llist_get_next (&self->arguments);
1145 if (n==0)
1146 return self->argv_0;
1148 while (--n)
1150 if (p == &self->arguments)
1151 return 0;
1152 p = llist_get_next (p);
1154 return (const char *)(p)->data;
1160 mala_engine_exception (MalaEngine self, MalaStringListNode begin, MalaStringListNode end, const char * excpt)
1162 self->state = mala_strlist_insert_before (begin, excpt);
1163 if (self->state > MALA_EFAULT)
1164 return self->state;
1166 self->state = mala_strlist_insert_after_cat2 (end, "--HERE", excpt+1);
1167 if (self->state > MALA_EFAULT)
1168 return self->state;
1170 return self->state = MALA_EXCEPTION;
1174 MalaAction
1175 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1176 MalaParserFunc parser, MalaDataDestructor destructor)
1178 MalaAction act;
1180 act = mala_action_new (name, data, parser, destructor);
1181 if (!act)
1182 goto ealloc;
1184 self->state = mala_actiondict_push (self->actions, act);
1185 if (self->state)
1186 goto epush;
1188 return act;
1190 epush:
1191 mala_action_destroy (act);
1192 ealloc:
1193 return 0;
1197 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1199 MalaAction act;
1201 act = mala_actiondict_lookupaction (self->actions, name);
1202 if (!act)
1203 return MALA_NO_EXPANSION;
1205 if (act->parser != mala_substitute_parser)
1206 return MALA_EPARSER;
1208 return mala_string_check ((t_uchar*) act->data);
1212 MalaAction
1213 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1215 return mala_actiondict_lookupaction (self->actions, name);
1218 MalaAction
1219 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1221 return mala_actiondict_lookupprevaction (self->actions, name);
1224 #endif /*TODO*/
1231 // Local Variables:
1232 // mode: C
1233 // c-file-style: "gnu"
1234 // End:
1235 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1236 // end_of_file