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.
23 #include "mala_types.h"
25 #include "actiondesc.h"
27 #include "stringlist.h"
31 #define MALA_EXPAND(e,S) S
32 static const char * mala_common_strings
[] = MALA_COMMON_STRINGS
;
35 #define MALA_STATE(s) #s
36 const char * mala_engine_states
[] = {MALA_STATES
};
41 * function definitions
50 self
= malloc (sizeof(mala_engine
));
55 self
->engine_trace
= MALA_NOTRACE
;
58 self
->state
= MALA_CONTINUE
;
60 mala_stringbucket_init (&self
->words
, MALA_STRING_FWD
, (void(*)(void*)) mala_actiondesc_free
);
62 self
->gc_trace
= &self
->words
.gc_trace
;
64 mala_engine_add_action_cstr (self
, "--WORLD", NULL
, NULL
, NULL
, NULL
);
66 for (i
= 0; i
< MALA_STRING_MAX
; ++i
)
68 self
->common_string
[i
] = mala_string_new (mala_common_strings
[i
], &self
->words
);
69 if (!self
->common_string
[i
])
73 mala_stringlist_init (&self
->program
);
74 mala_stringlist_init (&self
->arguments
);
80 mala_string_free (self
->common_string
[i
]);
87 mala_engine_new_main (int (*initfunc
) (MalaEngine
),
88 int argc
, char **argv
,
89 mala_actioninit
* actions_init
)
91 /*TODO convinience function*/
96 mala_engine_ppexpand_define (MalaEngine self
, const char * name
, int argc
, char ** argv
)
100 MalaStringListNode itr
;
103 if (mala_engine_state_get (self
) > MALA_EFAULT
)
104 return mala_engine_state_get (self
);
106 mala_stringlist_init (&pre
);
108 for (i
= 0; i
!= argc
&& *argv
; ++i
,++argv
)
110 if (!mala_stringlist_tail_new_cstr (&pre
, *argv
, &self
->words
))
114 list
= mala_stringlist_new ();
118 /*TODO preprocess in own function*/
119 while (!mala_stringlist_is_empty (&pre
))
123 itr
= mala_stringlist_head (&pre
);
125 putaway
= mala_engine_ppexpand (self
, &pre
, &itr
);
127 if (self
->state
> MALA_EFAULT
)
132 mala_stringlist_node_remove (&pre
, itr
);
133 mala_stringlist_tail_insert (list
, itr
);
134 if (putaway
&& mala_stringlist_is_empty (&pre
))
136 itr
= mala_stringlist_head (&pre
);
140 if (mala_stringlist_is_empty (list
))
142 mala_stringlist_free (list
);
143 return mala_engine_add_action_cstr (self
, name
,
144 mala_string_copy (self
->common_string
[MALA_STRING_PASS
]),
145 mala_substitute_parser
,
146 (MalaDataFactory
)mala_string_factory
,
147 mala_action_get_cstr (&self
->words
, "--WORLD"));
150 if (mala_stringlist_is_tail (list
, mala_stringlist_head (list
)))
155 subst
= mala_string_copy (mala_stringlist_head (list
) -> string
);
156 mala_stringlist_free (list
);
158 return mala_engine_add_action_cstr (self
, name
, subst
,
159 mala_substitute_parser
,
160 (MalaDataFactory
)mala_string_factory
,
161 mala_action_get_cstr (&self
->words
, "--WORLD"));
166 return mala_engine_add_action_cstr (self
, name
, list
,
168 (MalaDataFactory
) mala_stringlist_factory
,
169 mala_action_get_cstr (&self
->words
, "--WORLD"));
173 mala_stringlist_free (list
);
174 mala_stringlist_erase (&pre
);
175 return self
->state
= MALA_ESYNTAX
;
179 mala_stringlist_erase (&pre
);
180 return self
->state
= MALA_EALLOC
;
184 mala_engine_pushback_word (MalaEngine self
, const char * word
)
186 if (mala_engine_state_get (self
) > MALA_EFAULT
)
187 return mala_engine_state_get (self
);
189 if (!mala_stringlist_tail_new_cstr (&self
->program
, word
, &self
->words
))
190 return self
->state
= MALA_EALLOC
;
196 mala_engine_add_action_cstr (MalaEngine self
, const char * cname
, void * data
,
197 MalaParserFunc parser
, MalaDataFactory factory
,
203 if (mala_engine_state_get (self
) > MALA_EFAULT
)
204 return mala_engine_state_get (self
);
206 name
= mala_string_new (cname
, &self
->words
);
210 action
= mala_action_new (name
, data
, parser
, factory
, parent
);
214 if (mala_action_attach (action
) != MALA_SUCCESS
)
217 mala_string_free (name
);
221 mala_action_free (action
);
223 mala_string_free (name
);
225 return self
->state
= MALA_EALLOC
;
229 mala_engine_add_action (MalaEngine self
, MalaString name
, void * data
,
230 MalaParserFunc parser
, MalaDataFactory factory
,
235 if (mala_engine_state_get (self
) > MALA_EFAULT
)
236 return mala_engine_state_get (self
);
238 action
= mala_action_new (name
, data
, parser
, factory
,
239 parent
?parent
:mala_action_get_cstr (&self
->words
, "--WORLD"));
243 if (mala_action_attach (action
) != MALA_SUCCESS
)
249 mala_action_free (action
);
251 return self
->state
= MALA_EALLOC
;
256 mala_engine_new_initfunc (int (*initfunc
)(MalaEngine
))
260 self
= mala_engine_new ();
264 self
->state
= initfunc (self
);
269 mala_engine_free (MalaEngine self
)
274 if (self
->words
.gc_trace
> MALA_NOTRACE
)
275 fprintf (stderr
,"GC: engine free, program\n");
277 mala_stringlist_erase (&self
->program
);
279 if (self
->words
.gc_trace
> MALA_NOTRACE
)
280 fprintf (stderr
,"GC: engine free, arguments\n");
282 mala_stringlist_erase (&self
->arguments
);
284 if (self
->words
.gc_trace
> MALA_NOTRACE
)
285 fprintf (stderr
,"GC: engine free world\n");
287 /*TODO direct pointer top of the worlds*/
288 mala_action_free (mala_action_get_cstr (&self
->words
, "--WORLD"));
290 if (self
->words
.gc_trace
> MALA_NOTRACE
)
291 fprintf (stderr
,"GC: engine free, bucket\n");
293 mala_stringbucket_erase (&self
->words
);
299 mala_engine_actions_register (MalaEngine self
, mala_actioninit
* actioninit
)
303 if (mala_engine_state_get (self
) > MALA_EFAULT
)
304 return mala_engine_state_get (self
);
306 while (actioninit
->command
)
308 action
= mala_action_new_actioninit (actioninit
, self
);
312 if (mala_action_attach (action
) != MALA_SUCCESS
)
321 return self
->state
= MALA_EINIT
;
325 /*TODO make some inlines { */
328 mala_engine_getprogram (MalaEngine self
)
330 if (mala_engine_state_get (self
) > MALA_EFAULT
)
333 return &self
->program
;
337 mala_engine_state_get (MalaEngine self
)
339 return self
? self
->state
: MALA_EINVALID
;
343 mala_engine_state_str (MalaEngine self
)
345 return mala_engine_states
[self
? self
->state
: MALA_EINVALID
];
349 mala_engine_clearstate (MalaEngine self
)
352 self
->state
= MALA_SUCCESS
;
356 mala_engine_negated (MalaEngine self
)
358 return self
? self
->negated
: -1;
362 mala_engine_clear_negated (MalaEngine self
)
364 if (mala_engine_state_get (self
) > MALA_EFAULT
)
368 /* } TODO make some inlines */
372 mala_engine_dumpprogram (MalaEngine self
, FILE* stream
, const char * prefix
, const char * suffix
)
374 MalaStringListNode node
;
379 for (node
= mala_stringlist_head (&self
->program
);
380 node
!= (void *)&self
->program
;
381 mala_stringlistnode_fwd (&node
))
383 fprintf (stream
, "%s%s%s", prefix
, mala_string_cstr (node
->string
), suffix
);
388 mala_engine_dumpargs (MalaEngine self
, FILE* stream
, const char * prefix
, const char * suffix
)
390 MalaStringListNode node
;
395 for (node
= mala_stringlist_head (&self
->arguments
);
396 node
!= (void *)&self
->arguments
;
397 mala_stringlistnode_fwd (&node
))
399 fprintf (stream
, "%s%s%s", prefix
, mala_string_cstr (node
->string
), suffix
);
405 mala_engine_run (MalaEngine self
)
407 MalaStringListNode pptr
;
409 if (mala_engine_state_get (self
) > MALA_EFAULT
)
412 if (self
->words
.gc_trace
> MALA_NOTRACE
)
413 fprintf (stderr
,"GC: engine run\n");
415 while (self
->state
< MALA_EFAULT
&&
416 (pptr
= mala_stringlist_head (&self
->program
)) != (void *)&self
->program
)
418 if (self
->state
== MALA_LITERAL
)
420 self
->state
= mala_engine_string_istrue (self
,
421 mala_stringlistnode_string (pptr
))
424 mala_stringlist_elem_remove (&self
->program
, pptr
);
425 mala_stringlist_tail_insert (&self
->arguments
, pptr
);
428 mala_engine_eval (self
, &pptr
);
434 mala_engine_step (MalaEngine self
)
436 MalaStringListNode pptr
;
438 pptr
= mala_stringlist_head (&self
->program
);
440 mala_engine_eval (self
, &pptr
);
442 while (pptr
->string
== self
->common_string
[MALA_STRING_PASS
])
443 mala_engine_eval (self
, &pptr
);
449 mala_engine_eval (MalaEngine self
, MalaStringListNode_ref pptr
)
453 int state
= MALA_SUCCESS
;
455 if (self
->engine_trace
&& (*pptr
)->string
!= self
->common_string
[MALA_STRING_PASS
])
457 fprintf (stderr
, "%-8s: ", mala_engine_state_str (self
));
458 mala_engine_dumpprogram (self
, stderr
, "", " ");
459 fprintf (stderr
, "\n");
462 desc
= (MalaActionDesc
) mala_string_user_get ((*pptr
)->string
);
466 act
= mala_actiondesc_top (desc
);
470 state
= mala_action_execute (act
, pptr
, self
);
471 if (self
->state
!= MALA_REMOVE
)
477 if (self
->state
!= MALA_REMOVE
)
480 if (!(*pptr
= mala_stringlist_before_new (&self
->program
,
482 self
->common_string
[MALA_STRING_DEFAULT_PARSER
])))
483 return self
->state
= state
= MALA_EALLOC
;
485 self
->state
= MALA_LITERAL
;
488 mala_stringlistnode_substitute_string (*pptr
, self
->common_string
[MALA_STRING_DEFAULT_PARSER
]);
491 if (self
->state
== MALA_EXCEPTION
)
492 self
->state
= state
= MALA_ENOACTION
;
498 Evaluate the nth argument until the resulting state is less or equal
499 final_state or greater or equal to MALA_EXCEPTION
502 mala_engine_arg_eval (MalaEngine self
,
503 MalaStringListNode_ref pptr
,
507 MalaStringListNode next
;
509 if (mala_engine_state_get (self
) > MALA_EFAULT
)
513 nth
&& !mala_stringlist_is_tail (&self
->program
, next
);
514 mala_stringlistnode_fwd (&next
), --nth
);
519 if (self
->state
== MALA_REMOVE
)
521 mala_engine_eval (self
, &next
);
525 self
->state
= MALA_CONTINUE
;
527 while (self
->state
> final_state
&& self
->state
< MALA_EXCEPTION
)
529 mala_engine_eval (self
, &next
);
530 if (mala_stringlist_is_end (&self
->program
, next
))
538 mala_engine_exception (self
, pptr
, mala_stringlist_tail (&self
->program
),
539 self
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
545 Evaluate the nth argument until one of the following happens
546 - for at most 'times' (-1 for full evaluation)
547 - until we reach a final state MALA_SUCCESS, MALA_FAILURE or MALA_LITERAL
548 - an error/exception is flagged
549 - the type associated with the data of the current word equals to 'type'
552 mala_engine_arg_eval (MalaEngine self
,
553 MalaStringListNode_ref pptr
,
556 MalaDataFactory type
,
557 MalaParserFunc parser
)
560 MalaStringListNode next
;
562 if (mala_engine_state_get (self
) > MALA_EFAULT
)
566 nth
&& !mala_stringlist_is_tail (&self
->program
, next
);
567 mala_stringlistnode_fwd (&next
), --nth
);
572 if (self
->state
== MALA_REMOVE
)
574 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (next
->string
));
575 mala_engine_eval (self
, &next
);
579 self
->state
= MALA_CONTINUE
;
581 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (next
->string
));
582 while (self
->state
== MALA_CONTINUE
584 && ((act
&& type
) ? (act
->factory
!= type
) : 1)
585 && ((act
&& parser
) ? (act
->parser
!= parser
) : 1))
587 mala_engine_eval (self
, &next
);
588 if (mala_stringlist_is_end (&self
->program
, next
))
590 act
= mala_actiondesc_top ((MalaActionDesc
) mala_string_user_get (next
->string
));
597 mala_engine_exception (self
, pptr
, mala_stringlist_tail (&self
->program
),
598 self
->common_string
[MALA_STRING_ERROR_MISSING_ARGUMENT
]);
604 mala_engine_arg_eval_fmt (MalaEngine self
,
605 MalaStringListNode_ref pptr
,
612 MalaStringListNode node
;
615 node
= mala_engine_arg_eval (self
, pptr
, nth
, MALA_LITERAL
);
617 if (self
->state
!= MALA_EXCEPTION
)
619 r
= mala_string_scan (mala_stringlistnode_string (node
), fmt
, dest
);
621 r
= pred (dest
, constraint
);
623 return mala_engine_exception (self
, pptr
, node
,
624 self
->common_string
[MALA_STRING_ERROR_WRONG_TYPE
]);
631 mala_engine_arg_eval_string (MalaEngine self
,
632 MalaStringListNode_ref pptr
,
639 string
= mala_stringlistnode_string (mala_engine_arg_eval (self
, pptr
, nth
, MALA_LITERAL
));
641 if (self
->state
>= MALA_EXCEPTION
|| ! (pred
? pred (string
, constraint
) : 1))
649 mala_engine_command_done (MalaEngine eng
, MalaStringListNode_ref pptr
, int args
)
651 mala_stringlistnode_substitute_string (*pptr
, eng
->common_string
[MALA_STRING_PASS
]);
654 mala_stringlist_elem_delete (&eng
->program
, mala_stringlistnode_next (*pptr
));
660 mala_engine_exception (MalaEngine self
,
661 MalaStringListNode_ref pptr
,
662 MalaStringListNode here
,
665 MalaStringListNode tmp
;
667 if (mala_engine_state_get (self
) > MALA_EFAULT
)
668 return mala_engine_state_get (self
);
670 tmp
= mala_stringlist_before_new (&self
->program
, *pptr
, except
);
672 return self
->state
= MALA_EALLOC
;
674 if (!mala_stringlist_after_new (&self
->program
, here
,
675 self
->common_string
[MALA_STRING_HERE
]))
676 return self
->state
= MALA_EALLOC
;
680 /*TODO self-state needs to be preserved somehow?*/
681 return self
->state
= MALA_EXCEPTION
;
686 mala_engine_ppexpand (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
690 if (self
->state
> MALA_EFAULT
)
691 return MALA_EXPANSION_ERROR
;
693 #define mala_run_expansion(name) \
694 if (MALA_NO_EXPANSION != (ret = mala_engine_##name (self, list, pptr))) return ret
696 mala_run_expansion (literal_expansion
);
697 mala_run_expansion (numsplit_expansion
);
698 mala_run_expansion (exclam_expansion
);
699 mala_run_expansion (no_expansion
);
700 mala_run_expansion (assign_expansion
);
701 mala_run_expansion (char_expansion
);
702 mala_run_expansion (underscore_expansion
);
703 mala_run_expansion (bracket_expansion
);
704 mala_run_expansion (assign_contraction
);
705 mala_run_expansion (envvar_expansion
);
706 mala_run_expansion (setenv_expansion
);
707 mala_run_expansion (backquote_expansion
);
708 #undef mala_run_expansion
714 mala_engine_literal_expansion (MalaEngine self
,
716 MalaStringListNode_ref pptr
)
718 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_LITERAL_EXPANSION
)
719 && mala_string_check_prefix ((*pptr
)->string
, "`")
720 && !mala_string_check_prefix ((*pptr
)->string
, "``"))
723 MalaStringListNode newnode1
;
724 MalaStringListNode newnode2
;
726 newnode1
= mala_stringlist_after_new (list
,
728 self
->common_string
[MALA_STRING_LITERAL
]);
730 goto ealloc_newnode1
;
732 nstr
= mala_string_new_substr ((*pptr
)->string
, 1, SIZE_MAX
);
733 newnode2
= mala_stringlist_after_new (list
, newnode1
, nstr
);
735 goto ealloc_newnode2
;
737 mala_stringlist_elem_delete (list
, *pptr
);
743 mala_stringlist_elem_delete (list
, newnode1
);
745 self
->state
= MALA_EALLOC
;
746 return MALA_EXPANSION_ERROR
;
748 return MALA_NO_EXPANSION
;
753 mala_engine_backquote_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
755 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_LITERAL_EXPANSION
)
756 && mala_string_check_prefix ((*pptr
)->string
, "``"))
759 MalaStringListNode newnode
;
761 nstr
= mala_string_new_substr ((*pptr
)->string
, 1, SIZE_MAX
);
762 newnode
= mala_stringlist_after_new (list
, *pptr
, nstr
);
766 mala_stringlist_elem_delete (list
, *pptr
);
772 self
->state
= MALA_EALLOC
;
773 return MALA_EXPANSION_ERROR
;
775 return MALA_NO_EXPANSION
;
779 mala_engine_numsplit_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
781 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_NUMSPLIT_EXPANSION
)
782 && mala_string_length ((*pptr
)->string
) > 2
783 && mala_string_at ((*pptr
)->string
, 0) == '-'
784 && isalpha (mala_string_at ((*pptr
)->string
, 1))
789 for (i
= 2; i
< mala_string_length ((*pptr
)->string
); ++i
)
791 if (isdigit (mala_string_at ((*pptr
)->string
, i
)))
796 MalaStringListNode na
;
797 MalaStringListNode nb
;
799 a
= mala_string_new_substr ((*pptr
)->string
, 0, i
);
800 b
= mala_string_new_substr ((*pptr
)->string
, i
, SIZE_MAX
);
804 na
= mala_stringlist_after_new (list
, *pptr
, a
);
808 nb
= mala_stringlist_after_new (list
, na
, b
);
812 mala_stringlist_elem_delete (list
, *pptr
);
815 mala_string_free (a
);
816 mala_string_free (b
);
821 mala_stringlist_elem_delete (list
, na
);
824 mala_string_free (a
);
825 mala_string_free (b
);
826 self
->state
= MALA_EALLOC
;
827 return MALA_EXPANSION_ERROR
;
831 return MALA_NO_EXPANSION
;
836 mala_engine_exclam_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
838 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_EXCLAM_EXPANSION
)
839 && mala_string_length ((*pptr
)->string
) == 1
840 && mala_string_same ((*pptr
)->string
, self
->common_string
[MALA_STRING_EXCLAMATIONMARK
]))
842 MalaStringListNode newnode
;
844 newnode
= mala_stringlist_after_new (list
,
846 self
->common_string
[MALA_STRING_NOT
]);
848 return self
->state
= MALA_EALLOC
;
850 mala_stringlist_elem_delete (list
, *pptr
);
854 return MALA_NO_EXPANSION
;
859 mala_engine_no_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
861 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_NO_EXPANSION
)
862 && mala_string_check_prefix_nocase ((*pptr
)->string
, "--NO-")
863 && mala_string_length ((*pptr
)->string
) >= sizeof ("--NO-"))
867 MalaStringListNode n1
;
868 MalaStringListNode n2
;
870 a
= mala_string_new_substr ((*pptr
)->string
, sizeof ("--NO-")-1, SIZE_MAX
);
871 aa
= mala_string_new_prefix ("--", a
);
875 n1
= mala_stringlist_after_new (list
,
876 *pptr
, self
->common_string
[MALA_STRING_NOT
]);
880 n2
= mala_stringlist_after_new (list
, n1
, aa
);
884 mala_string_free (a
);
885 mala_string_free (aa
);
886 mala_stringlist_elem_delete (list
, *pptr
);
891 mala_stringlist_elem_delete (list
, n1
);
893 mala_string_free (a
);
894 mala_string_free (aa
);
896 self
->state
= MALA_EALLOC
;
897 return MALA_EXPANSION_ERROR
;
899 return MALA_NO_EXPANSION
;
904 mala_engine_assign_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
908 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_ASSIGN_EXPANSION
)
909 && mala_string_check_prefix ((*pptr
)->string
, "--")
910 && ((eq
= mala_string_char_find ((*pptr
)->string
, '=')) != SIZE_MAX
)
911 && mala_string_length ((*pptr
)->string
) > eq
+ 1)
916 MalaStringListNode na
;
917 MalaStringListNode nb
;
919 a
= mala_string_new_substr ((*pptr
)->string
, 0, eq
);
920 b
= mala_string_new_substr ((*pptr
)->string
, eq
+ 1, SIZE_MAX
);
924 na
= mala_stringlist_after_new (list
, *pptr
, a
);
928 nb
= mala_stringlist_after_new (list
, na
, b
);
932 mala_stringlist_elem_delete (list
, *pptr
);
935 mala_string_free (a
);
936 mala_string_free (b
);
942 mala_stringlist_elem_delete (list
, na
);
945 mala_string_free (a
);
946 mala_string_free (b
);
947 self
->state
= MALA_EALLOC
;
948 return MALA_EXPANSION_ERROR
;
950 return MALA_NO_EXPANSION
;
955 mala_engine_envvar_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
957 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_ENVVAR_EXPANSION
)
958 && (mala_string_char_find ((*pptr
)->string
, '$') != SIZE_MAX
))
960 MalaStringListNode newnode
;
962 newnode
= mala_stringlist_before_new (list
,
964 self
->common_string
[MALA_STRING_ENVSUBST
]);
972 self
->state
= MALA_EALLOC
;
973 return MALA_EXPANSION_ERROR
;
976 return MALA_NO_EXPANSION
;
981 mala_engine_char_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
983 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_CHAR_EXPANSION
)
984 && mala_string_length ((*pptr
)->string
) > 2
985 && ( mala_string_at ((*pptr
)->string
, 0) == '-'
986 || mala_string_at ((*pptr
)->string
, 0) == '+')
987 && isalpha (mala_string_at ((*pptr
)->string
, 1)))
989 char prefix
[2] = "-";
990 char current
[2] = " ";
995 MalaStringListNode node
= NULL
;
996 MalaStringListNode pred
= *pptr
;
999 for (i
= mala_string_cstr ((*pptr
)->string
); *i
; ++i
)
1001 if (*i
== '-' || *i
== '+')
1003 else if (isalpha (*i
))
1007 str
= mala_string_new_cat2 (prefix
, current
,
1008 mala_string_bucket_get ((*pptr
)->string
));
1012 node
= mala_stringlist_after_new (list
,
1018 mala_string_free (str
);
1025 mala_stringlistnode_fwd (&pred
);
1026 mala_stringlist_elem_delete (list
, *pptr
);
1031 mala_string_free (str
);
1032 /* cleanup from pred downto pptr */
1033 while (pred
!= *pptr
)
1035 MalaStringListNode tmp
= mala_stringlistnode_prev (pred
);
1036 mala_stringlist_elem_delete (list
, pred
);
1039 self
->state
= MALA_EALLOC
;
1040 return MALA_EXPANSION_ERROR
;
1042 return MALA_NO_EXPANSION
;
1047 mala_engine_underscore_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
1049 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_UNDERSCORE_EXPANSION
)
1050 && mala_string_check_prefix ((*pptr
)->string
, "--")
1051 && strchr (mala_string_cstr ((*pptr
)->string
), '_'))
1054 MalaStringListNode node
;
1058 cstr
= strdup (mala_string_cstr ((*pptr
)->string
));
1062 for (i
= cstr
+ 2; *i
; ++i
)
1068 str
= mala_string_new (cstr
, &self
->words
);
1072 node
= mala_stringlist_after_new (list
,
1079 mala_string_free (str
);
1081 mala_stringlist_elem_delete (list
, *pptr
);
1086 mala_string_free (str
);
1090 self
->state
= MALA_EALLOC
;
1091 return MALA_EXPANSION_ERROR
;
1093 return MALA_NO_EXPANSION
;
1098 mala_engine_setenv_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
1102 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_SETENV_EXPANSION
)
1103 && mala_string_length ((*pptr
)->string
) > 1
1104 && (eq
= mala_string_char_find ((*pptr
)->string
, '='))
1107 && !mala_string_check_prefix ((*pptr
)->string
, "-"))
1111 MalaStringListNode n1
;
1112 MalaStringListNode n2
;
1113 MalaStringListNode n3
;
1115 key
= mala_string_new_substr ((*pptr
)->string
, 0, eq
);
1119 value
= mala_string_new_substr ((*pptr
)->string
, eq
+ 1, SIZE_MAX
);
1123 n1
= mala_stringlist_after_new (list
,
1124 *pptr
, self
->common_string
[MALA_STRING_SETENV
]);
1128 n2
= mala_stringlist_after_new (list
, n1
, key
);
1132 n3
= mala_stringlist_after_new (list
, n2
, value
);
1136 mala_string_free (key
);
1137 mala_string_free (value
);
1138 mala_stringlist_elem_delete (list
, *pptr
);
1143 mala_stringlist_elem_delete (list
, n2
);
1145 mala_stringlist_elem_delete (list
, n1
);
1147 mala_string_free (value
);
1149 mala_string_free (key
);
1151 self
->state
= MALA_EALLOC
;
1152 return MALA_EXPANSION_ERROR
;
1154 return MALA_NO_EXPANSION
;
1159 mala_engine_bracket_expansion (MalaEngine self
, MalaStringList list
, MalaStringListNode_ref pptr
)
1161 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_BRACKET_EXPANSION
)
1162 && mala_string_at ((*pptr
)->string
, 0) == '[')
1164 MalaStringListNode nitr
;
1165 MalaStringListNode node
;
1167 MalaString str1
= NULL
;
1168 MalaStringListNode node1
;
1170 MalaString str2
= NULL
;
1171 MalaStringListNode node2
;
1173 node
= mala_stringlist_after_new (list
, *pptr
, self
->common_string
[MALA_STRING_SECTION
]);
1177 if (mala_string_length((*pptr
)->string
) > 1)
1179 str1
= mala_string_new_substr ((*pptr
)->string
, 1, SIZE_MAX
);
1180 node1
= mala_stringlist_after_new (list
, node
, str1
);
1187 mala_stringlistnode_fwd (&node1
);
1190 for (nitr
= node1
; (void*)nitr
!= (void*)list
; mala_stringlistnode_fwd (&nitr
))
1192 if (mala_string_at (nitr
->string
, mala_string_length(nitr
->string
) - 1) == ']')
1196 if ((void*)nitr
!= (void*)list
)
1198 if (mala_string_length(nitr
->string
) > 1)
1200 str2
= mala_string_new_substr (nitr
->string
, 0,
1201 mala_string_length(nitr
->string
) - 1);
1202 node2
= mala_stringlist_after_new (list
, nitr
, str2
);
1211 mala_string_free (str1
);
1212 mala_string_free (str2
);
1213 mala_stringlist_elem_delete (list
, *pptr
);
1214 mala_stringlist_elem_delete (list
, nitr
);
1220 mala_string_free (str1
);
1221 mala_stringlist_elem_delete (list
, node1
);
1222 mala_stringlist_elem_delete (list
, node
);
1223 self
->state
= MALA_ESYNTAX
;
1224 return MALA_EXPANSION_ERROR
;
1227 mala_string_free (str1
);
1228 mala_stringlist_elem_delete (list
, node1
);
1230 mala_stringlist_elem_delete (list
, node
);
1232 self
->state
= MALA_EALLOC
;
1233 return MALA_EXPANSION_ERROR
;
1235 return MALA_NO_EXPANSION
;
1240 mala_engine_assign_contraction (MalaEngine self
,
1241 MalaStringList list
,
1242 MalaStringListNode_ref pptr
)
1244 MalaStringListNode assign
;
1245 MalaStringListNode value
;
1248 mala_stringlistnode_fwd (&assign
);
1251 if (mala_engine_check_expansionflag (self
, MALA_STRING_FLAG_ASSIGN_CONTRACTION
)
1252 && !mala_stringlist_is_tail (list
, *pptr
)
1253 && !mala_stringlist_is_tail (list
, assign
)
1254 && mala_string_same (assign
->string
, self
->common_string
[MALA_STRING_ASSIGN
]))
1257 MalaStringListNode node
;
1259 mala_stringlistnode_fwd (&value
);
1261 str
= mala_string_new_print (mala_string_bucket_get ((*pptr
)->string
),
1263 mala_string_cstr ((*pptr
)->string
),
1264 mala_string_cstr (value
->string
));
1267 node
= mala_stringlist_after_new (list
,
1273 mala_string_free (str
);
1274 mala_stringlist_elem_delete (list
, *pptr
);
1275 mala_stringlist_elem_delete (list
, assign
);
1276 mala_stringlist_elem_delete (list
, value
);
1281 mala_string_free (str
);
1282 self
->state
= MALA_EALLOC
;
1283 return MALA_EXPANSION_ERROR
;
1285 return MALA_NO_EXPANSION
;
1292 mala_engine_string_istrue (MalaEngine self
, MalaString str
)
1294 /*TODO check for other zero representations 0.0 0e0 etc.*/
1296 || !mala_string_compare (str
, self
->common_string
[MALA_STRING_EMPTY
])
1297 || !mala_string_compare (str
, self
->common_string
[MALA_STRING_FALSE
])
1298 || !mala_string_compare (str
, self
->common_string
[MALA_STRING_ZERO
]))
1305 mala_engine_check_expansionflag (MalaEngine self
, int flag
)
1307 MalaActionDesc desc
;
1308 desc
= (MalaActionDesc
) mala_string_user_get (self
->common_string
[flag
]);
1310 /*only enabled when the topmost action is a subtitution to --TRUE*/
1311 return mala_actiondesc_data_top (desc
) == self
->common_string
[MALA_STRING_TRUE
];
1328 mala_engine_erase_action (MalaEngine self
, const t_uchar
* key
)
1332 if (self
->state
> MALA_EFAULT
)
1335 act
= mala_actiondict_lookupaction (self
->actions
, key
);
1339 mala_actiondict_destroy_action (self
->actions
, act
);
1341 return MALA_SUCCESS
;
1344 self
->state
= MALA_ENOACTION
;
1351 mala_engine_deepeval (MalaEngine self
, MalaStringListNode_ref pptr
)
1353 MalaStringListNode base
= llist_get_prev (pptr
);
1354 while (mala_engine_eval (self
, llist_get_nextt (base
)) < MALA_EVAL
)
1355 if (llist_get_next (base
) == &self
->program
)
1356 return MALA_ENOACTION
;
1364 mala_engine_pusfront_program (MalaEngine self
, int argc
, char ** argv
)
1366 self
->state
= mala_strlist_pushfront_cstrings (&self
->program
, argc
, argv
);
1372 mala_engine_argc (MalaEngine self
)
1374 return llist_count (&self
->arguments
) + 1;
1378 mala_engine_argv (MalaEngine self
, int n
)
1380 MalaStringListNode p
;
1381 p
= llist_get_next (&self
->arguments
);
1384 return self
->argv_0
;
1388 if (p
== &self
->arguments
)
1390 p
= llist_get_next (p
);
1392 return (const char *)(p
)->data
;
1398 mala_engine_action_new (MalaEngine self
, t_uchar
** name
, void** data
,
1399 MalaParserFunc parser
, MalaDataDestructor destructor
)
1403 act
= mala_action_new (name
, data
, parser
, destructor
);
1407 self
->state
= mala_actiondict_push (self
->actions
, act
);
1414 mala_action_destroy (act
);
1420 mala_engine_check_expansionflag (MalaEngine self
, const t_uchar
* name
)
1424 act
= mala_actiondict_lookupaction (self
->actions
, name
);
1426 return MALA_NO_EXPANSION
;
1428 if (act
->parser
!= mala_substitute_parser
)
1429 return MALA_EPARSER
;
1431 return mala_string_check ((t_uchar
*) act
->data
);
1436 mala_engine_getaction (MalaEngine self
, const t_uchar
* name
)
1438 return mala_actiondict_lookupaction (self
->actions
, name
);
1442 mala_engine_getprevaction (MalaEngine self
, const t_uchar
* name
)
1444 return mala_actiondict_lookupprevaction (self
->actions
, name
);
1456 // c-file-style: "gnu"
1458 // arch-tag: ece5489f-f703-4033-8cbc-efc1b0562100