else_parser
[mala.git] / engine / engine.c
blobc97d4070eff59b994f21bcea9ccc6bf23920a4a2
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
35 #define MALA_STATE(s) #s
36 const char * mala_engine_states [] = {MALA_STATES};
37 #undef MALA_STATE
41 * function definitions
44 MalaEngine
45 mala_engine_new ()
47 MalaEngine self;
48 int i;
50 self = malloc (sizeof(mala_engine));
51 if (!self)
52 return NULL;
54 self->negated = 0;
55 self->trace = 0;
56 self->blockcnt = 0;
58 self->state = MALA_CONTINUE;
60 mala_stringbucket_init (&self->words, MALA_STRING_FWD, (void(*)(void*)) mala_actiondesc_free);
62 for (i = 0; i < MALA_STRING_MAX; ++i)
64 self->common_string[i] = mala_string_new (mala_common_strings[i], &self->words);
65 if (!self->common_string[i])
66 goto ealloc_strings;
69 mala_stringlist_init (&self->program);
70 mala_stringlist_init (&self->arguments);
72 return self;
74 ealloc_strings:
75 while (--i >= 0)
76 mala_string_free (self->common_string[i]);
77 free (self);
78 return NULL;
81 #if 0
82 MalaEngine
83 mala_engine_new_main (int (*initfunc) (MalaEngine),
84 int argc, char **argv,
85 mala_actioninit * actions_init)
87 /*TODO convinience function*/
89 #endif
91 int
92 mala_engine_ppexpand_define (MalaEngine self, const char * name, int argc, char ** argv)
94 int i;
95 MalaStringList list;
96 MalaStringListNode itr;
97 mala_stringlist pre;
99 if (mala_engine_state_get (self) > MALA_EFAULT)
100 return mala_engine_state_get (self);
102 mala_stringlist_init (&pre);
104 for (i = 0; i != argc && *argv; ++i ,++argv)
106 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
107 goto ealloc_node;
110 list = mala_stringlist_new ();
111 if (!list)
112 goto ealloc_list;
114 /*TODO preprocess in own function*/
115 while (!mala_stringlist_is_empty (&pre))
117 int putaway;
119 itr = mala_stringlist_head (&pre);
121 putaway = mala_engine_ppexpand (self, &pre, &itr);
123 if (self->state > MALA_EFAULT)
124 return self->state;
126 while (putaway--)
128 mala_stringlist_node_remove (&pre, itr);
129 mala_stringlist_tail_insert (list, itr);
130 if (putaway && mala_stringlist_is_empty (&pre))
131 goto eunderrun;
132 itr = mala_stringlist_head (&pre);
136 if (mala_stringlist_is_empty (list))
138 mala_stringlist_free (list);
139 return mala_engine_add_action_cstr (self, name,
140 mala_string_copy (self->common_string[MALA_STRING_PASS]),
141 mala_substitute_parser,
142 (MalaDataFactory)mala_string_factory,
143 NULL);
146 if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
148 /* substitute */
149 MalaString subst;
151 subst = mala_string_copy (mala_stringlist_head (list) -> string);
152 mala_stringlist_free (list);
154 return mala_engine_add_action_cstr (self, name, subst,
155 mala_substitute_parser,
156 (MalaDataFactory)mala_string_factory,
157 NULL);
159 else
161 /* expand */
162 return mala_engine_add_action_cstr (self, name, list,
163 mala_expand_parser,
164 (MalaDataFactory) mala_stringlist_factory,
165 NULL);
168 eunderrun:
169 mala_stringlist_free (list);
170 mala_stringlist_erase (&pre);
171 return self->state = MALA_ESYNTAX;
173 ealloc_list:
174 ealloc_node:
175 mala_stringlist_erase (&pre);
176 return self->state = MALA_EALLOC;
180 mala_engine_pushback_word (MalaEngine self, const char * word)
182 if (mala_engine_state_get (self) > MALA_EFAULT)
183 return mala_engine_state_get (self);
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 if (mala_engine_state_get (self) > MALA_EFAULT)
200 return mala_engine_state_get (self);
202 name = mala_string_new (cname, &self->words);
203 if (!name)
204 goto ealloc_name;
206 action = mala_action_new (name, data, parser, factory, parent);
207 if (!action)
208 goto ealloc_action;
210 if (mala_action_attach (action) != MALA_SUCCESS)
211 goto ealloc_attach;
213 mala_string_free (name);
214 return MALA_SUCCESS;
216 ealloc_attach:
217 mala_action_free (action);
218 ealloc_action:
219 mala_string_free (name);
220 ealloc_name:
221 return self->state = MALA_EALLOC;
225 mala_engine_add_action (MalaEngine self, MalaString name, void * data,
226 MalaParserFunc parser, MalaDataFactory factory,
227 MalaAction parent)
229 MalaAction action;
231 if (mala_engine_state_get (self) > MALA_EFAULT)
232 return mala_engine_state_get (self);
234 action = mala_action_new (name, data, parser, factory, parent);
235 if (!action)
236 goto ealloc_action;
238 if (mala_action_attach (action) != MALA_SUCCESS)
239 goto ealloc_attach;
241 return MALA_SUCCESS;
243 ealloc_attach:
244 mala_action_free (action);
245 ealloc_action:
246 return self->state = MALA_EALLOC;
250 MalaEngine
251 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
253 MalaEngine self;
255 self = mala_engine_new ();
256 if (!self)
257 return NULL;
259 self->state = initfunc (self);
260 return self;
263 void
264 mala_engine_free (MalaEngine self)
266 int i;
268 if (!self)
269 return;
271 mala_stringlist_erase (&self->program);
272 mala_stringlist_erase (&self->arguments);
274 mala_stringbucket_erase (&self->words);
276 for (i = 0; i < MALA_STRING_MAX; ++i)
277 mala_string_free (self->common_string[i]);
279 free (self);
283 mala_engine_actions_register (MalaEngine self, mala_actioninit * actioninit)
285 MalaAction action;
287 if (mala_engine_state_get (self) > MALA_EFAULT)
288 return mala_engine_state_get (self);
290 while (actioninit->command)
292 action = mala_action_new_actioninit (actioninit, &self->words);
293 if (!action)
294 goto ealloc;
296 if (mala_action_attach (action) != MALA_SUCCESS)
297 goto ealloc;
299 ++actioninit;
302 return MALA_SUCCESS;
304 ealloc:
305 return self->state = MALA_EINIT;
309 /*TODO make some inlines { */
311 MalaStringList
312 mala_engine_getprogram (MalaEngine self)
314 if (mala_engine_state_get (self) > MALA_EFAULT)
315 return NULL;
317 return &self->program;
320 mala_state
321 mala_engine_state_get (MalaEngine self)
323 return self ? self->state : MALA_EINVALID;
326 const char *
327 mala_engine_state_str (MalaEngine self)
329 return mala_engine_states [self ? self->state : MALA_EINVALID];
332 void
333 mala_engine_clearstate (MalaEngine self)
335 if (self)
336 self->state = MALA_SUCCESS;
340 mala_engine_negated (MalaEngine self)
342 return self ? self->negated : -1;
345 void
346 mala_engine_clear_negated (MalaEngine self)
348 if (mala_engine_state_get (self) > MALA_EFAULT)
349 return;
350 self->negated = 0;
352 /* } TODO make some inlines */
355 void
356 mala_engine_dumpprogram (MalaEngine self, FILE* stream, const char * prefix, const char * suffix)
358 MalaStringListNode node;
360 if (!self)
361 return;
363 for (node = mala_stringlist_head (&self->program);
364 node != (void *)&self->program;
365 mala_stringlistnode_fwd (&node))
367 fprintf (stream, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
371 void
372 mala_engine_dumpargs (MalaEngine self, FILE* stream, const char * prefix, const char * suffix)
374 MalaStringListNode node;
376 if (!self)
377 return;
379 for (node = mala_stringlist_head (&self->arguments);
380 node != (void *)&self->arguments;
381 mala_stringlistnode_fwd (&node))
383 fprintf (stream, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
388 MalaEngine
389 mala_engine_run (MalaEngine self)
391 MalaStringListNode pptr;
393 if (mala_engine_state_get (self) > MALA_EFAULT)
394 return NULL;
396 while (self->state < MALA_EFAULT &&
397 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
399 if (self->state == MALA_LITERAL)
401 self->state = mala_engine_string_istrue (self,
402 mala_stringlistnode_string (pptr))
403 ? MALA_SUCCESS
404 : MALA_FAILURE;
405 mala_stringlist_elem_remove (&self->program, pptr);
406 mala_stringlist_tail_insert (&self->arguments, pptr);
408 else
409 mala_engine_eval (self, &pptr);
411 return self;
414 MalaEngine
415 mala_engine_step (MalaEngine self)
417 MalaStringListNode pptr;
419 pptr = mala_stringlist_head (&self->program);
421 mala_engine_eval (self, &pptr);
423 while (pptr->string == self->common_string[MALA_STRING_PASS])
424 mala_engine_eval (self, &pptr);
426 return self;
430 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
432 MalaAction act;
433 MalaActionDesc desc;
434 int state;
436 if (self->trace && (*pptr)->string != self->common_string[MALA_STRING_PASS])
438 fprintf (stderr, "%-8s: ", mala_engine_state_str (self));
439 mala_engine_dumpprogram (self, stderr, "", " ");
440 fprintf (stderr, "\n");
443 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
444 if (!desc)
445 goto def_parser;
447 act = mala_actiondesc_top (desc);
449 if (act)
451 state = mala_action_execute (act, pptr, self);
452 if (self->state != MALA_REMOVE)
453 self->state = state;
455 else
457 def_parser:
458 if (self->state != MALA_REMOVE)
460 if (!(*pptr = mala_stringlist_before_new (&self->program,
461 *pptr,
462 self->common_string[MALA_STRING_DEFAULT_PARSER])))
463 return self->state = state = MALA_EALLOC;
465 else
466 mala_stringlistnode_substitute_string (*pptr, self->common_string[MALA_STRING_DEFAULT_PARSER]);
469 if (self->state == MALA_EXCEPTION)
470 self->state = state = MALA_ENOACTION;
472 return state;
476 Evaluate the nth argument until one of the following happens
477 - for at most 'times' (-1 for full evaluation)
478 - until we reach a final state MALA_SUCCESS, MALA_FAILURE or MALA_LITERAL
479 - an error/exception is flagged
480 - the type associated with the data of the current word equals to 'type'
482 MalaStringListNode
483 mala_engine_arg_eval (MalaEngine self,
484 MalaStringListNode_ref pptr,
485 unsigned nth,
486 int times,
487 MalaDataFactory type)
489 MalaAction act;
490 MalaStringListNode next;
492 if (mala_engine_state_get (self) > MALA_EFAULT)
493 return NULL;
495 for (next = *pptr;
496 nth && !mala_stringlist_is_tail (&self->program, next);
497 mala_stringlistnode_fwd (&next), --nth);
499 if (nth)
500 goto eend;
502 if (self->state == MALA_REMOVE)
504 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (next->string));
505 mala_engine_eval (self, &next);
507 else
509 self->state = MALA_CONTINUE;
511 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (next->string));
512 while (self->state == MALA_CONTINUE
513 && times--
514 && ((act && type) ? (act->factory != type) : 1))
516 mala_engine_eval (self, &next);
517 if (mala_stringlist_is_end (&self->program, next))
518 goto eend;
522 return next;
524 eend:
525 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
526 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
527 return NULL;
531 mala_engine_arg_eval_fmt (MalaEngine self,
532 MalaStringListNode_ref pptr,
533 unsigned nth,
534 const char* fmt,
535 void * dest,
536 MalaPredicate pred,
537 void * constraint)
539 MalaStringListNode node;
540 int r;
542 node = mala_engine_arg_eval (self, pptr, nth, -1, NULL);
544 if (self->state != MALA_EXCEPTION)
546 r = mala_string_scan (mala_stringlistnode_string (node), fmt, dest);
547 if (r == 1 && pred)
548 r = pred (dest, constraint);
549 if (!r)
550 return mala_engine_exception (self, pptr, node,
551 self->common_string[MALA_STRING_ERROR_WRONG_TYPE]);
554 return self->state;
557 MalaString
558 mala_engine_arg_eval_string (MalaEngine self,
559 MalaStringListNode_ref pptr,
560 unsigned nth,
561 MalaPredicate pred,
562 void * constraint)
564 MalaString string;
566 string = mala_stringlistnode_string (mala_engine_arg_eval (self, pptr, nth, -1, NULL));
568 if (self->state >= MALA_EXCEPTION || ! (pred ? pred (string, constraint) : 1))
569 return NULL;
571 return string;
575 void
576 mala_engine_command_done (MalaEngine eng, MalaStringListNode_ref pptr, int args)
578 mala_stringlistnode_substitute_string (*pptr, eng->common_string[MALA_STRING_PASS]);
579 while (args--)
581 mala_stringlist_elem_delete (&eng->program, mala_stringlistnode_next (*pptr));
587 mala_engine_exception (MalaEngine self,
588 MalaStringListNode_ref pptr,
589 MalaStringListNode here,
590 MalaString except)
592 MalaStringListNode tmp;
594 if (mala_engine_state_get (self) > MALA_EFAULT)
595 return mala_engine_state_get (self);
597 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
598 if (!tmp)
599 return self->state = MALA_EALLOC;
601 if (!mala_stringlist_after_new (&self->program, here,
602 self->common_string[MALA_STRING_HERE]))
603 return self->state = MALA_EALLOC;
605 *pptr = tmp;
607 /*TODO self-state needs to be preserved somehow?*/
608 return self->state = MALA_EXCEPTION;
613 mala_engine_ppexpand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
615 int ret = 0;
617 if (self->state > MALA_EFAULT)
618 return MALA_EXPANSION_ERROR;
620 #define mala_run_expansion(name) \
621 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
623 mala_run_expansion (literal_expansion);
624 mala_run_expansion (numsplit_expansion);
625 mala_run_expansion (exclam_expansion);
626 mala_run_expansion (no_expansion);
627 mala_run_expansion (assign_expansion);
628 mala_run_expansion (char_expansion);
629 mala_run_expansion (underscore_expansion);
630 mala_run_expansion (bracket_expansion);
631 mala_run_expansion (assign_contraction);
632 mala_run_expansion (envvar_expansion);
633 mala_run_expansion (setenv_expansion);
634 mala_run_expansion (backquote_expansion);
635 #undef mala_run_expansion
637 return 1;
641 mala_engine_literal_expansion (MalaEngine self,
642 MalaStringList list,
643 MalaStringListNode_ref pptr)
645 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
646 && mala_string_check_prefix ((*pptr)->string, "`")
647 && !mala_string_check_prefix ((*pptr)->string, "``"))
649 MalaString nstr;
650 MalaStringListNode newnode1;
651 MalaStringListNode newnode2;
653 newnode1 = mala_stringlist_after_new (list,
654 *pptr,
655 self->common_string[MALA_STRING_LITERAL]);
656 if (!newnode1)
657 goto ealloc_newnode1;
659 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
660 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
661 if (!newnode2)
662 goto ealloc_newnode2;
664 mala_stringlist_elem_delete (list, *pptr);
665 *pptr = newnode1;
667 return 2;
669 ealloc_newnode2:
670 mala_stringlist_elem_delete (list, newnode1);
671 ealloc_newnode1:
672 self->state = MALA_EALLOC;
673 return MALA_EXPANSION_ERROR;
675 return MALA_NO_EXPANSION;
680 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
682 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
683 && mala_string_check_prefix ((*pptr)->string, "``"))
685 MalaString nstr;
686 MalaStringListNode newnode;
688 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
689 newnode = mala_stringlist_after_new (list, *pptr, nstr);
690 if (!newnode)
691 goto ealloc_newnode;
693 mala_stringlist_elem_delete (list, *pptr);
694 *pptr = newnode;
696 return 1;
698 ealloc_newnode:
699 self->state = MALA_EALLOC;
700 return MALA_EXPANSION_ERROR;
702 return MALA_NO_EXPANSION;
706 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
708 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
709 && mala_string_length ((*pptr)->string) > 2
710 && mala_string_at ((*pptr)->string, 0) == '-'
711 && isalpha (mala_string_at ((*pptr)->string, 1))
714 size_t i;
716 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
718 if (isdigit (mala_string_at ((*pptr)->string, i)))
720 MalaString a;
721 MalaString b;
723 MalaStringListNode na;
724 MalaStringListNode nb;
726 a = mala_string_new_substr ((*pptr)->string, 0, i);
727 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
728 if (!a || !b)
729 goto ealloc_str;
731 na = mala_stringlist_after_new (list, *pptr, a);
732 if (!na)
733 goto ealloc_nodea;
735 nb = mala_stringlist_after_new (list, na, b);
736 if (!nb)
737 goto ealloc_nodeb;
739 mala_stringlist_elem_delete (list, *pptr);
740 *pptr = na;
742 mala_string_free (a);
743 mala_string_free (b);
745 return 0;
747 ealloc_nodeb:
748 mala_stringlist_elem_delete (list, na);
749 ealloc_nodea:
750 ealloc_str:
751 mala_string_free (a);
752 mala_string_free (b);
753 self->state = MALA_EALLOC;
754 return MALA_EXPANSION_ERROR;
758 return MALA_NO_EXPANSION;
763 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
765 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
766 && mala_string_length ((*pptr)->string) == 1
767 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
769 MalaStringListNode newnode;
771 newnode = mala_stringlist_after_new (list,
772 *pptr,
773 self->common_string[MALA_STRING_NOT]);
774 if (!newnode)
775 return self->state = MALA_EALLOC;
777 mala_stringlist_elem_delete (list, *pptr);
778 *pptr= newnode;
779 return 1;
781 return MALA_NO_EXPANSION;
786 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
788 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
789 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
790 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
792 MalaString a;
793 MalaString aa;
794 MalaStringListNode n1;
795 MalaStringListNode n2;
797 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
798 aa = mala_string_new_prefix ("--", a);
799 if (!a || !aa)
800 goto ealloc_a;
802 n1 = mala_stringlist_after_new (list,
803 *pptr, self->common_string[MALA_STRING_NOT]);
804 if (!n1)
805 goto ealloc_n1;
807 n2 = mala_stringlist_after_new (list, n1, aa);
808 if (!n2)
809 goto ealloc_n2;
811 mala_string_free (a);
812 mala_string_free (aa);
813 mala_stringlist_elem_delete (list, *pptr);
814 *pptr = n1;
815 return 1;
817 ealloc_n2:
818 mala_stringlist_elem_delete (list, n1);
819 ealloc_n1:
820 mala_string_free (a);
821 mala_string_free (aa);
822 ealloc_a:
823 self->state = MALA_EALLOC;
824 return MALA_EXPANSION_ERROR;
826 return MALA_NO_EXPANSION;
831 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
833 size_t eq;
835 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
836 && mala_string_check_prefix ((*pptr)->string, "--")
837 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
838 && mala_string_length ((*pptr)->string) > eq + 1)
840 MalaString a;
841 MalaString b;
843 MalaStringListNode na;
844 MalaStringListNode nb;
846 a = mala_string_new_substr ((*pptr)->string, 0, eq);
847 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
848 if (!a || !b)
849 goto ealloc_str;
851 na = mala_stringlist_after_new (list, *pptr, a);
852 if (!na)
853 goto ealloc_nodea;
855 nb = mala_stringlist_after_new (list, na, b);
856 if (!nb)
857 goto ealloc_nodeb;
859 mala_stringlist_elem_delete (list, *pptr);
860 *pptr = na;
862 mala_string_free (a);
863 mala_string_free (b);
866 return 0;
868 ealloc_nodeb:
869 mala_stringlist_elem_delete (list, na);
870 ealloc_nodea:
871 ealloc_str:
872 mala_string_free (a);
873 mala_string_free (b);
874 self->state = MALA_EALLOC;
875 return MALA_EXPANSION_ERROR;
877 return MALA_NO_EXPANSION;
882 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
884 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
885 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
887 MalaStringListNode newnode;
889 newnode = mala_stringlist_before_new (list,
890 *pptr,
891 self->common_string[MALA_STRING_ENVSUBST]);
892 if (!newnode)
893 goto ealloc_node;
895 *pptr= newnode;
896 return 2;
898 ealloc_node:
899 self->state = MALA_EALLOC;
900 return MALA_EXPANSION_ERROR;
903 return MALA_NO_EXPANSION;
908 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
910 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
911 && mala_string_length ((*pptr)->string) > 2
912 && ( mala_string_at ((*pptr)->string, 0) == '-'
913 || mala_string_at ((*pptr)->string, 0) == '+')
914 && isalpha (mala_string_at ((*pptr)->string, 1)))
916 char prefix[2] = "-";
917 char current[2] = " ";
918 const char * i;
919 int cnt = 0;
921 MalaString str;
922 MalaStringListNode node = NULL;
923 MalaStringListNode pred = *pptr;
926 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
928 if (*i == '-' || *i == '+')
929 prefix[0] = *i;
930 else if (isalpha (*i))
932 ++cnt;
933 current[0] = *i;
934 str = mala_string_new_cat2 (prefix, current,
935 mala_string_bucket_get ((*pptr)->string));
936 if (!str)
937 goto ealloc;
939 node = mala_stringlist_after_new (list,
940 pred, str);
941 if (!node)
942 goto ealloc;
944 pred = node;
945 mala_string_free (str);
947 else
948 break;
951 pred = *pptr;
952 mala_stringlistnode_fwd (&pred);
953 mala_stringlist_elem_delete (list, *pptr);
954 *pptr= pred;
955 return cnt;
957 ealloc:
958 mala_string_free (str);
959 /* cleanup from pred downto pptr */
960 while (pred != *pptr)
962 MalaStringListNode tmp = mala_stringlistnode_prev (pred);
963 mala_stringlist_elem_delete (list, pred);
964 pred = tmp;
966 self->state = MALA_EALLOC;
967 return MALA_EXPANSION_ERROR;
969 return MALA_NO_EXPANSION;
974 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
976 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
977 && mala_string_check_prefix ((*pptr)->string, "--")
978 && strchr (mala_string_cstr ((*pptr)->string), '_'))
980 MalaString str;
981 MalaStringListNode node;
982 char * cstr;
983 char * i;
985 cstr = strdup (mala_string_cstr ((*pptr)->string));
986 if (!cstr)
987 goto ealloc_cstr;
989 for (i = cstr + 2; *i; ++i)
991 if (*i == '_')
992 *i = '-';
995 str = mala_string_new (cstr, &self->words);
996 if (!str)
997 goto ealloc_str;
999 node = mala_stringlist_after_new (list,
1000 *pptr,
1001 str);
1002 if (!node)
1003 goto ealloc_node;
1005 free (cstr);
1006 mala_string_free (str);
1008 mala_stringlist_elem_delete (list, *pptr);
1009 *pptr= node;
1010 return 0;
1012 ealloc_node:
1013 mala_string_free (str);
1014 ealloc_str:
1015 free (cstr);
1016 ealloc_cstr:
1017 self->state = MALA_EALLOC;
1018 return MALA_EXPANSION_ERROR;
1020 return MALA_NO_EXPANSION;
1025 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
1027 size_t eq;
1029 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
1030 && mala_string_length ((*pptr)->string) > 1
1031 && (eq = mala_string_char_find ((*pptr)->string, '='))
1032 && eq > 0
1033 && eq < SIZE_MAX
1034 && !mala_string_check_prefix ((*pptr)->string, "-"))
1036 MalaString key;
1037 MalaString value;
1038 MalaStringListNode n1;
1039 MalaStringListNode n2;
1040 MalaStringListNode n3;
1042 key = mala_string_new_substr ((*pptr)->string, 0, eq);
1043 if (!key)
1044 goto ealloc_key;
1046 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
1047 if (!value)
1048 goto ealloc_value;
1050 n1 = mala_stringlist_after_new (list,
1051 *pptr, self->common_string[MALA_STRING_SETENV]);
1052 if (!n1)
1053 goto ealloc_n1;
1055 n2 = mala_stringlist_after_new (list, n1, key);
1056 if (!n2)
1057 goto ealloc_n2;
1059 n3 = mala_stringlist_after_new (list, n2, value);
1060 if (!n3)
1061 goto ealloc_n3;
1063 mala_string_free (key);
1064 mala_string_free (value);
1065 mala_stringlist_elem_delete (list, *pptr);
1066 *pptr = n1;
1067 return 3;
1069 ealloc_n3:
1070 mala_stringlist_elem_delete (list, n2);
1071 ealloc_n2:
1072 mala_stringlist_elem_delete (list, n1);
1073 ealloc_n1:
1074 mala_string_free (value);
1075 ealloc_value:
1076 mala_string_free (key);
1077 ealloc_key:
1078 self->state = MALA_EALLOC;
1079 return MALA_EXPANSION_ERROR;
1081 return MALA_NO_EXPANSION;
1086 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
1088 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
1089 && mala_string_at ((*pptr)->string, 0) == '[')
1091 MalaStringListNode nitr;
1092 MalaStringListNode node;
1094 MalaString str1 = NULL;
1095 MalaStringListNode node1;
1097 MalaString str2 = NULL;
1098 MalaStringListNode node2;
1100 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
1101 if (!node)
1102 goto ealloc_node;
1104 if (mala_string_length((*pptr)->string) > 1)
1106 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
1107 node1 = mala_stringlist_after_new (list, node, str1);
1108 if (!node1)
1109 goto ealloc_node1;
1111 else
1113 node1 = node;
1114 mala_stringlistnode_fwd (&node1);
1117 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlistnode_fwd (&nitr))
1119 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1120 break;
1123 if ((void*)nitr != (void*)list)
1125 if (mala_string_length(nitr->string) > 1)
1127 str2 = mala_string_new_substr (nitr->string, 0,
1128 mala_string_length(nitr->string) - 1);
1129 node2 = mala_stringlist_after_new (list, nitr, str2);
1130 if (!node2)
1131 goto ealloc_node2;
1134 else
1135 goto esyntax;
1138 mala_string_free (str1);
1139 mala_string_free (str2);
1140 mala_stringlist_elem_delete (list, *pptr);
1141 mala_stringlist_elem_delete (list, nitr);
1142 *pptr = node;
1144 return 0;
1146 esyntax:
1147 mala_string_free (str1);
1148 mala_stringlist_elem_delete (list, node1);
1149 mala_stringlist_elem_delete (list, node);
1150 self->state = MALA_ESYNTAX;
1151 return MALA_EXPANSION_ERROR;
1153 ealloc_node2:
1154 mala_string_free (str1);
1155 mala_stringlist_elem_delete (list, node1);
1156 ealloc_node1:
1157 mala_stringlist_elem_delete (list, node);
1158 ealloc_node:
1159 self->state = MALA_EALLOC;
1160 return MALA_EXPANSION_ERROR;
1162 return MALA_NO_EXPANSION;
1167 mala_engine_assign_contraction (MalaEngine self,
1168 MalaStringList list,
1169 MalaStringListNode_ref pptr)
1171 MalaStringListNode assign;
1172 MalaStringListNode value ;
1174 assign = *pptr;
1175 mala_stringlistnode_fwd (&assign);
1176 value = assign;
1178 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1179 && !mala_stringlist_is_tail (list, *pptr)
1180 && !mala_stringlist_is_tail (list, assign)
1181 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1183 MalaString str;
1184 MalaStringListNode node;
1186 mala_stringlistnode_fwd (&value);
1188 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1189 "%s=%s",
1190 mala_string_cstr ((*pptr)->string),
1191 mala_string_cstr (value->string));
1194 node = mala_stringlist_after_new (list,
1195 value,
1196 str);
1197 if (!node)
1198 goto ealloc_node;
1200 mala_string_free (str);
1201 mala_stringlist_elem_delete (list, *pptr);
1202 mala_stringlist_elem_delete (list, assign);
1203 mala_stringlist_elem_delete (list, value);
1204 *pptr = node;
1205 return 0;
1207 ealloc_node:
1208 mala_string_free (str);
1209 self->state = MALA_EALLOC;
1210 return MALA_EXPANSION_ERROR;
1212 return MALA_NO_EXPANSION;
1219 mala_engine_string_istrue (MalaEngine self, MalaString str)
1221 /*TODO check for other zero representations 0.0 0e0 etc.*/
1222 if (!str
1223 || !mala_string_compare (str, self->common_string[MALA_STRING_EMPTY])
1224 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1225 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1226 return 0;
1228 return 1;
1232 mala_engine_check_expansionflag (MalaEngine self, int flag)
1234 MalaActionDesc desc;
1235 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1237 /*only enabled when the topmost action is a subtitution to --TRUE*/
1238 return mala_actiondesc_data_top (desc) == self->common_string[MALA_STRING_TRUE];
1253 #if 0 /*TODO*/
1255 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1257 MalaAction act;
1259 if (self->state > MALA_EFAULT)
1260 return self->state;
1262 act = mala_actiondict_lookupaction (self->actions, key);
1263 if (!act)
1264 goto enoact;
1266 mala_actiondict_destroy_action (self->actions, act);
1268 return MALA_SUCCESS;
1270 enoact:
1271 self->state = MALA_ENOACTION;
1272 return self->state;
1278 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1280 MalaStringListNode base = llist_get_prev (pptr);
1281 while (mala_engine_eval (self, llist_get_nextt (base)) < MALA_EVAL)
1282 if (llist_get_next (base) == &self->program)
1283 return MALA_ENOACTION;
1285 return self->state;
1290 void
1291 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1293 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1299 mala_engine_argc (MalaEngine self)
1301 return llist_count (&self->arguments) + 1;
1304 const char*
1305 mala_engine_argv (MalaEngine self, int n)
1307 MalaStringListNode p;
1308 p = llist_get_next (&self->arguments);
1310 if (n==0)
1311 return self->argv_0;
1313 while (--n)
1315 if (p == &self->arguments)
1316 return 0;
1317 p = llist_get_next (p);
1319 return (const char *)(p)->data;
1324 MalaAction
1325 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1326 MalaParserFunc parser, MalaDataDestructor destructor)
1328 MalaAction act;
1330 act = mala_action_new (name, data, parser, destructor);
1331 if (!act)
1332 goto ealloc;
1334 self->state = mala_actiondict_push (self->actions, act);
1335 if (self->state)
1336 goto epush;
1338 return act;
1340 epush:
1341 mala_action_destroy (act);
1342 ealloc:
1343 return 0;
1347 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1349 MalaAction act;
1351 act = mala_actiondict_lookupaction (self->actions, name);
1352 if (!act)
1353 return MALA_NO_EXPANSION;
1355 if (act->parser != mala_substitute_parser)
1356 return MALA_EPARSER;
1358 return mala_string_check ((t_uchar*) act->data);
1362 MalaAction
1363 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1365 return mala_actiondict_lookupaction (self->actions, name);
1368 MalaAction
1369 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1371 return mala_actiondict_lookupprevaction (self->actions, name);
1374 #endif /*TODO*/
1381 // Local Variables:
1382 // mode: C
1383 // c-file-style: "gnu"
1384 // End:
1385 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1386 // end_of_file