new macro semantics with %n and %-n
[mala.git] / engine / engine.c
blobbd8b553d352160674f7273d043a467d4dd7fd395
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 #define MALA_EXPAND(e,S) S
32 static const char * mala_common_strings [] = MALA_COMMON_STRINGS;
33 #undef MALA_EXPAND
37 * function definitions
40 MalaEngine
41 mala_engine_new ()
43 MalaEngine self;
44 int i;
46 self = malloc (sizeof(mala_engine));
47 if (!self)
48 return NULL;
50 self->negated = 0;
51 self->blockcnt = 0;
53 self->state = MALA_SUCCESS;
55 mala_stringbucket_init (&self->words, MALA_STRING_FWD, (void(*)(void*)) mala_actiondesc_free);
57 for (i = 0; i < MALA_STRING_MAX; ++i)
59 self->common_string[i] = mala_string_new (mala_common_strings[i], &self->words);
60 if (!self->common_string[i])
61 goto ealloc_strings;
64 mala_stringlist_init (&self->program);
65 mala_stringlist_init (&self->arguments);
67 return self;
69 ealloc_strings:
70 while (--i >= 0)
71 mala_string_free (self->common_string[i]);
72 free (self);
73 return NULL;
76 #if 0
77 MalaEngine
78 mala_engine_new_main (int (*initfunc) (MalaEngine),
79 int argc, char **argv,
80 mala_actioninit * actions_init)
82 /*TODO convinience function*/
84 #endif
86 int
87 mala_engine_expand_define (MalaEngine self, const char * name, int argc, char ** argv)
89 int i;
90 MalaStringList list;
91 MalaStringListNode itr;
92 mala_stringlist pre;
94 if(!self)
95 return MALA_EINVALID;
96 if(self->state > MALA_EFAULT)
97 return self->state;
99 mala_stringlist_init (&pre);
101 for (i = 0; i != argc && *argv; ++i ,++argv)
103 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
104 goto ealloc_node;
107 list = mala_stringlist_new ();
108 if (!list)
109 goto ealloc_list;
111 /*TODO preprocess in own function*/
112 while (!mala_stringlist_is_empty (&pre))
114 int putaway;
116 itr = mala_stringlist_head (&pre);
118 putaway = mala_engine_expand (self, &pre, &itr);
120 if (self->state > MALA_EFAULT)
121 return self->state;
123 while (putaway--)
125 mala_stringlist_node_remove (&pre, itr);
126 mala_stringlist_tail_insert (list, itr);
127 if (putaway && mala_stringlist_is_empty (&pre))
128 goto eunderrun;
129 itr = mala_stringlist_head (&pre);
133 if (mala_stringlist_is_empty (list))
135 /* empty substituted by --NULL, TODO use empty string instead? */
136 mala_stringlist_free (list);
137 return mala_engine_add_action_cstr (self, name,
138 mala_string_copy (self->common_string[MALA_STRING_NULL]),
139 mala_substitute_parser,
140 (MalaDataFactory)mala_string_factory,
141 NULL);
144 if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
146 /* substitute */
147 MalaString subst;
149 subst = mala_string_copy (mala_stringlist_head (list) -> string);
150 mala_stringlist_free (list);
152 return mala_engine_add_action_cstr (self, name, subst,
153 mala_substitute_parser,
154 (MalaDataFactory)mala_string_factory,
155 NULL);
157 else
159 /* expand */
160 return mala_engine_add_action_cstr (self, name, list,
161 mala_expand_parser,
162 (MalaDataFactory) mala_stringlist_factory,
163 NULL);
166 eunderrun:
167 mala_stringlist_free (list);
168 mala_stringlist_erase (&pre);
169 return self->state = MALA_ESYNTAX;
171 ealloc_list:
172 ealloc_node:
173 mala_stringlist_erase (&pre);
174 return self->state = MALA_EALLOC;
178 mala_engine_pushback_word (MalaEngine self, const char * word)
180 if(!self)
181 return MALA_EINVALID;
182 if(self->state > MALA_EFAULT)
183 return self->state;
185 if (!mala_stringlist_tail_new_cstr (&self->program, word, &self->words))
186 return self->state = MALA_EALLOC;
188 return MALA_SUCCESS;
192 mala_engine_add_action_cstr (MalaEngine self, const char * cname, void * data,
193 MalaParserFunc parser, MalaDataFactory factory,
194 MalaAction parent)
196 MalaString name;
197 MalaAction action;
199 /*TODO such checks everywhere*/
200 if(!self)
201 return MALA_EINVALID;
202 if(self->state > MALA_EFAULT)
203 return self->state;
205 name = mala_string_new (cname, &self->words);
206 if (!name)
207 goto ealloc_name;
209 action = mala_action_new (name, data, parser, factory, parent);
210 if (!action)
211 goto ealloc_action;
213 if (mala_action_attach (action) != MALA_SUCCESS)
214 goto ealloc_attach;
216 mala_string_free (name);
217 return MALA_SUCCESS;
219 ealloc_attach:
220 mala_action_free (action);
221 ealloc_action:
222 mala_string_free (name);
223 ealloc_name:
224 return self->state = MALA_EALLOC;
228 mala_engine_add_action (MalaEngine self, MalaString name, void * data,
229 MalaParserFunc parser, MalaDataFactory factory,
230 MalaAction parent)
232 MalaAction action;
234 /*TODO such checks everywhere*/
235 if(!self)
236 return MALA_EINVALID;
237 if(self->state > MALA_EFAULT)
238 return self->state;
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 return MALA_SUCCESS;
249 ealloc_attach:
250 mala_action_free (action);
251 ealloc_action:
252 return self->state = MALA_EALLOC;
256 MalaEngine
257 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
259 MalaEngine self;
261 self = mala_engine_new ();
262 if (!self)
263 return 0;
265 self->state = initfunc (self);
266 return self;
269 void
270 mala_engine_free (MalaEngine self)
272 int i;
274 if (!self)
275 return;
277 mala_stringlist_erase (&self->program);
278 mala_stringlist_erase (&self->arguments);
280 mala_stringbucket_erase (&self->words);
282 for (i = 0; i < MALA_STRING_MAX; ++i)
283 mala_string_free (self->common_string[i]);
285 free (self);
289 mala_engine_actions_register (MalaEngine self, mala_actioninit * actioninit)
291 MalaAction action;
293 if (!self)
294 return MALA_EINVALID;
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 mala_stringlist_elem_remove (&self->program, pptr);
390 mala_stringlist_tail_insert (&self->arguments, pptr);
391 self->state = MALA_SUCCESS;
393 else
394 mala_engine_eval (self, &pptr);
396 return self;
400 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
402 MalaAction act;
403 MalaActionDesc desc;
405 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
406 if (!desc)
407 goto def_parser;
409 act = mala_actiondesc_top (desc);
411 if (act)
412 self->state = mala_action_execute (act, pptr, self);
413 else
415 def_parser:
416 if (!(*pptr = mala_stringlist_before_new (&self->program,
417 *pptr,
418 self->common_string[MALA_STRING_DEFAULT_PARSER])))
419 return self->state = MALA_EALLOC;
422 if (self->state == MALA_EXCEPTION)
423 self->state = MALA_ENOACTION;
425 return self->state;
428 MalaStringListNode
429 mala_engine_eval_arg_n (MalaEngine self, MalaStringListNode_ref pptr, unsigned n)
431 MalaStringListNode next;
433 if (self->state > MALA_EFAULT)
434 return NULL;
436 for (next = *pptr;
437 n && !mala_stringlist_is_tail (&self->program, next);
438 mala_stringlist_fwd (&next), --n);
440 if (n)
441 goto eend;
443 self->state = MALA_SUCCESS;
444 while (self->state < MALA_EXCEPTION)
446 mala_engine_eval (self, &next);
447 if (mala_stringlist_is_end (&self->program, next))
448 goto eend;
451 return next;
453 eend:
454 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
455 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
456 return NULL;
459 MalaStringListNode
460 mala_engine_get_arg_n (MalaEngine self, MalaStringListNode_ref pptr, unsigned n)
462 MalaStringListNode next;
464 if (self->state > MALA_EFAULT)
465 return NULL;
467 for (next = *pptr;
468 n && !mala_stringlist_is_tail (&self->program, next);
469 mala_stringlist_fwd (&next), --n);
471 if (n)
472 goto eend;
474 self->state = MALA_SUCCESS;
476 if (mala_stringlist_is_end (&self->program, next))
477 goto eend;
479 return next;
481 eend:
482 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
483 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
484 return NULL;
489 mala_engine_exception (MalaEngine self,
490 MalaStringListNode_ref pptr,
491 MalaStringListNode here,
492 MalaString except)
494 MalaStringListNode tmp;
496 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
497 if (!tmp)
498 return self->state = MALA_EALLOC;
500 if (!mala_stringlist_after_new (&self->program, here,
501 self->common_string[MALA_STRING_HERE]))
502 return self->state = MALA_EALLOC;
504 *pptr = tmp;
506 /*TODO self-state needs to be preserved somehow?*/
507 return self->state = MALA_EXCEPTION;
512 mala_engine_expand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
514 int ret = 0;
516 if (self->state > MALA_EFAULT)
517 return MALA_EXPANSION_ERROR;
519 #define mala_run_expansion(name) \
520 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
522 mala_run_expansion (literal_expansion);
523 mala_run_expansion (numsplit_expansion);
524 mala_run_expansion (exclam_expansion);
525 mala_run_expansion (no_expansion);
526 mala_run_expansion (assign_expansion);
527 mala_run_expansion (char_expansion);
528 mala_run_expansion (underscore_expansion);
529 mala_run_expansion (bracket_expansion);
530 mala_run_expansion (assign_contraction);
531 mala_run_expansion (envvar_expansion);
532 mala_run_expansion (setenv_expansion);
533 mala_run_expansion (backquote_expansion);
534 #undef mala_run_expansion
536 return 1;
540 mala_engine_literal_expansion (MalaEngine self,
541 MalaStringList list,
542 MalaStringListNode_ref pptr)
544 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
545 && mala_string_check_prefix ((*pptr)->string, "`")
546 && !mala_string_check_prefix ((*pptr)->string, "``"))
548 MalaString nstr;
549 MalaStringListNode newnode1;
550 MalaStringListNode newnode2;
552 newnode1 = mala_stringlist_after_new (list,
553 *pptr,
554 self->common_string[MALA_STRING_LITERAL]);
555 if (!newnode1)
556 goto ealloc_newnode1;
558 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
559 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
560 if (!newnode2)
561 goto ealloc_newnode2;
563 mala_stringlist_elem_delete (list, *pptr);
564 *pptr = newnode1;
566 return 2;
568 ealloc_newnode2:
569 mala_stringlist_elem_delete (list, newnode1);
570 ealloc_newnode1:
571 self->state = MALA_EALLOC;
572 return MALA_EXPANSION_ERROR;
574 return MALA_NO_EXPANSION;
579 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
581 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
582 && mala_string_check_prefix ((*pptr)->string, "``"))
584 MalaString nstr;
585 MalaStringListNode newnode;
587 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
588 newnode = mala_stringlist_after_new (list, *pptr, nstr);
589 if (!newnode)
590 goto ealloc_newnode;
592 mala_stringlist_elem_delete (list, *pptr);
593 *pptr = newnode;
595 return 1;
597 ealloc_newnode:
598 self->state = MALA_EALLOC;
599 return MALA_EXPANSION_ERROR;
601 return MALA_NO_EXPANSION;
605 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
607 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
608 && mala_string_length ((*pptr)->string) > 2
609 && mala_string_at ((*pptr)->string, 0) == '-'
610 && isalpha (mala_string_at ((*pptr)->string, 1))
613 size_t i;
615 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
617 if (isdigit (mala_string_at ((*pptr)->string, i)))
619 MalaString a;
620 MalaString b;
622 MalaStringListNode na;
623 MalaStringListNode nb;
625 a = mala_string_new_substr ((*pptr)->string, 0, i);
626 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
627 if (!a || !b)
628 goto ealloc_str;
630 na = mala_stringlist_after_new (list, *pptr, a);
631 if (!na)
632 goto ealloc_nodea;
634 nb = mala_stringlist_after_new (list, na, b);
635 if (!nb)
636 goto ealloc_nodeb;
638 mala_stringlist_elem_delete (list, *pptr);
639 *pptr = na;
641 mala_string_free (a);
642 mala_string_free (b);
644 return 0;
646 ealloc_nodeb:
647 mala_stringlist_elem_delete (list, na);
648 ealloc_nodea:
649 ealloc_str:
650 mala_string_free (a);
651 mala_string_free (b);
652 self->state = MALA_EALLOC;
653 return MALA_EXPANSION_ERROR;
657 return MALA_NO_EXPANSION;
662 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
664 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
665 && mala_string_length ((*pptr)->string) == 1
666 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
668 MalaStringListNode newnode;
670 newnode = mala_stringlist_after_new (list,
671 *pptr,
672 self->common_string[MALA_STRING_NOT]);
673 if (!newnode)
674 return self->state = MALA_EALLOC;
676 mala_stringlist_elem_delete (list, *pptr);
677 *pptr= newnode;
678 return 1;
680 return MALA_NO_EXPANSION;
685 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
687 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
688 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
689 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
691 MalaString a;
692 MalaString aa;
693 MalaStringListNode n1;
694 MalaStringListNode n2;
696 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
697 aa = mala_string_new_prefix ("--", a);
698 if (!a || !aa)
699 goto ealloc_a;
701 n1 = mala_stringlist_after_new (list,
702 *pptr, self->common_string[MALA_STRING_NOT]);
703 if (!n1)
704 goto ealloc_n1;
706 n2 = mala_stringlist_after_new (list, n1, aa);
707 if (!n2)
708 goto ealloc_n2;
710 mala_string_free (a);
711 mala_string_free (aa);
712 mala_stringlist_elem_delete (list, *pptr);
713 *pptr = n1;
714 return 1;
716 ealloc_n2:
717 mala_stringlist_elem_delete (list, n1);
718 ealloc_n1:
719 mala_string_free (a);
720 mala_string_free (aa);
721 ealloc_a:
722 self->state = MALA_EALLOC;
723 return MALA_EXPANSION_ERROR;
725 return MALA_NO_EXPANSION;
730 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
732 size_t eq;
734 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
735 && mala_string_check_prefix ((*pptr)->string, "--")
736 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
737 && mala_string_length ((*pptr)->string) > eq + 1)
739 MalaString a;
740 MalaString b;
742 MalaStringListNode na;
743 MalaStringListNode nb;
745 a = mala_string_new_substr ((*pptr)->string, 0, eq);
746 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
747 if (!a || !b)
748 goto ealloc_str;
750 na = mala_stringlist_after_new (list, *pptr, a);
751 if (!na)
752 goto ealloc_nodea;
754 nb = mala_stringlist_after_new (list, na, b);
755 if (!nb)
756 goto ealloc_nodeb;
758 mala_stringlist_elem_delete (list, *pptr);
759 *pptr = na;
761 mala_string_free (a);
762 mala_string_free (b);
765 return 0;
767 ealloc_nodeb:
768 mala_stringlist_elem_delete (list, na);
769 ealloc_nodea:
770 ealloc_str:
771 mala_string_free (a);
772 mala_string_free (b);
773 self->state = MALA_EALLOC;
774 return MALA_EXPANSION_ERROR;
776 return MALA_NO_EXPANSION;
781 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
783 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
784 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
786 MalaStringListNode newnode;
788 newnode = mala_stringlist_before_new (list,
789 *pptr,
790 self->common_string[MALA_STRING_ENVSUBST]);
791 if (!newnode)
792 goto ealloc_node;
794 *pptr= newnode;
795 return 2;
797 ealloc_node:
798 self->state = MALA_EALLOC;
799 return MALA_EXPANSION_ERROR;
802 return MALA_NO_EXPANSION;
807 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
809 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
810 && mala_string_length ((*pptr)->string) > 2
811 && ( mala_string_at ((*pptr)->string, 0) == '-'
812 || mala_string_at ((*pptr)->string, 0) == '+')
813 && isalpha (mala_string_at ((*pptr)->string, 1)))
815 char prefix[2] = "-";
816 char current[2] = " ";
817 const char * i;
818 int cnt = 0;
820 MalaString str;
821 MalaStringListNode node = NULL;
822 MalaStringListNode pred = *pptr;
825 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
827 if (*i == '-' || *i == '+')
828 prefix[0] = *i;
829 else if (isalpha (*i))
831 ++cnt;
832 current[0] = *i;
833 str = mala_string_new_cat2 (prefix, current,
834 mala_string_bucket_get ((*pptr)->string));
835 if (!str)
836 goto ealloc;
838 node = mala_stringlist_after_new (list,
839 pred, str);
840 if (!node)
841 goto ealloc;
843 pred = node;
844 mala_string_free (str);
846 else
847 break;
850 pred = *pptr;
851 mala_stringlist_fwd (&pred);
852 mala_stringlist_elem_delete (list, *pptr);
853 *pptr= pred;
854 return cnt;
856 ealloc:
857 mala_string_free (str);
858 /* cleanup from pred downto pptr */
859 while (pred != *pptr)
861 // TODO use stringlist func
862 MalaStringListNode tmp = pred->node.cqe_prev;
863 mala_stringlist_elem_delete (list, pred);
864 pred = tmp;
866 self->state = MALA_EALLOC;
867 return MALA_EXPANSION_ERROR;
869 return MALA_NO_EXPANSION;
874 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
876 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
877 && mala_string_check_prefix ((*pptr)->string, "--")
878 && strchr (mala_string_cstr ((*pptr)->string), '_'))
880 MalaString str;
881 MalaStringListNode node;
882 char * cstr;
883 char * i;
885 cstr = strdup (mala_string_cstr ((*pptr)->string));
886 if (!cstr)
887 goto ealloc_cstr;
889 for (i = cstr + 2; *i; ++i)
891 if (*i == '_')
892 *i = '-';
895 str = mala_string_new (cstr, &self->words);
896 if (!str)
897 goto ealloc_str;
899 node = mala_stringlist_after_new (list,
900 *pptr,
901 str);
902 if (!node)
903 goto ealloc_node;
905 free (cstr);
906 mala_string_free (str);
908 mala_stringlist_elem_delete (list, *pptr);
909 *pptr= node;
910 return 0;
912 ealloc_node:
913 mala_string_free (str);
914 ealloc_str:
915 free (cstr);
916 ealloc_cstr:
917 self->state = MALA_EALLOC;
918 return MALA_EXPANSION_ERROR;
920 return MALA_NO_EXPANSION;
925 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
927 unsigned eq;
929 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
930 && mala_string_length ((*pptr)->string) > 1
931 && (eq = mala_string_char_find ((*pptr)->string, '='))
932 && eq > 0
933 && eq < SIZE_MAX
934 && !mala_string_check_prefix ((*pptr)->string, "-"))
936 MalaString key;
937 MalaString value;
938 MalaStringListNode n1;
939 MalaStringListNode n2;
940 MalaStringListNode n3;
942 key = mala_string_new_substr ((*pptr)->string, 0, eq);
943 if (!key)
944 goto ealloc_key;
946 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
947 if (!value)
948 goto ealloc_value;
950 n1 = mala_stringlist_after_new (list,
951 *pptr, self->common_string[MALA_STRING_SETENV]);
952 if (!n1)
953 goto ealloc_n1;
955 n2 = mala_stringlist_after_new (list, n1, key);
956 if (!n2)
957 goto ealloc_n2;
959 n3 = mala_stringlist_after_new (list, n2, value);
960 if (!n3)
961 goto ealloc_n3;
963 mala_string_free (key);
964 mala_string_free (value);
965 mala_stringlist_elem_delete (list, *pptr);
966 *pptr = n1;
967 return 3;
969 ealloc_n3:
970 mala_stringlist_elem_delete (list, n2);
971 ealloc_n2:
972 mala_stringlist_elem_delete (list, n1);
973 ealloc_n1:
974 mala_string_free (value);
975 ealloc_value:
976 mala_string_free (key);
977 ealloc_key:
978 self->state = MALA_EALLOC;
979 return MALA_EXPANSION_ERROR;
981 return MALA_NO_EXPANSION;
986 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
988 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
989 && mala_string_at ((*pptr)->string, 0) == '[')
991 MalaStringListNode nitr;
992 MalaStringListNode node;
994 MalaString str1 = NULL;
995 MalaStringListNode node1;
997 MalaString str2 = NULL;
998 MalaStringListNode node2;
1000 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
1001 if (!node)
1002 goto ealloc_node;
1004 if (mala_string_length((*pptr)->string) > 1)
1006 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
1007 node1 = mala_stringlist_after_new (list, node, str1);
1008 if (!node1)
1009 goto ealloc_node1;
1011 else
1013 node1 = node;
1014 mala_stringlist_fwd (&node1);
1017 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlist_fwd (&nitr))
1019 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1020 break;
1023 if ((void*)nitr != (void*)list)
1025 if (mala_string_length(nitr->string) > 1)
1027 str2 = mala_string_new_substr (nitr->string, 0,
1028 mala_string_length(nitr->string) - 1);
1029 node2 = mala_stringlist_after_new (list, nitr, str2);
1030 if (!node2)
1031 goto ealloc_node2;
1034 else
1035 goto esyntax;
1038 mala_string_free (str1);
1039 mala_string_free (str2);
1040 mala_stringlist_elem_delete (list, *pptr);
1041 mala_stringlist_elem_delete (list, nitr);
1042 *pptr = node;
1044 return 0;
1046 esyntax:
1047 mala_string_free (str1);
1048 mala_stringlist_elem_delete (list, node1);
1049 mala_stringlist_elem_delete (list, node);
1050 self->state = MALA_ESYNTAX;
1051 return MALA_EXPANSION_ERROR;
1053 ealloc_node2:
1054 mala_string_free (str1);
1055 mala_stringlist_elem_delete (list, node1);
1056 ealloc_node1:
1057 mala_stringlist_elem_delete (list, node);
1058 ealloc_node:
1059 self->state = MALA_EALLOC;
1060 return MALA_EXPANSION_ERROR;
1062 return MALA_NO_EXPANSION;
1067 mala_engine_assign_contraction (MalaEngine self,
1068 MalaStringList list,
1069 MalaStringListNode_ref pptr)
1071 MalaStringListNode assign;
1072 MalaStringListNode value ;
1074 assign = *pptr;
1075 mala_stringlist_fwd (&assign);
1076 value = assign;
1078 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1079 && !mala_stringlist_is_tail (list, *pptr)
1080 && !mala_stringlist_is_tail (list, assign)
1081 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1083 MalaString str;
1084 MalaStringListNode node;
1086 mala_stringlist_fwd (&value);
1088 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1089 "%s=%s",
1090 mala_string_cstr ((*pptr)->string),
1091 mala_string_cstr (value->string));
1094 node = mala_stringlist_after_new (list,
1095 value,
1096 str);
1097 if (!node)
1098 goto ealloc_node;
1100 mala_string_free (str);
1101 mala_stringlist_elem_delete (list, *pptr);
1102 mala_stringlist_elem_delete (list, assign);
1103 mala_stringlist_elem_delete (list, value);
1104 *pptr = node;
1105 return 0;
1107 ealloc_node:
1108 mala_string_free (str);
1109 self->state = MALA_EALLOC;
1110 return MALA_EXPANSION_ERROR;
1112 return MALA_NO_EXPANSION;
1119 mala_engine_string_istrue (MalaEngine self, MalaString str)
1121 if (!str
1122 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1123 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1124 return 0;
1126 return 1;
1130 mala_engine_check_expansionflag (MalaEngine self, int flag)
1132 MalaActionDesc desc;
1133 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1134 if (!desc)
1135 return 0;
1137 /*only enabled when the topmost action is a subtitution to --TRUE*/
1138 if (desc->actions.lh_first)
1139 return desc->actions.lh_first->data == self->common_string[MALA_STRING_TRUE];
1141 return 0;
1156 #if 0 /*TODO*/
1158 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1160 MalaAction act;
1162 if (self->state > MALA_EFAULT)
1163 return self->state;
1165 act = mala_actiondict_lookupaction (self->actions, key);
1166 if (!act)
1167 goto enoact;
1169 mala_actiondict_destroy_action (self->actions, act);
1171 return MALA_SUCCESS;
1173 enoact:
1174 self->state = MALA_ENOACTION;
1175 return self->state;
1181 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1183 MalaStringListNode base = llist_get_prev (pptr);
1184 while (mala_engine_eval (self, llist_get_next (base)) < MALA_EVAL)
1185 if (llist_get_next (base) == &self->program)
1186 return MALA_ENOACTION;
1188 return self->state;
1193 void
1194 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1196 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1202 mala_engine_argc (MalaEngine self)
1204 return llist_count (&self->arguments) + 1;
1207 const char*
1208 mala_engine_argv (MalaEngine self, int n)
1210 MalaStringListNode p;
1211 p = llist_get_next (&self->arguments);
1213 if (n==0)
1214 return self->argv_0;
1216 while (--n)
1218 if (p == &self->arguments)
1219 return 0;
1220 p = llist_get_next (p);
1222 return (const char *)(p)->data;
1227 MalaAction
1228 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1229 MalaParserFunc parser, MalaDataDestructor destructor)
1231 MalaAction act;
1233 act = mala_action_new (name, data, parser, destructor);
1234 if (!act)
1235 goto ealloc;
1237 self->state = mala_actiondict_push (self->actions, act);
1238 if (self->state)
1239 goto epush;
1241 return act;
1243 epush:
1244 mala_action_destroy (act);
1245 ealloc:
1246 return 0;
1250 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1252 MalaAction act;
1254 act = mala_actiondict_lookupaction (self->actions, name);
1255 if (!act)
1256 return MALA_NO_EXPANSION;
1258 if (act->parser != mala_substitute_parser)
1259 return MALA_EPARSER;
1261 return mala_string_check ((t_uchar*) act->data);
1265 MalaAction
1266 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1268 return mala_actiondict_lookupaction (self->actions, name);
1271 MalaAction
1272 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1274 return mala_actiondict_lookupprevaction (self->actions, name);
1277 #endif /*TODO*/
1284 // Local Variables:
1285 // mode: C
1286 // c-file-style: "gnu"
1287 // End:
1288 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1289 // end_of_file