add failure exit to test.sh
[mala.git] / engine / engine.c
blobb42c03c78c7f4ad792edbe3bcf32ce2c6d8c15ed
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_ppexpand_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_ppexpand (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_stringlistnode_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_stringlistnode_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;
399 MalaEngine
400 mala_engine_step (MalaEngine self)
402 MalaStringListNode pptr;
404 if (self->state < MALA_EFAULT &&
405 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
407 if (self->state == MALA_LITERAL)
409 mala_stringlist_elem_remove (&self->program, pptr);
410 mala_stringlist_tail_insert (&self->arguments, pptr);
411 self->state = MALA_SUCCESS;
413 else
414 mala_engine_eval (self, &pptr);
416 return self;
420 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
422 MalaAction act;
423 MalaActionDesc desc;
425 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
426 if (!desc)
427 goto def_parser;
429 act = mala_actiondesc_top (desc);
431 if (act)
432 self->state = mala_action_execute (act, pptr, self);
433 else
435 def_parser:
436 if (!(*pptr = mala_stringlist_before_new (&self->program,
437 *pptr,
438 self->common_string[MALA_STRING_DEFAULT_PARSER])))
439 return self->state = MALA_EALLOC;
442 if (self->state == MALA_EXCEPTION)
443 self->state = MALA_ENOACTION;
445 return self->state;
449 Evaluate the nth argument until one of the following happens
450 - for at most 'times'
451 - until we reach the state of MALA_LITERAL (no further expansions are possible)
452 - an error/exception is flagged
453 - the type associated with the data of the current word equals to 'type'
455 MalaStringListNode
456 mala_engine_arg_eval (MalaEngine self,
457 MalaStringListNode_ref pptr,
458 unsigned nth,
459 int times,
460 MalaDataFactory type)
462 MalaAction act;
463 MalaStringListNode next;
465 if (!self || self->state > MALA_EFAULT)
466 return NULL;
468 for (next = *pptr;
469 nth && !mala_stringlist_is_tail (&self->program, next);
470 mala_stringlistnode_fwd (&next), --nth);
472 if (nth)
473 goto eend;
475 self->state = MALA_SUCCESS;
476 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (next->string));
477 while (self->state < MALA_EXCEPTION
478 && times--
479 && ((act && type) ? (act->factory != type) : 1))
481 mala_engine_eval (self, &next);
482 if (mala_stringlist_is_end (&self->program, next))
483 goto eend;
486 return next;
488 eend:
489 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
490 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
491 return NULL;
496 mala_engine_exception (MalaEngine self,
497 MalaStringListNode_ref pptr,
498 MalaStringListNode here,
499 MalaString except)
501 MalaStringListNode tmp;
503 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
504 if (!tmp)
505 return self->state = MALA_EALLOC;
507 if (!mala_stringlist_after_new (&self->program, here,
508 self->common_string[MALA_STRING_HERE]))
509 return self->state = MALA_EALLOC;
511 *pptr = tmp;
513 /*TODO self-state needs to be preserved somehow?*/
514 return self->state = MALA_EXCEPTION;
519 mala_engine_ppexpand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
521 int ret = 0;
523 if (self->state > MALA_EFAULT)
524 return MALA_EXPANSION_ERROR;
526 #define mala_run_expansion(name) \
527 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
529 mala_run_expansion (literal_expansion);
530 mala_run_expansion (numsplit_expansion);
531 mala_run_expansion (exclam_expansion);
532 mala_run_expansion (no_expansion);
533 mala_run_expansion (assign_expansion);
534 mala_run_expansion (char_expansion);
535 mala_run_expansion (underscore_expansion);
536 mala_run_expansion (bracket_expansion);
537 mala_run_expansion (assign_contraction);
538 mala_run_expansion (envvar_expansion);
539 mala_run_expansion (setenv_expansion);
540 mala_run_expansion (backquote_expansion);
541 #undef mala_run_expansion
543 return 1;
547 mala_engine_literal_expansion (MalaEngine self,
548 MalaStringList list,
549 MalaStringListNode_ref pptr)
551 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
552 && mala_string_check_prefix ((*pptr)->string, "`")
553 && !mala_string_check_prefix ((*pptr)->string, "``"))
555 MalaString nstr;
556 MalaStringListNode newnode1;
557 MalaStringListNode newnode2;
559 newnode1 = mala_stringlist_after_new (list,
560 *pptr,
561 self->common_string[MALA_STRING_LITERAL]);
562 if (!newnode1)
563 goto ealloc_newnode1;
565 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
566 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
567 if (!newnode2)
568 goto ealloc_newnode2;
570 mala_stringlist_elem_delete (list, *pptr);
571 *pptr = newnode1;
573 return 2;
575 ealloc_newnode2:
576 mala_stringlist_elem_delete (list, newnode1);
577 ealloc_newnode1:
578 self->state = MALA_EALLOC;
579 return MALA_EXPANSION_ERROR;
581 return MALA_NO_EXPANSION;
586 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
588 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
589 && mala_string_check_prefix ((*pptr)->string, "``"))
591 MalaString nstr;
592 MalaStringListNode newnode;
594 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
595 newnode = mala_stringlist_after_new (list, *pptr, nstr);
596 if (!newnode)
597 goto ealloc_newnode;
599 mala_stringlist_elem_delete (list, *pptr);
600 *pptr = newnode;
602 return 1;
604 ealloc_newnode:
605 self->state = MALA_EALLOC;
606 return MALA_EXPANSION_ERROR;
608 return MALA_NO_EXPANSION;
612 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
614 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
615 && mala_string_length ((*pptr)->string) > 2
616 && mala_string_at ((*pptr)->string, 0) == '-'
617 && isalpha (mala_string_at ((*pptr)->string, 1))
620 size_t i;
622 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
624 if (isdigit (mala_string_at ((*pptr)->string, i)))
626 MalaString a;
627 MalaString b;
629 MalaStringListNode na;
630 MalaStringListNode nb;
632 a = mala_string_new_substr ((*pptr)->string, 0, i);
633 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
634 if (!a || !b)
635 goto ealloc_str;
637 na = mala_stringlist_after_new (list, *pptr, a);
638 if (!na)
639 goto ealloc_nodea;
641 nb = mala_stringlist_after_new (list, na, b);
642 if (!nb)
643 goto ealloc_nodeb;
645 mala_stringlist_elem_delete (list, *pptr);
646 *pptr = na;
648 mala_string_free (a);
649 mala_string_free (b);
651 return 0;
653 ealloc_nodeb:
654 mala_stringlist_elem_delete (list, na);
655 ealloc_nodea:
656 ealloc_str:
657 mala_string_free (a);
658 mala_string_free (b);
659 self->state = MALA_EALLOC;
660 return MALA_EXPANSION_ERROR;
664 return MALA_NO_EXPANSION;
669 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
671 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
672 && mala_string_length ((*pptr)->string) == 1
673 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
675 MalaStringListNode newnode;
677 newnode = mala_stringlist_after_new (list,
678 *pptr,
679 self->common_string[MALA_STRING_NOT]);
680 if (!newnode)
681 return self->state = MALA_EALLOC;
683 mala_stringlist_elem_delete (list, *pptr);
684 *pptr= newnode;
685 return 1;
687 return MALA_NO_EXPANSION;
692 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
694 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
695 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
696 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
698 MalaString a;
699 MalaString aa;
700 MalaStringListNode n1;
701 MalaStringListNode n2;
703 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
704 aa = mala_string_new_prefix ("--", a);
705 if (!a || !aa)
706 goto ealloc_a;
708 n1 = mala_stringlist_after_new (list,
709 *pptr, self->common_string[MALA_STRING_NOT]);
710 if (!n1)
711 goto ealloc_n1;
713 n2 = mala_stringlist_after_new (list, n1, aa);
714 if (!n2)
715 goto ealloc_n2;
717 mala_string_free (a);
718 mala_string_free (aa);
719 mala_stringlist_elem_delete (list, *pptr);
720 *pptr = n1;
721 return 1;
723 ealloc_n2:
724 mala_stringlist_elem_delete (list, n1);
725 ealloc_n1:
726 mala_string_free (a);
727 mala_string_free (aa);
728 ealloc_a:
729 self->state = MALA_EALLOC;
730 return MALA_EXPANSION_ERROR;
732 return MALA_NO_EXPANSION;
737 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
739 size_t eq;
741 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
742 && mala_string_check_prefix ((*pptr)->string, "--")
743 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
744 && mala_string_length ((*pptr)->string) > eq + 1)
746 MalaString a;
747 MalaString b;
749 MalaStringListNode na;
750 MalaStringListNode nb;
752 a = mala_string_new_substr ((*pptr)->string, 0, eq);
753 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
754 if (!a || !b)
755 goto ealloc_str;
757 na = mala_stringlist_after_new (list, *pptr, a);
758 if (!na)
759 goto ealloc_nodea;
761 nb = mala_stringlist_after_new (list, na, b);
762 if (!nb)
763 goto ealloc_nodeb;
765 mala_stringlist_elem_delete (list, *pptr);
766 *pptr = na;
768 mala_string_free (a);
769 mala_string_free (b);
772 return 0;
774 ealloc_nodeb:
775 mala_stringlist_elem_delete (list, na);
776 ealloc_nodea:
777 ealloc_str:
778 mala_string_free (a);
779 mala_string_free (b);
780 self->state = MALA_EALLOC;
781 return MALA_EXPANSION_ERROR;
783 return MALA_NO_EXPANSION;
788 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
790 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
791 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
793 MalaStringListNode newnode;
795 newnode = mala_stringlist_before_new (list,
796 *pptr,
797 self->common_string[MALA_STRING_ENVSUBST]);
798 if (!newnode)
799 goto ealloc_node;
801 *pptr= newnode;
802 return 2;
804 ealloc_node:
805 self->state = MALA_EALLOC;
806 return MALA_EXPANSION_ERROR;
809 return MALA_NO_EXPANSION;
814 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
816 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
817 && mala_string_length ((*pptr)->string) > 2
818 && ( mala_string_at ((*pptr)->string, 0) == '-'
819 || mala_string_at ((*pptr)->string, 0) == '+')
820 && isalpha (mala_string_at ((*pptr)->string, 1)))
822 char prefix[2] = "-";
823 char current[2] = " ";
824 const char * i;
825 int cnt = 0;
827 MalaString str;
828 MalaStringListNode node = NULL;
829 MalaStringListNode pred = *pptr;
832 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
834 if (*i == '-' || *i == '+')
835 prefix[0] = *i;
836 else if (isalpha (*i))
838 ++cnt;
839 current[0] = *i;
840 str = mala_string_new_cat2 (prefix, current,
841 mala_string_bucket_get ((*pptr)->string));
842 if (!str)
843 goto ealloc;
845 node = mala_stringlist_after_new (list,
846 pred, str);
847 if (!node)
848 goto ealloc;
850 pred = node;
851 mala_string_free (str);
853 else
854 break;
857 pred = *pptr;
858 mala_stringlistnode_fwd (&pred);
859 mala_stringlist_elem_delete (list, *pptr);
860 *pptr= pred;
861 return cnt;
863 ealloc:
864 mala_string_free (str);
865 /* cleanup from pred downto pptr */
866 while (pred != *pptr)
868 MalaStringListNode tmp = mala_stringlistnode_prev (pred);
869 mala_stringlist_elem_delete (list, pred);
870 pred = tmp;
872 self->state = MALA_EALLOC;
873 return MALA_EXPANSION_ERROR;
875 return MALA_NO_EXPANSION;
880 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
882 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
883 && mala_string_check_prefix ((*pptr)->string, "--")
884 && strchr (mala_string_cstr ((*pptr)->string), '_'))
886 MalaString str;
887 MalaStringListNode node;
888 char * cstr;
889 char * i;
891 cstr = strdup (mala_string_cstr ((*pptr)->string));
892 if (!cstr)
893 goto ealloc_cstr;
895 for (i = cstr + 2; *i; ++i)
897 if (*i == '_')
898 *i = '-';
901 str = mala_string_new (cstr, &self->words);
902 if (!str)
903 goto ealloc_str;
905 node = mala_stringlist_after_new (list,
906 *pptr,
907 str);
908 if (!node)
909 goto ealloc_node;
911 free (cstr);
912 mala_string_free (str);
914 mala_stringlist_elem_delete (list, *pptr);
915 *pptr= node;
916 return 0;
918 ealloc_node:
919 mala_string_free (str);
920 ealloc_str:
921 free (cstr);
922 ealloc_cstr:
923 self->state = MALA_EALLOC;
924 return MALA_EXPANSION_ERROR;
926 return MALA_NO_EXPANSION;
931 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
933 size_t eq;
935 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
936 && mala_string_length ((*pptr)->string) > 1
937 && (eq = mala_string_char_find ((*pptr)->string, '='))
938 && eq > 0
939 && eq < SIZE_MAX
940 && !mala_string_check_prefix ((*pptr)->string, "-"))
942 MalaString key;
943 MalaString value;
944 MalaStringListNode n1;
945 MalaStringListNode n2;
946 MalaStringListNode n3;
948 key = mala_string_new_substr ((*pptr)->string, 0, eq);
949 if (!key)
950 goto ealloc_key;
952 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
953 if (!value)
954 goto ealloc_value;
956 n1 = mala_stringlist_after_new (list,
957 *pptr, self->common_string[MALA_STRING_SETENV]);
958 if (!n1)
959 goto ealloc_n1;
961 n2 = mala_stringlist_after_new (list, n1, key);
962 if (!n2)
963 goto ealloc_n2;
965 n3 = mala_stringlist_after_new (list, n2, value);
966 if (!n3)
967 goto ealloc_n3;
969 mala_string_free (key);
970 mala_string_free (value);
971 mala_stringlist_elem_delete (list, *pptr);
972 *pptr = n1;
973 return 3;
975 ealloc_n3:
976 mala_stringlist_elem_delete (list, n2);
977 ealloc_n2:
978 mala_stringlist_elem_delete (list, n1);
979 ealloc_n1:
980 mala_string_free (value);
981 ealloc_value:
982 mala_string_free (key);
983 ealloc_key:
984 self->state = MALA_EALLOC;
985 return MALA_EXPANSION_ERROR;
987 return MALA_NO_EXPANSION;
992 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
994 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
995 && mala_string_at ((*pptr)->string, 0) == '[')
997 MalaStringListNode nitr;
998 MalaStringListNode node;
1000 MalaString str1 = NULL;
1001 MalaStringListNode node1;
1003 MalaString str2 = NULL;
1004 MalaStringListNode node2;
1006 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
1007 if (!node)
1008 goto ealloc_node;
1010 if (mala_string_length((*pptr)->string) > 1)
1012 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
1013 node1 = mala_stringlist_after_new (list, node, str1);
1014 if (!node1)
1015 goto ealloc_node1;
1017 else
1019 node1 = node;
1020 mala_stringlistnode_fwd (&node1);
1023 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlistnode_fwd (&nitr))
1025 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1026 break;
1029 if ((void*)nitr != (void*)list)
1031 if (mala_string_length(nitr->string) > 1)
1033 str2 = mala_string_new_substr (nitr->string, 0,
1034 mala_string_length(nitr->string) - 1);
1035 node2 = mala_stringlist_after_new (list, nitr, str2);
1036 if (!node2)
1037 goto ealloc_node2;
1040 else
1041 goto esyntax;
1044 mala_string_free (str1);
1045 mala_string_free (str2);
1046 mala_stringlist_elem_delete (list, *pptr);
1047 mala_stringlist_elem_delete (list, nitr);
1048 *pptr = node;
1050 return 0;
1052 esyntax:
1053 mala_string_free (str1);
1054 mala_stringlist_elem_delete (list, node1);
1055 mala_stringlist_elem_delete (list, node);
1056 self->state = MALA_ESYNTAX;
1057 return MALA_EXPANSION_ERROR;
1059 ealloc_node2:
1060 mala_string_free (str1);
1061 mala_stringlist_elem_delete (list, node1);
1062 ealloc_node1:
1063 mala_stringlist_elem_delete (list, node);
1064 ealloc_node:
1065 self->state = MALA_EALLOC;
1066 return MALA_EXPANSION_ERROR;
1068 return MALA_NO_EXPANSION;
1073 mala_engine_assign_contraction (MalaEngine self,
1074 MalaStringList list,
1075 MalaStringListNode_ref pptr)
1077 MalaStringListNode assign;
1078 MalaStringListNode value ;
1080 assign = *pptr;
1081 mala_stringlistnode_fwd (&assign);
1082 value = assign;
1084 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1085 && !mala_stringlist_is_tail (list, *pptr)
1086 && !mala_stringlist_is_tail (list, assign)
1087 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1089 MalaString str;
1090 MalaStringListNode node;
1092 mala_stringlistnode_fwd (&value);
1094 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1095 "%s=%s",
1096 mala_string_cstr ((*pptr)->string),
1097 mala_string_cstr (value->string));
1100 node = mala_stringlist_after_new (list,
1101 value,
1102 str);
1103 if (!node)
1104 goto ealloc_node;
1106 mala_string_free (str);
1107 mala_stringlist_elem_delete (list, *pptr);
1108 mala_stringlist_elem_delete (list, assign);
1109 mala_stringlist_elem_delete (list, value);
1110 *pptr = node;
1111 return 0;
1113 ealloc_node:
1114 mala_string_free (str);
1115 self->state = MALA_EALLOC;
1116 return MALA_EXPANSION_ERROR;
1118 return MALA_NO_EXPANSION;
1125 mala_engine_string_istrue (MalaEngine self, MalaString str)
1127 if (!str
1128 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1129 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1130 return 0;
1132 return 1;
1136 mala_engine_check_expansionflag (MalaEngine self, int flag)
1138 MalaActionDesc desc;
1139 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1141 /*only enabled when the topmost action is a subtitution to --TRUE*/
1142 return mala_actiondesc_data_top (desc) == self->common_string[MALA_STRING_TRUE];
1157 #if 0 /*TODO*/
1159 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1161 MalaAction act;
1163 if (self->state > MALA_EFAULT)
1164 return self->state;
1166 act = mala_actiondict_lookupaction (self->actions, key);
1167 if (!act)
1168 goto enoact;
1170 mala_actiondict_destroy_action (self->actions, act);
1172 return MALA_SUCCESS;
1174 enoact:
1175 self->state = MALA_ENOACTION;
1176 return self->state;
1182 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1184 MalaStringListNode base = llist_get_prev (pptr);
1185 while (mala_engine_eval (self, llist_get_nextt (base)) < MALA_EVAL)
1186 if (llist_get_next (base) == &self->program)
1187 return MALA_ENOACTION;
1189 return self->state;
1194 void
1195 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1197 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1203 mala_engine_argc (MalaEngine self)
1205 return llist_count (&self->arguments) + 1;
1208 const char*
1209 mala_engine_argv (MalaEngine self, int n)
1211 MalaStringListNode p;
1212 p = llist_get_next (&self->arguments);
1214 if (n==0)
1215 return self->argv_0;
1217 while (--n)
1219 if (p == &self->arguments)
1220 return 0;
1221 p = llist_get_next (p);
1223 return (const char *)(p)->data;
1228 MalaAction
1229 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1230 MalaParserFunc parser, MalaDataDestructor destructor)
1232 MalaAction act;
1234 act = mala_action_new (name, data, parser, destructor);
1235 if (!act)
1236 goto ealloc;
1238 self->state = mala_actiondict_push (self->actions, act);
1239 if (self->state)
1240 goto epush;
1242 return act;
1244 epush:
1245 mala_action_destroy (act);
1246 ealloc:
1247 return 0;
1251 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1253 MalaAction act;
1255 act = mala_actiondict_lookupaction (self->actions, name);
1256 if (!act)
1257 return MALA_NO_EXPANSION;
1259 if (act->parser != mala_substitute_parser)
1260 return MALA_EPARSER;
1262 return mala_string_check ((t_uchar*) act->data);
1266 MalaAction
1267 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1269 return mala_actiondict_lookupaction (self->actions, name);
1272 MalaAction
1273 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1275 return mala_actiondict_lookupprevaction (self->actions, name);
1278 #endif /*TODO*/
1285 // Local Variables:
1286 // mode: C
1287 // c-file-style: "gnu"
1288 // End:
1289 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1290 // end_of_file