literal_parser
[mala.git] / engine / engine.c
blob115d0ea2ade64ce5577349e15fffbe8b4756981e
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 "--FLAG-LITERAL-EXPANSION",
47 "--FLAG-EXCLAM-EXPANSION",
48 "--FLAG-NO-EXPANSION",
49 "--FLAG-NUMSPLIT-EXPANSION",
50 "--FLAG-CHAR-EXPANSION",
51 "--FLAG-ASSIGN-EXPANSION",
52 "--FLAG-SETENV-EXPANSION",
53 "--FLAG-ENVVAR-EXPANSION",
54 "--FLAG-UNDERSCORE-EXPANSION",
55 "--FLAG-BRACKET-EXPANSION",
56 "--FLAG-ASSIGN-CONTRACTION",
57 "--ERROR-MISSING-ARGUMENT",
58 NULL
65 * function definitions
68 MalaEngine
69 mala_engine_new ()
71 MalaEngine self;
72 int i;
74 self = malloc (sizeof(mala_engine));
75 if (!self)
76 return NULL;
78 self->negated = 0;
80 self->state = MALA_SUCCESS;
82 mala_stringbucket_init (&self->words, MALA_STRING_FWD, (void(*)(void*)) mala_actiondesc_free);
84 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
86 self->common_string[i] = mala_string_new (mala_common_strings[i], &self->words);
87 if (!self->common_string[i])
88 goto ealloc_strings;
91 mala_stringlist_init (&self->program);
92 mala_stringlist_init (&self->arguments);
94 return self;
96 ealloc_strings:
97 while (--i >= 0)
98 mala_string_free (self->common_string[i]);
99 free (self);
100 return NULL;
103 #if 0
104 MalaEngine
105 mala_engine_new_main (int (*initfunc) (MalaEngine),
106 int argc, char **argv,
107 mala_actioninit * actions_init)
109 /*TODO convinience function*/
111 #endif
114 mala_engine_macro_define (MalaEngine self, const char * name, int argc, char ** argv)
116 int i;
117 MalaStringList list;
118 MalaStringListNode itr;
119 int mexp = 0;
120 mala_stringlist pre;
122 if(!self)
123 return MALA_EINVALID;
124 if(self->state > MALA_EFAULT)
125 return self->state;
127 mala_stringlist_init (&pre);
129 for (i = 0; i != argc && *argv; ++i ,++argv)
131 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
132 goto ealloc_node;
135 list = mala_stringlist_new ();
136 if (!list)
137 goto ealloc_list;
139 /*TODO preprocess in own function*/
140 while (!mala_stringlist_is_empty (&pre))
142 int putaway;
144 itr = mala_stringlist_head (&pre);
146 putaway = mala_engine_expand (self, &pre, &itr);
148 if (self->state > MALA_EFAULT)
149 return self->state;
151 while (putaway--)
153 mala_stringlist_node_remove (&pre, itr);
154 mala_stringlist_tail_insert (list, itr);
155 if (putaway && mala_stringlist_is_empty (&pre))
156 goto eunderrun;
157 itr = mala_stringlist_head (&pre);
161 if (mala_stringlist_is_empty (list))
163 /* empty substituted by --NULL, TODO use empty string instead? */
164 mala_stringlist_free (list);
165 return mala_engine_add_action (self, name,
166 mala_string_copy(self->common_string[MALA_STRING_NULL]),
167 mala_substitute_parser,
168 (MalaDataFactory)mala_string_factory,
169 NULL);
173 for (itr = mala_stringlist_head (list);
174 !mala_stringlist_is_end (list, itr);
175 mala_stringlist_fwd(&itr))
176 if (mala_string_char_find (itr->string, '%') != SIZE_MAX)
178 mexp = 1;
179 break;
182 if (mexp)
184 /* macro */
185 return mala_engine_add_action (self, name, list,
186 mala_macro_parser,
187 (MalaDataFactory)mala_stringlist_factory,
188 NULL);
190 else if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
192 /* substitute */
193 MalaString subst;
195 subst = mala_string_copy (mala_stringlist_head (list) -> string);
196 mala_stringlist_free (list);
198 return mala_engine_add_action (self, name, subst,
199 mala_substitute_parser,
200 (MalaDataFactory)mala_string_factory,
201 NULL);
203 else
205 /* expand */
206 return mala_engine_add_action (self, name, list,
207 mala_expand_parser,
208 (MalaDataFactory) mala_stringlist_factory,
209 NULL);
212 eunderrun:
213 mala_stringlist_free (list);
214 mala_stringlist_erase (&pre);
215 return self->state = MALA_ESYNTAX;
217 ealloc_list:
218 ealloc_node:
219 mala_stringlist_erase (&pre);
220 return self->state = MALA_EALLOC;
224 mala_engine_pushback_word (MalaEngine self, const char * word)
226 if(!self)
227 return MALA_EINVALID;
228 if(self->state > MALA_EFAULT)
229 return self->state;
231 if (!mala_stringlist_tail_new_cstr (&self->program, word, &self->words))
232 return self->state = MALA_EALLOC;
234 return MALA_SUCCESS;
238 mala_engine_add_action (MalaEngine self, const char * cname, void * data,
239 MalaParserFunc parser, MalaDataFactory factory,
240 MalaAction parent)
242 MalaString name;
243 MalaAction action;
245 /*TODO such checks everywhere*/
246 if(!self)
247 return MALA_EINVALID;
248 if(self->state > MALA_EFAULT)
249 return self->state;
251 name = mala_string_new (cname, &self->words);
252 if (!name)
253 goto ealloc_name;
255 action = mala_action_new (name, data, parser, factory, parent);
256 if (!action)
257 goto ealloc_action;
259 if (mala_action_attach (action) != MALA_SUCCESS)
260 goto ealloc_attach;
262 mala_string_free (name);
263 return MALA_SUCCESS;
265 ealloc_attach:
266 mala_action_free (action);
267 ealloc_action:
268 mala_string_free (name);
269 ealloc_name:
270 return self->state = MALA_EALLOC;
274 MalaEngine
275 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
277 MalaEngine self;
279 self = mala_engine_new ();
280 if (!self)
281 return 0;
283 self->state = initfunc (self);
284 return self;
287 void
288 mala_engine_free (MalaEngine self)
290 int i;
292 if (!self)
293 return;
295 mala_stringlist_erase (&self->program);
296 mala_stringlist_erase (&self->arguments);
298 mala_stringbucket_erase (&self->words);
300 for (i = 0; i < MALA_MAX_COMMON_STRING; ++i)
301 mala_string_free (self->common_string[i]);
303 free (self);
307 mala_engine_actions_register (MalaEngine self, mala_actioninit * actioninit)
309 MalaAction action;
311 if (!self)
312 return MALA_EINVALID;
314 if (self->state > MALA_EFAULT)
315 return self->state;
317 while (actioninit->command)
319 action = mala_action_new_actioninit (actioninit, &self->words);
320 if (!action)
321 goto ealloc;
323 if (mala_action_attach (action) != MALA_SUCCESS)
324 goto ealloc;
326 ++actioninit;
329 return MALA_SUCCESS;
331 ealloc:
332 return self->state = MALA_EINIT;
336 /*TODO make some inlines { */
338 MalaStringList
339 mala_engine_getprogram (MalaEngine self)
341 return &self->program;
344 mala_state
345 mala_engine_state_get (MalaEngine self)
347 return self->state;
350 void
351 mala_engine_clearstate (MalaEngine self)
353 self->state = MALA_SUCCESS;
357 mala_engine_negated (MalaEngine self)
359 return self->negated;
362 void
363 mala_engine_clear_negated (MalaEngine self)
365 self->negated = 0;
367 /* } TODO make some inlines */
370 void
371 mala_engine_dumpprogram (MalaEngine self, const char * prefix, const char * suffix)
373 MalaStringListNode node;
375 for (node = mala_stringlist_head (&self->program);
376 node != (void *)&self->program;
377 mala_stringlist_fwd (&node))
379 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
383 void
384 mala_engine_dumpargs (MalaEngine self, const char * prefix, const char * suffix)
386 MalaStringListNode node;
388 for (node = mala_stringlist_head (&self->arguments);
389 node != (void *)&self->arguments;
390 mala_stringlist_fwd (&node))
392 fprintf (stderr, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
397 MalaEngine
398 mala_engine_run (MalaEngine self)
400 MalaStringListNode pptr;
402 while (self->state < MALA_EFAULT &&
403 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
405 if (self->state == MALA_LITERAL)
407 self->state = (mala_engine_string_istrue (self, pptr->string) ^ self->negated)?
408 MALA_SUCCESS : MALA_FAILURE;
409 mala_stringlist_elem_remove (&self->program, pptr);
410 mala_stringlist_tail_insert (&self->arguments, pptr);
412 else
413 mala_engine_eval (self, &pptr);
415 return self;
419 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
421 MalaAction act;
422 MalaActionDesc desc;
424 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
425 if (!desc)
426 return self->state = MALA_LITERAL;
428 act = mala_actiondesc_top (desc);
430 if (act)
431 self->state = mala_action_execute(act, pptr, self);
433 if (self->state == MALA_EXCEPTION)
434 self->state = MALA_ENOACTION;
436 return self->state;
439 void
440 mala_engine_try_eval_arg_n (MalaEngine self, MalaStringListNode_ref pptr, unsigned n)
442 MalaStringListNode next;
443 for (next = *pptr;
444 n && !mala_stringlist_is_tail (&self->program, next);
445 mala_stringlist_fwd (&next), --n);
447 while (!mala_stringlist_is_tail (&self->program, *pptr) && self->state < MALA_EXCEPTION)
449 mala_engine_eval (self, &next);
454 mala_engine_exception (MalaEngine self,
455 MalaStringListNode_ref pptr,
456 MalaStringListNode here,
457 MalaString except)
459 MalaStringListNode tmp;
461 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
462 if (!tmp)
463 return self->state = MALA_EALLOC;
465 if (!mala_stringlist_after_new (&self->program, here,
466 self->common_string[MALA_STRING_HERE]))
467 return self->state = MALA_EALLOC;
469 *pptr = tmp;
471 /*TODO self-state needs to be preserved somehow?*/
472 return self->state = MALA_EXCEPTION;
477 mala_engine_expand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
479 int ret = 0;
481 if (self->state > MALA_EFAULT)
482 return MALA_EXPANSION_ERROR;
484 #define mala_run_expansion(name) \
485 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
487 mala_run_expansion (literal_expansion);
488 mala_run_expansion (numsplit_expansion);
489 mala_run_expansion (exclam_expansion);
490 mala_run_expansion (no_expansion);
491 mala_run_expansion (assign_expansion);
492 mala_run_expansion (char_expansion);
493 mala_run_expansion (underscore_expansion);
494 mala_run_expansion (bracket_expansion);
495 mala_run_expansion (assign_contraction);
496 mala_run_expansion (envvar_expansion);
497 mala_run_expansion (setenv_expansion);
498 mala_run_expansion (backquote_expansion);
499 #undef mala_run_expansion
501 return 1;
505 mala_engine_literal_expansion (MalaEngine self,
506 MalaStringList list,
507 MalaStringListNode_ref pptr)
509 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
510 && mala_string_check_prefix ((*pptr)->string, "`")
511 && !mala_string_check_prefix ((*pptr)->string, "``"))
513 MalaString nstr;
514 MalaStringListNode newnode1;
515 MalaStringListNode newnode2;
517 newnode1 = mala_stringlist_after_new (list,
518 *pptr,
519 self->common_string[MALA_STRING_LITERAL]);
520 if (!newnode1)
521 goto ealloc_newnode1;
523 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
524 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
525 if (!newnode2)
526 goto ealloc_newnode2;
528 mala_stringlist_elem_delete (list, pptr);
529 *pptr = newnode1;
531 return 2;
533 ealloc_newnode2:
534 mala_stringlist_elem_delete (list, &newnode1);
535 ealloc_newnode1:
536 self->state = MALA_EALLOC;
537 return MALA_EXPANSION_ERROR;
539 return MALA_NO_EXPANSION;
544 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
546 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
547 && mala_string_check_prefix ((*pptr)->string, "``"))
549 MalaString nstr;
550 MalaStringListNode newnode;
552 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
553 newnode = mala_stringlist_after_new (list, *pptr, nstr);
554 if (!newnode)
555 goto ealloc_newnode;
557 mala_stringlist_elem_delete (list, pptr);
558 *pptr = newnode;
560 return 1;
562 ealloc_newnode:
563 self->state = MALA_EALLOC;
564 return MALA_EXPANSION_ERROR;
566 return MALA_NO_EXPANSION;
570 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
572 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
573 && mala_string_length ((*pptr)->string) > 2
574 && mala_string_at ((*pptr)->string, 0) == '-'
575 && isalpha (mala_string_at ((*pptr)->string, 1))
578 size_t i;
580 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
582 if (isdigit (mala_string_at ((*pptr)->string, i)))
584 MalaString a;
585 MalaString b;
587 MalaStringListNode na;
588 MalaStringListNode nb;
590 a = mala_string_new_substr ((*pptr)->string, 0, i);
591 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
592 if (!a || !b)
593 goto ealloc_str;
595 na = mala_stringlist_after_new (list, *pptr, a);
596 if (!na)
597 goto ealloc_nodea;
599 nb = mala_stringlist_after_new (list, na, b);
600 if (!nb)
601 goto ealloc_nodeb;
603 mala_stringlist_elem_delete (list, pptr);
604 *pptr = na;
606 mala_string_free (a);
607 mala_string_free (b);
609 return 0;
611 ealloc_nodeb:
612 mala_stringlist_elem_delete (list, &na);
613 ealloc_nodea:
614 ealloc_str:
615 mala_string_free (a);
616 mala_string_free (b);
617 self->state = MALA_EALLOC;
618 return MALA_EXPANSION_ERROR;
622 return MALA_NO_EXPANSION;
627 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
629 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
630 && mala_string_length ((*pptr)->string) == 1
631 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
633 MalaStringListNode newnode;
635 newnode = mala_stringlist_after_new (list,
636 *pptr,
637 self->common_string[MALA_STRING_NOT]);
638 if (!newnode)
639 return self->state = MALA_EALLOC;
641 mala_stringlist_elem_delete (list, pptr);
642 *pptr= newnode;
643 return 1;
645 return MALA_NO_EXPANSION;
650 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
652 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
653 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
654 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
656 MalaString a;
657 MalaString aa;
658 MalaStringListNode n1;
659 MalaStringListNode n2;
661 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
662 aa = mala_string_new_prefix ("--", a);
663 if (!a || !aa)
664 goto ealloc_a;
666 n1 = mala_stringlist_after_new (list,
667 *pptr, self->common_string[MALA_STRING_NOT]);
668 if (!n1)
669 goto ealloc_n1;
671 n2 = mala_stringlist_after_new (list, n1, aa);
672 if (!n2)
673 goto ealloc_n2;
675 mala_string_free (a);
676 mala_string_free (aa);
677 mala_stringlist_elem_delete (list, pptr);
678 *pptr = n1;
679 return 1;
681 ealloc_n2:
682 mala_stringlist_elem_delete (list, &n1);
683 ealloc_n1:
684 mala_string_free (a);
685 mala_string_free (aa);
686 ealloc_a:
687 self->state = MALA_EALLOC;
688 return MALA_EXPANSION_ERROR;
690 return MALA_NO_EXPANSION;
695 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
697 size_t eq;
699 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
700 && mala_string_check_prefix ((*pptr)->string, "--")
701 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
702 && mala_string_length ((*pptr)->string) > eq + 1)
704 MalaString a;
705 MalaString b;
707 MalaStringListNode na;
708 MalaStringListNode nb;
710 a = mala_string_new_substr ((*pptr)->string, 0, eq);
711 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
712 if (!a || !b)
713 goto ealloc_str;
715 na = mala_stringlist_after_new (list, *pptr, a);
716 if (!na)
717 goto ealloc_nodea;
719 nb = mala_stringlist_after_new (list, na, b);
720 if (!nb)
721 goto ealloc_nodeb;
723 mala_stringlist_elem_delete (list, pptr);
724 *pptr = na;
726 mala_string_free (a);
727 mala_string_free (b);
730 return 0;
732 ealloc_nodeb:
733 mala_stringlist_elem_delete (list, &na);
734 ealloc_nodea:
735 ealloc_str:
736 mala_string_free (a);
737 mala_string_free (b);
738 self->state = MALA_EALLOC;
739 return MALA_EXPANSION_ERROR;
741 return MALA_NO_EXPANSION;
746 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
748 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
749 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
751 MalaStringListNode newnode;
753 newnode = mala_stringlist_before_new (list,
754 *pptr,
755 self->common_string[MALA_STRING_ENVSUBST]);
756 if (!newnode)
757 goto ealloc_node;
759 *pptr= newnode;
760 return 2;
762 ealloc_node:
763 self->state = MALA_EALLOC;
764 return MALA_EXPANSION_ERROR;
767 return MALA_NO_EXPANSION;
772 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
774 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
775 && mala_string_length ((*pptr)->string) > 2
776 && ( mala_string_at ((*pptr)->string, 0) == '-'
777 || mala_string_at ((*pptr)->string, 0) == '+')
778 && isalpha (mala_string_at ((*pptr)->string, 1)))
780 char prefix[2] = "-";
781 char current[2] = " ";
782 const char * i;
783 int cnt = 0;
785 MalaString str;
786 MalaStringListNode node = NULL;
787 MalaStringListNode pred = *pptr;
790 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
792 if (*i == '-' || *i == '+')
793 prefix[0] = *i;
794 else if (isalpha (*i))
796 ++cnt;
797 current[0] = *i;
798 str = mala_string_new_cat2 (prefix, current,
799 mala_string_bucket_get ((*pptr)->string));
800 if (!str)
801 goto ealloc;
803 node = mala_stringlist_after_new (list,
804 pred, str);
805 if (!node)
806 goto ealloc;
808 pred = node;
809 mala_string_free (str);
811 else
812 break;
815 pred = *pptr;
816 mala_stringlist_fwd (&pred);
817 mala_stringlist_elem_delete (list, pptr);
818 *pptr= pred;
819 return cnt;
821 ealloc:
822 mala_string_free (str);
823 /* cleanup from pred downto pptr */
824 while (pred != *pptr)
826 // TODO use stringlist func
827 MalaStringListNode tmp = pred->node.cqe_prev;
828 mala_stringlist_elem_delete (list, &pred);
829 pred = tmp;
831 self->state = MALA_EALLOC;
832 return MALA_EXPANSION_ERROR;
834 return MALA_NO_EXPANSION;
839 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
841 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
842 && mala_string_check_prefix ((*pptr)->string, "--")
843 && strchr (mala_string_cstr ((*pptr)->string), '_'))
845 MalaString str;
846 MalaStringListNode node;
847 char * cstr;
848 char * i;
850 cstr = strdup (mala_string_cstr ((*pptr)->string));
851 if (!cstr)
852 goto ealloc_cstr;
854 for (i = cstr + 2; *i; ++i)
856 if (*i == '_')
857 *i = '-';
860 str = mala_string_new (cstr, &self->words);
861 if (!str)
862 goto ealloc_str;
864 node = mala_stringlist_after_new (list,
865 *pptr,
866 str);
867 if (!node)
868 goto ealloc_node;
870 free (cstr);
871 mala_string_free (str);
873 mala_stringlist_elem_delete (list, pptr);
874 *pptr= node;
875 return 0;
877 ealloc_node:
878 mala_string_free (str);
879 ealloc_str:
880 free (cstr);
881 ealloc_cstr:
882 self->state = MALA_EALLOC;
883 return MALA_EXPANSION_ERROR;
885 return MALA_NO_EXPANSION;
890 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
892 unsigned eq;
894 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
895 && mala_string_length ((*pptr)->string) > 1
896 && (eq = mala_string_char_find ((*pptr)->string, '='))
897 && eq > 0
898 && eq < SIZE_MAX
899 && !mala_string_check_prefix ((*pptr)->string, "-"))
901 MalaString key;
902 MalaString value;
903 MalaStringListNode n1;
904 MalaStringListNode n2;
905 MalaStringListNode n3;
907 key = mala_string_new_substr ((*pptr)->string, 0, eq);
908 if (!key)
909 goto ealloc_key;
911 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
912 if (!value)
913 goto ealloc_value;
915 n1 = mala_stringlist_after_new (list,
916 *pptr, self->common_string[MALA_STRING_SETENV]);
917 if (!n1)
918 goto ealloc_n1;
920 n2 = mala_stringlist_after_new (list, n1, key);
921 if (!n2)
922 goto ealloc_n2;
924 n3 = mala_stringlist_after_new (list, n2, value);
925 if (!n3)
926 goto ealloc_n3;
928 mala_string_free (key);
929 mala_string_free (value);
930 mala_stringlist_elem_delete (list, pptr);
931 *pptr = n1;
932 return 3;
934 ealloc_n3:
935 mala_stringlist_elem_delete (list, &n2);
936 ealloc_n2:
937 mala_stringlist_elem_delete (list, &n1);
938 ealloc_n1:
939 mala_string_free (value);
940 ealloc_value:
941 mala_string_free (key);
942 ealloc_key:
943 self->state = MALA_EALLOC;
944 return MALA_EXPANSION_ERROR;
946 return MALA_NO_EXPANSION;
951 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
953 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
954 && mala_string_at ((*pptr)->string, 0) == '[')
956 MalaStringListNode nitr;
957 MalaStringListNode node;
959 MalaString str1 = NULL;
960 MalaStringListNode node1;
962 MalaString str2 = NULL;
963 MalaStringListNode node2;
965 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
966 if (!node)
967 goto ealloc_node;
969 if (mala_string_length((*pptr)->string) > 1)
971 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
972 node1 = mala_stringlist_after_new (list, node, str1);
973 if (!node1)
974 goto ealloc_node1;
976 else
978 node1 = node;
979 mala_stringlist_fwd (&node1);
982 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlist_fwd (&nitr))
984 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
985 break;
988 if ((void*)nitr != (void*)list)
990 if (mala_string_length(nitr->string) > 1)
992 str2 = mala_string_new_substr (nitr->string, 0,
993 mala_string_length(nitr->string) - 1);
994 node2 = mala_stringlist_after_new (list, nitr, str2);
995 if (!node2)
996 goto ealloc_node2;
999 else
1000 goto esyntax;
1003 mala_string_free (str1);
1004 mala_string_free (str2);
1005 mala_stringlist_elem_delete (list, pptr);
1006 mala_stringlist_elem_delete (list, &nitr);
1007 *pptr = node;
1009 return 0;
1011 esyntax:
1012 mala_string_free (str1);
1013 mala_stringlist_elem_delete (list, &node1);
1014 mala_stringlist_elem_delete (list, &node);
1015 self->state = MALA_ESYNTAX;
1016 return MALA_EXPANSION_ERROR;
1018 ealloc_node2:
1019 mala_string_free (str1);
1020 mala_stringlist_elem_delete (list, &node1);
1021 ealloc_node1:
1022 mala_stringlist_elem_delete (list, &node);
1023 ealloc_node:
1024 self->state = MALA_EALLOC;
1025 return MALA_EXPANSION_ERROR;
1027 return MALA_NO_EXPANSION;
1032 mala_engine_assign_contraction (MalaEngine self,
1033 MalaStringList list,
1034 MalaStringListNode_ref pptr)
1036 MalaStringListNode assign;
1037 MalaStringListNode value ;
1039 assign = *pptr;
1040 mala_stringlist_fwd (&assign);
1041 value = assign;
1043 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1044 && !mala_stringlist_is_tail (list, *pptr)
1045 && !mala_stringlist_is_tail (list, assign)
1046 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1048 MalaString str;
1049 MalaStringListNode node;
1051 mala_stringlist_fwd (&value);
1053 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1054 "%s=%s",
1055 mala_string_cstr ((*pptr)->string),
1056 mala_string_cstr (value->string));
1059 node = mala_stringlist_after_new (list,
1060 value,
1061 str);
1062 if (!node)
1063 goto ealloc_node;
1065 mala_string_free (str);
1066 mala_stringlist_elem_delete (list, pptr);
1067 mala_stringlist_elem_delete (list, &assign);
1068 mala_stringlist_elem_delete (list, &value);
1069 *pptr = node;
1070 return 0;
1072 ealloc_node:
1073 mala_string_free (str);
1074 self->state = MALA_EALLOC;
1075 return MALA_EXPANSION_ERROR;
1077 return MALA_NO_EXPANSION;
1084 mala_engine_string_istrue (MalaEngine self, MalaString str)
1086 if (!str
1087 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1088 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1089 return 0;
1091 return 1;
1095 mala_engine_check_expansionflag (MalaEngine self, int flag)
1097 MalaActionDesc desc;
1098 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1099 if (!desc)
1100 return 0;
1102 /*only enabled when the topmost action is a subtitution to --TRUE*/
1103 if (desc->actions.lh_first)
1104 return desc->actions.lh_first->data == self->common_string[MALA_STRING_TRUE];
1106 return 0;
1121 #if 0 /*TODO*/
1123 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1125 MalaAction act;
1127 if (self->state > MALA_EFAULT)
1128 return self->state;
1130 act = mala_actiondict_lookupaction (self->actions, key);
1131 if (!act)
1132 goto enoact;
1134 mala_actiondict_destroy_action (self->actions, act);
1136 return MALA_SUCCESS;
1138 enoact:
1139 self->state = MALA_ENOACTION;
1140 return self->state;
1146 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1148 MalaStringListNode base = llist_get_prev (pptr);
1149 while (mala_engine_eval (self, llist_get_next (base)) < MALA_EVAL)
1150 if (llist_get_next (base) == &self->program)
1151 return MALA_ENOACTION;
1153 return self->state;
1158 void
1159 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1161 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1167 mala_engine_argc (MalaEngine self)
1169 return llist_count (&self->arguments) + 1;
1172 const char*
1173 mala_engine_argv (MalaEngine self, int n)
1175 MalaStringListNode p;
1176 p = llist_get_next (&self->arguments);
1178 if (n==0)
1179 return self->argv_0;
1181 while (--n)
1183 if (p == &self->arguments)
1184 return 0;
1185 p = llist_get_next (p);
1187 return (const char *)(p)->data;
1192 MalaAction
1193 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1194 MalaParserFunc parser, MalaDataDestructor destructor)
1196 MalaAction act;
1198 act = mala_action_new (name, data, parser, destructor);
1199 if (!act)
1200 goto ealloc;
1202 self->state = mala_actiondict_push (self->actions, act);
1203 if (self->state)
1204 goto epush;
1206 return act;
1208 epush:
1209 mala_action_destroy (act);
1210 ealloc:
1211 return 0;
1215 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1217 MalaAction act;
1219 act = mala_actiondict_lookupaction (self->actions, name);
1220 if (!act)
1221 return MALA_NO_EXPANSION;
1223 if (act->parser != mala_substitute_parser)
1224 return MALA_EPARSER;
1226 return mala_string_check ((t_uchar*) act->data);
1230 MalaAction
1231 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1233 return mala_actiondict_lookupaction (self->actions, name);
1236 MalaAction
1237 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1239 return mala_actiondict_lookupprevaction (self->actions, name);
1242 #endif /*TODO*/
1249 // Local Variables:
1250 // mode: C
1251 // c-file-style: "gnu"
1252 // End:
1253 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1254 // end_of_file