first work on helpsystem, types etc.
[mala.git] / engine / engine.c
blob30e507d6270b5f6b4d859577b30335648b64d5c1
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;
429 Evaluate the nth argument until one of the following happens
430 - for at most 'times'
431 - until we reach the state of MALA_LITERAL (no further expansions are possible)
432 - an error/exception is flagged
433 - the type associated with the data of the current word equals to 'type'
435 MalaStringListNode
436 mala_engine_arg_eval (MalaEngine self,
437 MalaStringListNode_ref pptr,
438 unsigned nth,
439 int times,
440 MalaDataFactory type)
442 MalaAction act;
443 MalaStringListNode next;
445 if (!self || self->state > MALA_EFAULT)
446 return NULL;
448 for (next = *pptr;
449 nth && !mala_stringlist_is_tail (&self->program, next);
450 mala_stringlist_fwd (&next), --nth);
452 if (nth)
453 goto eend;
455 self->state = MALA_SUCCESS;
456 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (next->string));
457 while (self->state < MALA_EXCEPTION
458 && times--
459 && ((act && type) ? (act->factory != type) : 1))
461 mala_engine_eval (self, &next);
462 if (mala_stringlist_is_end (&self->program, next))
463 goto eend;
466 return next;
468 eend:
469 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
470 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
471 return NULL;
476 mala_engine_exception (MalaEngine self,
477 MalaStringListNode_ref pptr,
478 MalaStringListNode here,
479 MalaString except)
481 MalaStringListNode tmp;
483 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
484 if (!tmp)
485 return self->state = MALA_EALLOC;
487 if (!mala_stringlist_after_new (&self->program, here,
488 self->common_string[MALA_STRING_HERE]))
489 return self->state = MALA_EALLOC;
491 *pptr = tmp;
493 /*TODO self-state needs to be preserved somehow?*/
494 return self->state = MALA_EXCEPTION;
499 mala_engine_expand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
501 int ret = 0;
503 if (self->state > MALA_EFAULT)
504 return MALA_EXPANSION_ERROR;
506 #define mala_run_expansion(name) \
507 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
509 mala_run_expansion (literal_expansion);
510 mala_run_expansion (numsplit_expansion);
511 mala_run_expansion (exclam_expansion);
512 mala_run_expansion (no_expansion);
513 mala_run_expansion (assign_expansion);
514 mala_run_expansion (char_expansion);
515 mala_run_expansion (underscore_expansion);
516 mala_run_expansion (bracket_expansion);
517 mala_run_expansion (assign_contraction);
518 mala_run_expansion (envvar_expansion);
519 mala_run_expansion (setenv_expansion);
520 mala_run_expansion (backquote_expansion);
521 #undef mala_run_expansion
523 return 1;
527 mala_engine_literal_expansion (MalaEngine self,
528 MalaStringList list,
529 MalaStringListNode_ref pptr)
531 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
532 && mala_string_check_prefix ((*pptr)->string, "`")
533 && !mala_string_check_prefix ((*pptr)->string, "``"))
535 MalaString nstr;
536 MalaStringListNode newnode1;
537 MalaStringListNode newnode2;
539 newnode1 = mala_stringlist_after_new (list,
540 *pptr,
541 self->common_string[MALA_STRING_LITERAL]);
542 if (!newnode1)
543 goto ealloc_newnode1;
545 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
546 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
547 if (!newnode2)
548 goto ealloc_newnode2;
550 mala_stringlist_elem_delete (list, *pptr);
551 *pptr = newnode1;
553 return 2;
555 ealloc_newnode2:
556 mala_stringlist_elem_delete (list, newnode1);
557 ealloc_newnode1:
558 self->state = MALA_EALLOC;
559 return MALA_EXPANSION_ERROR;
561 return MALA_NO_EXPANSION;
566 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
568 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
569 && mala_string_check_prefix ((*pptr)->string, "``"))
571 MalaString nstr;
572 MalaStringListNode newnode;
574 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
575 newnode = mala_stringlist_after_new (list, *pptr, nstr);
576 if (!newnode)
577 goto ealloc_newnode;
579 mala_stringlist_elem_delete (list, *pptr);
580 *pptr = newnode;
582 return 1;
584 ealloc_newnode:
585 self->state = MALA_EALLOC;
586 return MALA_EXPANSION_ERROR;
588 return MALA_NO_EXPANSION;
592 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
594 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
595 && mala_string_length ((*pptr)->string) > 2
596 && mala_string_at ((*pptr)->string, 0) == '-'
597 && isalpha (mala_string_at ((*pptr)->string, 1))
600 size_t i;
602 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
604 if (isdigit (mala_string_at ((*pptr)->string, i)))
606 MalaString a;
607 MalaString b;
609 MalaStringListNode na;
610 MalaStringListNode nb;
612 a = mala_string_new_substr ((*pptr)->string, 0, i);
613 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
614 if (!a || !b)
615 goto ealloc_str;
617 na = mala_stringlist_after_new (list, *pptr, a);
618 if (!na)
619 goto ealloc_nodea;
621 nb = mala_stringlist_after_new (list, na, b);
622 if (!nb)
623 goto ealloc_nodeb;
625 mala_stringlist_elem_delete (list, *pptr);
626 *pptr = na;
628 mala_string_free (a);
629 mala_string_free (b);
631 return 0;
633 ealloc_nodeb:
634 mala_stringlist_elem_delete (list, na);
635 ealloc_nodea:
636 ealloc_str:
637 mala_string_free (a);
638 mala_string_free (b);
639 self->state = MALA_EALLOC;
640 return MALA_EXPANSION_ERROR;
644 return MALA_NO_EXPANSION;
649 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
651 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
652 && mala_string_length ((*pptr)->string) == 1
653 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
655 MalaStringListNode newnode;
657 newnode = mala_stringlist_after_new (list,
658 *pptr,
659 self->common_string[MALA_STRING_NOT]);
660 if (!newnode)
661 return self->state = MALA_EALLOC;
663 mala_stringlist_elem_delete (list, *pptr);
664 *pptr= newnode;
665 return 1;
667 return MALA_NO_EXPANSION;
672 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
674 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
675 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
676 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
678 MalaString a;
679 MalaString aa;
680 MalaStringListNode n1;
681 MalaStringListNode n2;
683 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
684 aa = mala_string_new_prefix ("--", a);
685 if (!a || !aa)
686 goto ealloc_a;
688 n1 = mala_stringlist_after_new (list,
689 *pptr, self->common_string[MALA_STRING_NOT]);
690 if (!n1)
691 goto ealloc_n1;
693 n2 = mala_stringlist_after_new (list, n1, aa);
694 if (!n2)
695 goto ealloc_n2;
697 mala_string_free (a);
698 mala_string_free (aa);
699 mala_stringlist_elem_delete (list, *pptr);
700 *pptr = n1;
701 return 1;
703 ealloc_n2:
704 mala_stringlist_elem_delete (list, n1);
705 ealloc_n1:
706 mala_string_free (a);
707 mala_string_free (aa);
708 ealloc_a:
709 self->state = MALA_EALLOC;
710 return MALA_EXPANSION_ERROR;
712 return MALA_NO_EXPANSION;
717 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
719 size_t eq;
721 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
722 && mala_string_check_prefix ((*pptr)->string, "--")
723 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
724 && mala_string_length ((*pptr)->string) > eq + 1)
726 MalaString a;
727 MalaString b;
729 MalaStringListNode na;
730 MalaStringListNode nb;
732 a = mala_string_new_substr ((*pptr)->string, 0, eq);
733 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
734 if (!a || !b)
735 goto ealloc_str;
737 na = mala_stringlist_after_new (list, *pptr, a);
738 if (!na)
739 goto ealloc_nodea;
741 nb = mala_stringlist_after_new (list, na, b);
742 if (!nb)
743 goto ealloc_nodeb;
745 mala_stringlist_elem_delete (list, *pptr);
746 *pptr = na;
748 mala_string_free (a);
749 mala_string_free (b);
752 return 0;
754 ealloc_nodeb:
755 mala_stringlist_elem_delete (list, na);
756 ealloc_nodea:
757 ealloc_str:
758 mala_string_free (a);
759 mala_string_free (b);
760 self->state = MALA_EALLOC;
761 return MALA_EXPANSION_ERROR;
763 return MALA_NO_EXPANSION;
768 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
770 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
771 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
773 MalaStringListNode newnode;
775 newnode = mala_stringlist_before_new (list,
776 *pptr,
777 self->common_string[MALA_STRING_ENVSUBST]);
778 if (!newnode)
779 goto ealloc_node;
781 *pptr= newnode;
782 return 2;
784 ealloc_node:
785 self->state = MALA_EALLOC;
786 return MALA_EXPANSION_ERROR;
789 return MALA_NO_EXPANSION;
794 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
796 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
797 && mala_string_length ((*pptr)->string) > 2
798 && ( mala_string_at ((*pptr)->string, 0) == '-'
799 || mala_string_at ((*pptr)->string, 0) == '+')
800 && isalpha (mala_string_at ((*pptr)->string, 1)))
802 char prefix[2] = "-";
803 char current[2] = " ";
804 const char * i;
805 int cnt = 0;
807 MalaString str;
808 MalaStringListNode node = NULL;
809 MalaStringListNode pred = *pptr;
812 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
814 if (*i == '-' || *i == '+')
815 prefix[0] = *i;
816 else if (isalpha (*i))
818 ++cnt;
819 current[0] = *i;
820 str = mala_string_new_cat2 (prefix, current,
821 mala_string_bucket_get ((*pptr)->string));
822 if (!str)
823 goto ealloc;
825 node = mala_stringlist_after_new (list,
826 pred, str);
827 if (!node)
828 goto ealloc;
830 pred = node;
831 mala_string_free (str);
833 else
834 break;
837 pred = *pptr;
838 mala_stringlist_fwd (&pred);
839 mala_stringlist_elem_delete (list, *pptr);
840 *pptr= pred;
841 return cnt;
843 ealloc:
844 mala_string_free (str);
845 /* cleanup from pred downto pptr */
846 while (pred != *pptr)
848 // TODO use stringlist func
849 MalaStringListNode tmp = pred->node.cqe_prev;
850 mala_stringlist_elem_delete (list, pred);
851 pred = tmp;
853 self->state = MALA_EALLOC;
854 return MALA_EXPANSION_ERROR;
856 return MALA_NO_EXPANSION;
861 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
863 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
864 && mala_string_check_prefix ((*pptr)->string, "--")
865 && strchr (mala_string_cstr ((*pptr)->string), '_'))
867 MalaString str;
868 MalaStringListNode node;
869 char * cstr;
870 char * i;
872 cstr = strdup (mala_string_cstr ((*pptr)->string));
873 if (!cstr)
874 goto ealloc_cstr;
876 for (i = cstr + 2; *i; ++i)
878 if (*i == '_')
879 *i = '-';
882 str = mala_string_new (cstr, &self->words);
883 if (!str)
884 goto ealloc_str;
886 node = mala_stringlist_after_new (list,
887 *pptr,
888 str);
889 if (!node)
890 goto ealloc_node;
892 free (cstr);
893 mala_string_free (str);
895 mala_stringlist_elem_delete (list, *pptr);
896 *pptr= node;
897 return 0;
899 ealloc_node:
900 mala_string_free (str);
901 ealloc_str:
902 free (cstr);
903 ealloc_cstr:
904 self->state = MALA_EALLOC;
905 return MALA_EXPANSION_ERROR;
907 return MALA_NO_EXPANSION;
912 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
914 unsigned eq;
916 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
917 && mala_string_length ((*pptr)->string) > 1
918 && (eq = mala_string_char_find ((*pptr)->string, '='))
919 && eq > 0
920 && eq < SIZE_MAX
921 && !mala_string_check_prefix ((*pptr)->string, "-"))
923 MalaString key;
924 MalaString value;
925 MalaStringListNode n1;
926 MalaStringListNode n2;
927 MalaStringListNode n3;
929 key = mala_string_new_substr ((*pptr)->string, 0, eq);
930 if (!key)
931 goto ealloc_key;
933 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
934 if (!value)
935 goto ealloc_value;
937 n1 = mala_stringlist_after_new (list,
938 *pptr, self->common_string[MALA_STRING_SETENV]);
939 if (!n1)
940 goto ealloc_n1;
942 n2 = mala_stringlist_after_new (list, n1, key);
943 if (!n2)
944 goto ealloc_n2;
946 n3 = mala_stringlist_after_new (list, n2, value);
947 if (!n3)
948 goto ealloc_n3;
950 mala_string_free (key);
951 mala_string_free (value);
952 mala_stringlist_elem_delete (list, *pptr);
953 *pptr = n1;
954 return 3;
956 ealloc_n3:
957 mala_stringlist_elem_delete (list, n2);
958 ealloc_n2:
959 mala_stringlist_elem_delete (list, n1);
960 ealloc_n1:
961 mala_string_free (value);
962 ealloc_value:
963 mala_string_free (key);
964 ealloc_key:
965 self->state = MALA_EALLOC;
966 return MALA_EXPANSION_ERROR;
968 return MALA_NO_EXPANSION;
973 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
975 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
976 && mala_string_at ((*pptr)->string, 0) == '[')
978 MalaStringListNode nitr;
979 MalaStringListNode node;
981 MalaString str1 = NULL;
982 MalaStringListNode node1;
984 MalaString str2 = NULL;
985 MalaStringListNode node2;
987 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
988 if (!node)
989 goto ealloc_node;
991 if (mala_string_length((*pptr)->string) > 1)
993 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
994 node1 = mala_stringlist_after_new (list, node, str1);
995 if (!node1)
996 goto ealloc_node1;
998 else
1000 node1 = node;
1001 mala_stringlist_fwd (&node1);
1004 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlist_fwd (&nitr))
1006 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1007 break;
1010 if ((void*)nitr != (void*)list)
1012 if (mala_string_length(nitr->string) > 1)
1014 str2 = mala_string_new_substr (nitr->string, 0,
1015 mala_string_length(nitr->string) - 1);
1016 node2 = mala_stringlist_after_new (list, nitr, str2);
1017 if (!node2)
1018 goto ealloc_node2;
1021 else
1022 goto esyntax;
1025 mala_string_free (str1);
1026 mala_string_free (str2);
1027 mala_stringlist_elem_delete (list, *pptr);
1028 mala_stringlist_elem_delete (list, nitr);
1029 *pptr = node;
1031 return 0;
1033 esyntax:
1034 mala_string_free (str1);
1035 mala_stringlist_elem_delete (list, node1);
1036 mala_stringlist_elem_delete (list, node);
1037 self->state = MALA_ESYNTAX;
1038 return MALA_EXPANSION_ERROR;
1040 ealloc_node2:
1041 mala_string_free (str1);
1042 mala_stringlist_elem_delete (list, node1);
1043 ealloc_node1:
1044 mala_stringlist_elem_delete (list, node);
1045 ealloc_node:
1046 self->state = MALA_EALLOC;
1047 return MALA_EXPANSION_ERROR;
1049 return MALA_NO_EXPANSION;
1054 mala_engine_assign_contraction (MalaEngine self,
1055 MalaStringList list,
1056 MalaStringListNode_ref pptr)
1058 MalaStringListNode assign;
1059 MalaStringListNode value ;
1061 assign = *pptr;
1062 mala_stringlist_fwd (&assign);
1063 value = assign;
1065 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1066 && !mala_stringlist_is_tail (list, *pptr)
1067 && !mala_stringlist_is_tail (list, assign)
1068 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1070 MalaString str;
1071 MalaStringListNode node;
1073 mala_stringlist_fwd (&value);
1075 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1076 "%s=%s",
1077 mala_string_cstr ((*pptr)->string),
1078 mala_string_cstr (value->string));
1081 node = mala_stringlist_after_new (list,
1082 value,
1083 str);
1084 if (!node)
1085 goto ealloc_node;
1087 mala_string_free (str);
1088 mala_stringlist_elem_delete (list, *pptr);
1089 mala_stringlist_elem_delete (list, assign);
1090 mala_stringlist_elem_delete (list, value);
1091 *pptr = node;
1092 return 0;
1094 ealloc_node:
1095 mala_string_free (str);
1096 self->state = MALA_EALLOC;
1097 return MALA_EXPANSION_ERROR;
1099 return MALA_NO_EXPANSION;
1106 mala_engine_string_istrue (MalaEngine self, MalaString str)
1108 if (!str
1109 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1110 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1111 return 0;
1113 return 1;
1117 mala_engine_check_expansionflag (MalaEngine self, int flag)
1119 MalaActionDesc desc;
1120 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1121 if (!desc)
1122 return 0;
1124 /*only enabled when the topmost action is a subtitution to --TRUE*/
1125 if (desc->actions.lh_first)
1126 return desc->actions.lh_first->data == self->common_string[MALA_STRING_TRUE];
1128 return 0;
1143 #if 0 /*TODO*/
1145 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1147 MalaAction act;
1149 if (self->state > MALA_EFAULT)
1150 return self->state;
1152 act = mala_actiondict_lookupaction (self->actions, key);
1153 if (!act)
1154 goto enoact;
1156 mala_actiondict_destroy_action (self->actions, act);
1158 return MALA_SUCCESS;
1160 enoact:
1161 self->state = MALA_ENOACTION;
1162 return self->state;
1168 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1170 MalaStringListNode base = llist_get_prev (pptr);
1171 while (mala_engine_eval (self, llist_get_next (base)) < MALA_EVAL)
1172 if (llist_get_next (base) == &self->program)
1173 return MALA_ENOACTION;
1175 return self->state;
1180 void
1181 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1183 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1189 mala_engine_argc (MalaEngine self)
1191 return llist_count (&self->arguments) + 1;
1194 const char*
1195 mala_engine_argv (MalaEngine self, int n)
1197 MalaStringListNode p;
1198 p = llist_get_next (&self->arguments);
1200 if (n==0)
1201 return self->argv_0;
1203 while (--n)
1205 if (p == &self->arguments)
1206 return 0;
1207 p = llist_get_next (p);
1209 return (const char *)(p)->data;
1214 MalaAction
1215 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1216 MalaParserFunc parser, MalaDataDestructor destructor)
1218 MalaAction act;
1220 act = mala_action_new (name, data, parser, destructor);
1221 if (!act)
1222 goto ealloc;
1224 self->state = mala_actiondict_push (self->actions, act);
1225 if (self->state)
1226 goto epush;
1228 return act;
1230 epush:
1231 mala_action_destroy (act);
1232 ealloc:
1233 return 0;
1237 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1239 MalaAction act;
1241 act = mala_actiondict_lookupaction (self->actions, name);
1242 if (!act)
1243 return MALA_NO_EXPANSION;
1245 if (act->parser != mala_substitute_parser)
1246 return MALA_EPARSER;
1248 return mala_string_check ((t_uchar*) act->data);
1252 MalaAction
1253 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1255 return mala_actiondict_lookupaction (self->actions, name);
1258 MalaAction
1259 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1261 return mala_actiondict_lookupprevaction (self->actions, name);
1264 #endif /*TODO*/
1271 // Local Variables:
1272 // mode: C
1273 // c-file-style: "gnu"
1274 // End:
1275 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1276 // end_of_file