omit args/newline printing if there are none
[mala.git] / engine / engine.c
blob142658472ec1b0f5811452e013e6e601974efc44
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 (mala_engine_state_get (self) > MALA_EFAULT)
95 return mala_engine_state_get (self);
97 mala_stringlist_init (&pre);
99 for (i = 0; i != argc && *argv; ++i ,++argv)
101 if (!mala_stringlist_tail_new_cstr (&pre, *argv, &self->words))
102 goto ealloc_node;
105 list = mala_stringlist_new ();
106 if (!list)
107 goto ealloc_list;
109 /*TODO preprocess in own function*/
110 while (!mala_stringlist_is_empty (&pre))
112 int putaway;
114 itr = mala_stringlist_head (&pre);
116 putaway = mala_engine_ppexpand (self, &pre, &itr);
118 if (self->state > MALA_EFAULT)
119 return self->state;
121 while (putaway--)
123 mala_stringlist_node_remove (&pre, itr);
124 mala_stringlist_tail_insert (list, itr);
125 if (putaway && mala_stringlist_is_empty (&pre))
126 goto eunderrun;
127 itr = mala_stringlist_head (&pre);
131 if (mala_stringlist_is_empty (list))
133 /* empty substituted by --NULL, TODO use empty string instead? */
134 mala_stringlist_free (list);
135 return mala_engine_add_action_cstr (self, name,
136 mala_string_copy (self->common_string[MALA_STRING_NULL]),
137 mala_substitute_parser,
138 (MalaDataFactory)mala_string_factory,
139 NULL);
142 if (mala_stringlist_is_tail (list, mala_stringlist_head (list)))
144 /* substitute */
145 MalaString subst;
147 subst = mala_string_copy (mala_stringlist_head (list) -> string);
148 mala_stringlist_free (list);
150 return mala_engine_add_action_cstr (self, name, subst,
151 mala_substitute_parser,
152 (MalaDataFactory)mala_string_factory,
153 NULL);
155 else
157 /* expand */
158 return mala_engine_add_action_cstr (self, name, list,
159 mala_expand_parser,
160 (MalaDataFactory) mala_stringlist_factory,
161 NULL);
164 eunderrun:
165 mala_stringlist_free (list);
166 mala_stringlist_erase (&pre);
167 return self->state = MALA_ESYNTAX;
169 ealloc_list:
170 ealloc_node:
171 mala_stringlist_erase (&pre);
172 return self->state = MALA_EALLOC;
176 mala_engine_pushback_word (MalaEngine self, const char * word)
178 if (mala_engine_state_get (self) > MALA_EFAULT)
179 return mala_engine_state_get (self);
181 if (!mala_stringlist_tail_new_cstr (&self->program, word, &self->words))
182 return self->state = MALA_EALLOC;
184 return MALA_SUCCESS;
188 mala_engine_add_action_cstr (MalaEngine self, const char * cname, void * data,
189 MalaParserFunc parser, MalaDataFactory factory,
190 MalaAction parent)
192 MalaString name;
193 MalaAction action;
195 if (mala_engine_state_get (self) > MALA_EFAULT)
196 return mala_engine_state_get (self);
198 name = mala_string_new (cname, &self->words);
199 if (!name)
200 goto ealloc_name;
202 action = mala_action_new (name, data, parser, factory, parent);
203 if (!action)
204 goto ealloc_action;
206 if (mala_action_attach (action) != MALA_SUCCESS)
207 goto ealloc_attach;
209 mala_string_free (name);
210 return MALA_SUCCESS;
212 ealloc_attach:
213 mala_action_free (action);
214 ealloc_action:
215 mala_string_free (name);
216 ealloc_name:
217 return self->state = MALA_EALLOC;
221 mala_engine_add_action (MalaEngine self, MalaString name, void * data,
222 MalaParserFunc parser, MalaDataFactory factory,
223 MalaAction parent)
225 MalaAction action;
227 if (mala_engine_state_get (self) > MALA_EFAULT)
228 return mala_engine_state_get (self);
230 action = mala_action_new (name, data, parser, factory, parent);
231 if (!action)
232 goto ealloc_action;
234 if (mala_action_attach (action) != MALA_SUCCESS)
235 goto ealloc_attach;
237 return MALA_SUCCESS;
239 ealloc_attach:
240 mala_action_free (action);
241 ealloc_action:
242 return self->state = MALA_EALLOC;
246 MalaEngine
247 mala_engine_new_initfunc (int (*initfunc)(MalaEngine))
249 MalaEngine self;
251 self = mala_engine_new ();
252 if (!self)
253 return NULL;
255 self->state = initfunc (self);
256 return self;
259 void
260 mala_engine_free (MalaEngine self)
262 int i;
264 if (!self)
265 return;
267 mala_stringlist_erase (&self->program);
268 mala_stringlist_erase (&self->arguments);
270 mala_stringbucket_erase (&self->words);
272 for (i = 0; i < MALA_STRING_MAX; ++i)
273 mala_string_free (self->common_string[i]);
275 free (self);
279 mala_engine_actions_register (MalaEngine self, mala_actioninit * actioninit)
281 MalaAction action;
283 if (mala_engine_state_get (self) > MALA_EFAULT)
284 return mala_engine_state_get (self);
286 while (actioninit->command)
288 action = mala_action_new_actioninit (actioninit, &self->words);
289 if (!action)
290 goto ealloc;
292 if (mala_action_attach (action) != MALA_SUCCESS)
293 goto ealloc;
295 ++actioninit;
298 return MALA_SUCCESS;
300 ealloc:
301 return self->state = MALA_EINIT;
305 /*TODO make some inlines { */
307 MalaStringList
308 mala_engine_getprogram (MalaEngine self)
310 if (mala_engine_state_get (self) > MALA_EFAULT)
311 return NULL;
313 return &self->program;
316 mala_state
317 mala_engine_state_get (MalaEngine self)
319 return self ? self->state : MALA_EINVALID;
322 void
323 mala_engine_clearstate (MalaEngine self)
325 if (self)
326 self->state = MALA_SUCCESS;
330 mala_engine_negated (MalaEngine self)
332 return self ? self->negated : -1;
335 void
336 mala_engine_clear_negated (MalaEngine self)
338 if (mala_engine_state_get (self) > MALA_EFAULT)
339 return;
340 self->negated = 0;
342 /* } TODO make some inlines */
345 void
346 mala_engine_dumpprogram (MalaEngine self, FILE* stream, const char * prefix, const char * suffix)
348 MalaStringListNode node;
350 if (!self)
351 return;
353 for (node = mala_stringlist_head (&self->program);
354 node != (void *)&self->program;
355 mala_stringlistnode_fwd (&node))
357 fprintf (stream, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
361 void
362 mala_engine_dumpargs (MalaEngine self, FILE* stream, const char * prefix, const char * suffix)
364 MalaStringListNode node;
366 if (!self)
367 return;
369 for (node = mala_stringlist_head (&self->arguments);
370 node != (void *)&self->arguments;
371 mala_stringlistnode_fwd (&node))
373 fprintf (stream, "%s%s%s", prefix, mala_string_cstr (node->string), suffix);
378 MalaEngine
379 mala_engine_run (MalaEngine self)
381 MalaStringListNode pptr;
383 if (mala_engine_state_get (self) > MALA_EFAULT)
384 return NULL;
386 while (self->state < MALA_EFAULT &&
387 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
389 if (self->state == MALA_LITERAL)
391 mala_stringlist_elem_remove (&self->program, pptr);
392 mala_stringlist_tail_insert (&self->arguments, pptr);
393 self->state = MALA_SUCCESS;
395 else
396 mala_engine_eval (self, &pptr);
398 return self;
401 MalaEngine
402 mala_engine_step (MalaEngine self)
404 MalaStringListNode pptr;
406 if (mala_engine_state_get (self) > MALA_EFAULT)
407 return NULL;
409 if (self->state < MALA_EFAULT &&
410 (pptr = mala_stringlist_head (&self->program)) != (void *)&self->program)
412 if (self->state == MALA_LITERAL)
414 mala_stringlist_elem_remove (&self->program, pptr);
415 mala_stringlist_tail_insert (&self->arguments, pptr);
416 self->state = MALA_SUCCESS;
418 else
419 mala_engine_eval (self, &pptr);
421 return self;
425 mala_engine_eval (MalaEngine self, MalaStringListNode_ref pptr)
427 MalaAction act;
428 MalaActionDesc desc;
430 desc = (MalaActionDesc) mala_string_user_get ((*pptr)->string);
431 if (!desc)
432 goto def_parser;
434 act = mala_actiondesc_top (desc);
436 if (act)
437 self->state = mala_action_execute (act, pptr, self);
438 else
440 def_parser:
441 if (!(*pptr = mala_stringlist_before_new (&self->program,
442 *pptr,
443 self->common_string[MALA_STRING_DEFAULT_PARSER])))
444 return self->state = MALA_EALLOC;
447 if (self->state == MALA_EXCEPTION)
448 self->state = MALA_ENOACTION;
450 return self->state;
454 Evaluate the nth argument until one of the following happens
455 - for at most 'times' (-1 for full evaluation)
456 - until we reach the state of MALA_LITERAL (no further expansions are possible)
457 - an error/exception is flagged
458 - the type associated with the data of the current word equals to 'type'
460 MalaStringListNode
461 mala_engine_arg_eval (MalaEngine self,
462 MalaStringListNode_ref pptr,
463 unsigned nth,
464 int times,
465 MalaDataFactory type)
467 MalaAction act;
468 MalaStringListNode next;
470 if (mala_engine_state_get (self) > MALA_EFAULT)
471 return NULL;
473 for (next = *pptr;
474 nth && !mala_stringlist_is_tail (&self->program, next);
475 mala_stringlistnode_fwd (&next), --nth);
477 if (nth)
478 goto eend;
480 self->state = MALA_SUCCESS;
481 act = mala_actiondesc_top ((MalaActionDesc) mala_string_user_get (next->string));
482 while (self->state < MALA_LITERAL
483 && times--
484 && ((act && type) ? (act->factory != type) : 1))
486 mala_engine_eval (self, &next);
487 if (mala_stringlist_is_end (&self->program, next))
488 goto eend;
491 return next;
493 eend:
494 mala_engine_exception (self, pptr, mala_stringlist_tail (&self->program),
495 self->common_string[MALA_STRING_ERROR_MISSING_ARGUMENT]);
496 return NULL;
500 mala_engine_arg_eval_fmt (MalaEngine self,
501 MalaStringListNode_ref pptr,
502 unsigned nth,
503 const char* fmt,
504 void * dest,
505 MalaPredicate pred,
506 void * constraint)
508 MalaStringListNode node;
509 int r;
511 node = mala_engine_arg_eval (self, pptr, nth, -1, NULL);
513 if (self->state != MALA_EXCEPTION)
515 r = mala_string_scan (mala_stringlistnode_string (node), fmt, dest);
516 if (r == 1 && pred)
517 r = pred (dest, constraint);
518 if (!r)
519 return mala_engine_exception (self, pptr, node,
520 self->common_string[MALA_STRING_ERROR_WRONG_TYPE]);
523 return self->state;
526 MalaString
527 mala_engine_arg_eval_string (MalaEngine self,
528 MalaStringListNode_ref pptr,
529 unsigned nth,
530 MalaPredicate pred,
531 void * constraint)
533 MalaString string;
535 string = mala_stringlistnode_string (mala_engine_arg_eval (self, pptr, nth, -1, NULL));
537 if (self->state >= MALA_EXCEPTION || ! (pred ? pred (string, constraint) : 1))
538 return NULL;
540 return string;
544 mala_engine_exception (MalaEngine self,
545 MalaStringListNode_ref pptr,
546 MalaStringListNode here,
547 MalaString except)
549 MalaStringListNode tmp;
551 if (mala_engine_state_get (self) > MALA_EFAULT)
552 return mala_engine_state_get (self);
554 tmp = mala_stringlist_before_new (&self->program, *pptr, except);
555 if (!tmp)
556 return self->state = MALA_EALLOC;
558 if (!mala_stringlist_after_new (&self->program, here,
559 self->common_string[MALA_STRING_HERE]))
560 return self->state = MALA_EALLOC;
562 *pptr = tmp;
564 /*TODO self-state needs to be preserved somehow?*/
565 return self->state = MALA_EXCEPTION;
570 mala_engine_ppexpand (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
572 int ret = 0;
574 if (self->state > MALA_EFAULT)
575 return MALA_EXPANSION_ERROR;
577 #define mala_run_expansion(name) \
578 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
580 mala_run_expansion (literal_expansion);
581 mala_run_expansion (numsplit_expansion);
582 mala_run_expansion (exclam_expansion);
583 mala_run_expansion (no_expansion);
584 mala_run_expansion (assign_expansion);
585 mala_run_expansion (char_expansion);
586 mala_run_expansion (underscore_expansion);
587 mala_run_expansion (bracket_expansion);
588 mala_run_expansion (assign_contraction);
589 mala_run_expansion (envvar_expansion);
590 mala_run_expansion (setenv_expansion);
591 mala_run_expansion (backquote_expansion);
592 #undef mala_run_expansion
594 return 1;
598 mala_engine_literal_expansion (MalaEngine self,
599 MalaStringList list,
600 MalaStringListNode_ref pptr)
602 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
603 && mala_string_check_prefix ((*pptr)->string, "`")
604 && !mala_string_check_prefix ((*pptr)->string, "``"))
606 MalaString nstr;
607 MalaStringListNode newnode1;
608 MalaStringListNode newnode2;
610 newnode1 = mala_stringlist_after_new (list,
611 *pptr,
612 self->common_string[MALA_STRING_LITERAL]);
613 if (!newnode1)
614 goto ealloc_newnode1;
616 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
617 newnode2 = mala_stringlist_after_new (list, newnode1, nstr);
618 if (!newnode2)
619 goto ealloc_newnode2;
621 mala_stringlist_elem_delete (list, *pptr);
622 *pptr = newnode1;
624 return 2;
626 ealloc_newnode2:
627 mala_stringlist_elem_delete (list, newnode1);
628 ealloc_newnode1:
629 self->state = MALA_EALLOC;
630 return MALA_EXPANSION_ERROR;
632 return MALA_NO_EXPANSION;
637 mala_engine_backquote_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
639 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_LITERAL_EXPANSION)
640 && mala_string_check_prefix ((*pptr)->string, "``"))
642 MalaString nstr;
643 MalaStringListNode newnode;
645 nstr = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
646 newnode = mala_stringlist_after_new (list, *pptr, nstr);
647 if (!newnode)
648 goto ealloc_newnode;
650 mala_stringlist_elem_delete (list, *pptr);
651 *pptr = newnode;
653 return 1;
655 ealloc_newnode:
656 self->state = MALA_EALLOC;
657 return MALA_EXPANSION_ERROR;
659 return MALA_NO_EXPANSION;
663 mala_engine_numsplit_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
665 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NUMSPLIT_EXPANSION)
666 && mala_string_length ((*pptr)->string) > 2
667 && mala_string_at ((*pptr)->string, 0) == '-'
668 && isalpha (mala_string_at ((*pptr)->string, 1))
671 size_t i;
673 for (i = 2; i < mala_string_length ((*pptr)->string); ++i)
675 if (isdigit (mala_string_at ((*pptr)->string, i)))
677 MalaString a;
678 MalaString b;
680 MalaStringListNode na;
681 MalaStringListNode nb;
683 a = mala_string_new_substr ((*pptr)->string, 0, i);
684 b = mala_string_new_substr ((*pptr)->string, i, SIZE_MAX);
685 if (!a || !b)
686 goto ealloc_str;
688 na = mala_stringlist_after_new (list, *pptr, a);
689 if (!na)
690 goto ealloc_nodea;
692 nb = mala_stringlist_after_new (list, na, b);
693 if (!nb)
694 goto ealloc_nodeb;
696 mala_stringlist_elem_delete (list, *pptr);
697 *pptr = na;
699 mala_string_free (a);
700 mala_string_free (b);
702 return 0;
704 ealloc_nodeb:
705 mala_stringlist_elem_delete (list, na);
706 ealloc_nodea:
707 ealloc_str:
708 mala_string_free (a);
709 mala_string_free (b);
710 self->state = MALA_EALLOC;
711 return MALA_EXPANSION_ERROR;
715 return MALA_NO_EXPANSION;
720 mala_engine_exclam_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
722 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_EXCLAM_EXPANSION)
723 && mala_string_length ((*pptr)->string) == 1
724 && mala_string_same ((*pptr)->string, self->common_string[MALA_STRING_EXCLAMATIONMARK]))
726 MalaStringListNode newnode;
728 newnode = mala_stringlist_after_new (list,
729 *pptr,
730 self->common_string[MALA_STRING_NOT]);
731 if (!newnode)
732 return self->state = MALA_EALLOC;
734 mala_stringlist_elem_delete (list, *pptr);
735 *pptr= newnode;
736 return 1;
738 return MALA_NO_EXPANSION;
743 mala_engine_no_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
745 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_NO_EXPANSION)
746 && mala_string_check_prefix_nocase ((*pptr)->string, "--NO-")
747 && mala_string_length ((*pptr)->string) >= sizeof ("--NO-"))
749 MalaString a;
750 MalaString aa;
751 MalaStringListNode n1;
752 MalaStringListNode n2;
754 a = mala_string_new_substr ((*pptr)->string, sizeof ("--NO-")-1, SIZE_MAX);
755 aa = mala_string_new_prefix ("--", a);
756 if (!a || !aa)
757 goto ealloc_a;
759 n1 = mala_stringlist_after_new (list,
760 *pptr, self->common_string[MALA_STRING_NOT]);
761 if (!n1)
762 goto ealloc_n1;
764 n2 = mala_stringlist_after_new (list, n1, aa);
765 if (!n2)
766 goto ealloc_n2;
768 mala_string_free (a);
769 mala_string_free (aa);
770 mala_stringlist_elem_delete (list, *pptr);
771 *pptr = n1;
772 return 1;
774 ealloc_n2:
775 mala_stringlist_elem_delete (list, n1);
776 ealloc_n1:
777 mala_string_free (a);
778 mala_string_free (aa);
779 ealloc_a:
780 self->state = MALA_EALLOC;
781 return MALA_EXPANSION_ERROR;
783 return MALA_NO_EXPANSION;
788 mala_engine_assign_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
790 size_t eq;
792 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_EXPANSION)
793 && mala_string_check_prefix ((*pptr)->string, "--")
794 && ((eq = mala_string_char_find ((*pptr)->string, '=')) != SIZE_MAX)
795 && mala_string_length ((*pptr)->string) > eq + 1)
797 MalaString a;
798 MalaString b;
800 MalaStringListNode na;
801 MalaStringListNode nb;
803 a = mala_string_new_substr ((*pptr)->string, 0, eq);
804 b = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
805 if (!a || !b)
806 goto ealloc_str;
808 na = mala_stringlist_after_new (list, *pptr, a);
809 if (!na)
810 goto ealloc_nodea;
812 nb = mala_stringlist_after_new (list, na, b);
813 if (!nb)
814 goto ealloc_nodeb;
816 mala_stringlist_elem_delete (list, *pptr);
817 *pptr = na;
819 mala_string_free (a);
820 mala_string_free (b);
823 return 0;
825 ealloc_nodeb:
826 mala_stringlist_elem_delete (list, na);
827 ealloc_nodea:
828 ealloc_str:
829 mala_string_free (a);
830 mala_string_free (b);
831 self->state = MALA_EALLOC;
832 return MALA_EXPANSION_ERROR;
834 return MALA_NO_EXPANSION;
839 mala_engine_envvar_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
841 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ENVVAR_EXPANSION)
842 && (mala_string_char_find ((*pptr)->string, '$') != SIZE_MAX))
844 MalaStringListNode newnode;
846 newnode = mala_stringlist_before_new (list,
847 *pptr,
848 self->common_string[MALA_STRING_ENVSUBST]);
849 if (!newnode)
850 goto ealloc_node;
852 *pptr= newnode;
853 return 2;
855 ealloc_node:
856 self->state = MALA_EALLOC;
857 return MALA_EXPANSION_ERROR;
860 return MALA_NO_EXPANSION;
865 mala_engine_char_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
867 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_CHAR_EXPANSION)
868 && mala_string_length ((*pptr)->string) > 2
869 && ( mala_string_at ((*pptr)->string, 0) == '-'
870 || mala_string_at ((*pptr)->string, 0) == '+')
871 && isalpha (mala_string_at ((*pptr)->string, 1)))
873 char prefix[2] = "-";
874 char current[2] = " ";
875 const char * i;
876 int cnt = 0;
878 MalaString str;
879 MalaStringListNode node = NULL;
880 MalaStringListNode pred = *pptr;
883 for (i = mala_string_cstr ((*pptr)->string); *i; ++i)
885 if (*i == '-' || *i == '+')
886 prefix[0] = *i;
887 else if (isalpha (*i))
889 ++cnt;
890 current[0] = *i;
891 str = mala_string_new_cat2 (prefix, current,
892 mala_string_bucket_get ((*pptr)->string));
893 if (!str)
894 goto ealloc;
896 node = mala_stringlist_after_new (list,
897 pred, str);
898 if (!node)
899 goto ealloc;
901 pred = node;
902 mala_string_free (str);
904 else
905 break;
908 pred = *pptr;
909 mala_stringlistnode_fwd (&pred);
910 mala_stringlist_elem_delete (list, *pptr);
911 *pptr= pred;
912 return cnt;
914 ealloc:
915 mala_string_free (str);
916 /* cleanup from pred downto pptr */
917 while (pred != *pptr)
919 MalaStringListNode tmp = mala_stringlistnode_prev (pred);
920 mala_stringlist_elem_delete (list, pred);
921 pred = tmp;
923 self->state = MALA_EALLOC;
924 return MALA_EXPANSION_ERROR;
926 return MALA_NO_EXPANSION;
931 mala_engine_underscore_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
933 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_UNDERSCORE_EXPANSION)
934 && mala_string_check_prefix ((*pptr)->string, "--")
935 && strchr (mala_string_cstr ((*pptr)->string), '_'))
937 MalaString str;
938 MalaStringListNode node;
939 char * cstr;
940 char * i;
942 cstr = strdup (mala_string_cstr ((*pptr)->string));
943 if (!cstr)
944 goto ealloc_cstr;
946 for (i = cstr + 2; *i; ++i)
948 if (*i == '_')
949 *i = '-';
952 str = mala_string_new (cstr, &self->words);
953 if (!str)
954 goto ealloc_str;
956 node = mala_stringlist_after_new (list,
957 *pptr,
958 str);
959 if (!node)
960 goto ealloc_node;
962 free (cstr);
963 mala_string_free (str);
965 mala_stringlist_elem_delete (list, *pptr);
966 *pptr= node;
967 return 0;
969 ealloc_node:
970 mala_string_free (str);
971 ealloc_str:
972 free (cstr);
973 ealloc_cstr:
974 self->state = MALA_EALLOC;
975 return MALA_EXPANSION_ERROR;
977 return MALA_NO_EXPANSION;
982 mala_engine_setenv_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
984 size_t eq;
986 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_SETENV_EXPANSION)
987 && mala_string_length ((*pptr)->string) > 1
988 && (eq = mala_string_char_find ((*pptr)->string, '='))
989 && eq > 0
990 && eq < SIZE_MAX
991 && !mala_string_check_prefix ((*pptr)->string, "-"))
993 MalaString key;
994 MalaString value;
995 MalaStringListNode n1;
996 MalaStringListNode n2;
997 MalaStringListNode n3;
999 key = mala_string_new_substr ((*pptr)->string, 0, eq);
1000 if (!key)
1001 goto ealloc_key;
1003 value = mala_string_new_substr ((*pptr)->string, eq + 1, SIZE_MAX);
1004 if (!value)
1005 goto ealloc_value;
1007 n1 = mala_stringlist_after_new (list,
1008 *pptr, self->common_string[MALA_STRING_SETENV]);
1009 if (!n1)
1010 goto ealloc_n1;
1012 n2 = mala_stringlist_after_new (list, n1, key);
1013 if (!n2)
1014 goto ealloc_n2;
1016 n3 = mala_stringlist_after_new (list, n2, value);
1017 if (!n3)
1018 goto ealloc_n3;
1020 mala_string_free (key);
1021 mala_string_free (value);
1022 mala_stringlist_elem_delete (list, *pptr);
1023 *pptr = n1;
1024 return 3;
1026 ealloc_n3:
1027 mala_stringlist_elem_delete (list, n2);
1028 ealloc_n2:
1029 mala_stringlist_elem_delete (list, n1);
1030 ealloc_n1:
1031 mala_string_free (value);
1032 ealloc_value:
1033 mala_string_free (key);
1034 ealloc_key:
1035 self->state = MALA_EALLOC;
1036 return MALA_EXPANSION_ERROR;
1038 return MALA_NO_EXPANSION;
1043 mala_engine_bracket_expansion (MalaEngine self, MalaStringList list, MalaStringListNode_ref pptr)
1045 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_BRACKET_EXPANSION)
1046 && mala_string_at ((*pptr)->string, 0) == '[')
1048 MalaStringListNode nitr;
1049 MalaStringListNode node;
1051 MalaString str1 = NULL;
1052 MalaStringListNode node1;
1054 MalaString str2 = NULL;
1055 MalaStringListNode node2;
1057 node = mala_stringlist_after_new (list, *pptr, self->common_string[MALA_STRING_SECTION]);
1058 if (!node)
1059 goto ealloc_node;
1061 if (mala_string_length((*pptr)->string) > 1)
1063 str1 = mala_string_new_substr ((*pptr)->string, 1, SIZE_MAX);
1064 node1 = mala_stringlist_after_new (list, node, str1);
1065 if (!node1)
1066 goto ealloc_node1;
1068 else
1070 node1 = node;
1071 mala_stringlistnode_fwd (&node1);
1074 for (nitr = node1; (void*)nitr != (void*)list; mala_stringlistnode_fwd (&nitr))
1076 if (mala_string_at (nitr->string, mala_string_length(nitr->string) - 1) == ']')
1077 break;
1080 if ((void*)nitr != (void*)list)
1082 if (mala_string_length(nitr->string) > 1)
1084 str2 = mala_string_new_substr (nitr->string, 0,
1085 mala_string_length(nitr->string) - 1);
1086 node2 = mala_stringlist_after_new (list, nitr, str2);
1087 if (!node2)
1088 goto ealloc_node2;
1091 else
1092 goto esyntax;
1095 mala_string_free (str1);
1096 mala_string_free (str2);
1097 mala_stringlist_elem_delete (list, *pptr);
1098 mala_stringlist_elem_delete (list, nitr);
1099 *pptr = node;
1101 return 0;
1103 esyntax:
1104 mala_string_free (str1);
1105 mala_stringlist_elem_delete (list, node1);
1106 mala_stringlist_elem_delete (list, node);
1107 self->state = MALA_ESYNTAX;
1108 return MALA_EXPANSION_ERROR;
1110 ealloc_node2:
1111 mala_string_free (str1);
1112 mala_stringlist_elem_delete (list, node1);
1113 ealloc_node1:
1114 mala_stringlist_elem_delete (list, node);
1115 ealloc_node:
1116 self->state = MALA_EALLOC;
1117 return MALA_EXPANSION_ERROR;
1119 return MALA_NO_EXPANSION;
1124 mala_engine_assign_contraction (MalaEngine self,
1125 MalaStringList list,
1126 MalaStringListNode_ref pptr)
1128 MalaStringListNode assign;
1129 MalaStringListNode value ;
1131 assign = *pptr;
1132 mala_stringlistnode_fwd (&assign);
1133 value = assign;
1135 if (mala_engine_check_expansionflag (self, MALA_STRING_FLAG_ASSIGN_CONTRACTION)
1136 && !mala_stringlist_is_tail (list, *pptr)
1137 && !mala_stringlist_is_tail (list, assign)
1138 && mala_string_same (assign->string, self->common_string[MALA_STRING_ASSIGN]))
1140 MalaString str;
1141 MalaStringListNode node;
1143 mala_stringlistnode_fwd (&value);
1145 str = mala_string_new_print (mala_string_bucket_get ((*pptr)->string),
1146 "%s=%s",
1147 mala_string_cstr ((*pptr)->string),
1148 mala_string_cstr (value->string));
1151 node = mala_stringlist_after_new (list,
1152 value,
1153 str);
1154 if (!node)
1155 goto ealloc_node;
1157 mala_string_free (str);
1158 mala_stringlist_elem_delete (list, *pptr);
1159 mala_stringlist_elem_delete (list, assign);
1160 mala_stringlist_elem_delete (list, value);
1161 *pptr = node;
1162 return 0;
1164 ealloc_node:
1165 mala_string_free (str);
1166 self->state = MALA_EALLOC;
1167 return MALA_EXPANSION_ERROR;
1169 return MALA_NO_EXPANSION;
1176 mala_engine_string_istrue (MalaEngine self, MalaString str)
1178 if (!str
1179 || !mala_string_compare (str, self->common_string[MALA_STRING_FALSE])
1180 || !mala_string_compare (str, self->common_string[MALA_STRING_ZERO]))
1181 return 0;
1183 return 1;
1187 mala_engine_check_expansionflag (MalaEngine self, int flag)
1189 MalaActionDesc desc;
1190 desc = (MalaActionDesc) mala_string_user_get (self->common_string[flag]);
1192 /*only enabled when the topmost action is a subtitution to --TRUE*/
1193 return mala_actiondesc_data_top (desc) == self->common_string[MALA_STRING_TRUE];
1208 #if 0 /*TODO*/
1210 mala_engine_erase_action (MalaEngine self, const t_uchar * key)
1212 MalaAction act;
1214 if (self->state > MALA_EFAULT)
1215 return self->state;
1217 act = mala_actiondict_lookupaction (self->actions, key);
1218 if (!act)
1219 goto enoact;
1221 mala_actiondict_destroy_action (self->actions, act);
1223 return MALA_SUCCESS;
1225 enoact:
1226 self->state = MALA_ENOACTION;
1227 return self->state;
1233 mala_engine_deepeval (MalaEngine self, MalaStringListNode_ref pptr)
1235 MalaStringListNode base = llist_get_prev (pptr);
1236 while (mala_engine_eval (self, llist_get_nextt (base)) < MALA_EVAL)
1237 if (llist_get_next (base) == &self->program)
1238 return MALA_ENOACTION;
1240 return self->state;
1245 void
1246 mala_engine_pusfront_program (MalaEngine self, int argc, char ** argv)
1248 self->state = mala_strlist_pushfront_cstrings (&self->program, argc, argv);
1254 mala_engine_argc (MalaEngine self)
1256 return llist_count (&self->arguments) + 1;
1259 const char*
1260 mala_engine_argv (MalaEngine self, int n)
1262 MalaStringListNode p;
1263 p = llist_get_next (&self->arguments);
1265 if (n==0)
1266 return self->argv_0;
1268 while (--n)
1270 if (p == &self->arguments)
1271 return 0;
1272 p = llist_get_next (p);
1274 return (const char *)(p)->data;
1279 MalaAction
1280 mala_engine_action_new (MalaEngine self, t_uchar** name, void** data,
1281 MalaParserFunc parser, MalaDataDestructor destructor)
1283 MalaAction act;
1285 act = mala_action_new (name, data, parser, destructor);
1286 if (!act)
1287 goto ealloc;
1289 self->state = mala_actiondict_push (self->actions, act);
1290 if (self->state)
1291 goto epush;
1293 return act;
1295 epush:
1296 mala_action_destroy (act);
1297 ealloc:
1298 return 0;
1302 mala_engine_check_expansionflag (MalaEngine self, const t_uchar * name)
1304 MalaAction act;
1306 act = mala_actiondict_lookupaction (self->actions, name);
1307 if (!act)
1308 return MALA_NO_EXPANSION;
1310 if (act->parser != mala_substitute_parser)
1311 return MALA_EPARSER;
1313 return mala_string_check ((t_uchar*) act->data);
1317 MalaAction
1318 mala_engine_getaction (MalaEngine self, const t_uchar * name)
1320 return mala_actiondict_lookupaction (self->actions, name);
1323 MalaAction
1324 mala_engine_getprevaction (MalaEngine self, const t_uchar * name)
1326 return mala_actiondict_lookupprevaction (self->actions, name);
1329 #endif /*TODO*/
1336 // Local Variables:
1337 // mode: C
1338 // c-file-style: "gnu"
1339 // End:
1340 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100
1341 // end_of_file