MARC interface implemented. Minor bugs fixed. fmltest can
[egate.git] / fml / fml.c
1 /*
2  * FML interpreter. Europagate, 1995
3  *
4  * $Log: fml.c,v $
5  * Revision 1.7  1995/02/10 15:50:54  adam
6  * MARC interface implemented. Minor bugs fixed. fmltest can
7  * be used to format single MARC records. New function '\list'
8  * implemented.
9  *
10  * Revision 1.6  1995/02/09  16:06:06  adam
11  * FML can be called from the outside multiple times by the functions:
12  * fml_exec_call and fml_exec_call_str.
13  * An interactive parameter (-i) to fmltest starts a shell-like
14  * interface to FML by using the fml_exec_call_str function.
15  *
16  * Revision 1.5  1995/02/09  14:33:36  adam
17  * Split source fml.c and define relevant build-in functions in separate
18  * files. New operators mult, div, not, llen implemented.
19  *
20  * Revision 1.4  1995/02/09  13:07:14  adam
21  * Nodes are freed now. Many bugs fixed.
22  *
23  * Revision 1.3  1995/02/07  16:09:23  adam
24  * The \ character is no longer INCLUDED when terminating a token.
25  * Major changes in tokenization routines. Bug fixes in expressions
26  * with lists (fml_sub0).
27  *
28  * Revision 1.2  1995/02/06  15:23:25  adam
29  * Added some more relational operators (le,ne,ge). Added increment
30  * and decrement operators. Function index changed, so that first
31  * element is 1 - not 0. Function fml_atom_val edited.
32  *
33  * Revision 1.1.1.1  1995/02/06  13:48:10  adam
34  * First version of the FML interpreter. It's slow and memory isn't
35  * freed properly. In particular, the FML nodes aren't released yet.
36  *
37  */
38 #include <assert.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41
42 #include "fmlp.h"
43
44 static int default_read_func (void)
45 {
46     return getchar ();
47 }
48
49 static void default_err_handle (int no)
50 {
51     fprintf (stderr, "Error: %d\n", no);
52 }
53
54 static struct fml_node *fml_sub0 (Fml fml, struct fml_node *list);
55 static struct fml_node *fml_sub1 (Fml fml, struct fml_node **lp,
56                                   struct token *tp);
57 static struct fml_node *fml_sub2 (Fml fml, struct fml_node **lp,
58                                   struct token *tp);
59 static struct fml_node *fml_exec_space (Fml fml, struct fml_node **lp, 
60                                         struct token *tp);
61 static struct fml_node *fml_exec_nl (Fml fml, struct fml_node **lp, 
62                                      struct token *tp);
63                                   
64 static int indent = 0;
65
66 static void pr_indent (int n)
67 {
68     assert (indent >= 0);
69     if (n >= 0)
70     {
71         int i = indent;
72         while (--i >= 0)
73             putchar(' ');
74     }
75     if (n > 0)
76     {
77         printf ("[");
78         ++indent;
79     } 
80     else if (n < 0)
81     {
82         printf ("]\n");
83         --indent;
84     }
85 }
86
87 Fml fml_open (void)
88 {
89     struct fml_sym_info *sym_info;
90
91     Fml fml = malloc (sizeof(*fml));
92
93     if (!fml)
94         return NULL;
95
96     fml->escape_char = '\\';
97     fml->comment_char = '#';
98     fml->eof_mark = EOF;
99     fml->white_chars = " \t\f\r\n";
100     fml->read_func = default_read_func;
101     fml->err_handle = default_err_handle;
102
103     fml->list = NULL;
104     fml->sym_tab = fml_sym_open ();
105     fml->atom_free_list = NULL;
106     fml->node_free_list = NULL;
107     fml->debug = 0;
108
109     sym_info = fml_sym_add (fml->sym_tab, "func");
110     sym_info->kind = FML_FUNC;
111     sym_info = fml_sym_add (fml->sym_tab, "bin");
112     sym_info->kind = FML_BIN;
113     sym_info = fml_sym_add (fml->sym_tab, "if");
114     sym_info->kind = FML_IF;
115     sym_info = fml_sym_add (fml->sym_tab, "else");
116     sym_info->kind = FML_ELSE;
117     sym_info = fml_sym_add (fml->sym_tab, "foreach");
118     sym_info->kind = FML_FOREACH;
119     sym_info = fml_sym_add (fml->sym_tab, "set");
120     sym_info->kind = FML_SET;
121     sym_info = fml_sym_add (fml->sym_tab, "while");
122     sym_info->kind = FML_WHILE;
123     sym_info = fml_sym_add (fml->sym_tab, "return");
124     sym_info->kind = FML_RETURN;
125
126     fml_list_init (fml);
127     fml_arit_init (fml);
128     fml_rel_init (fml);
129
130     sym_info = fml_sym_add (fml->sym_tab, "s");
131     sym_info->kind = FML_CPREFIX;
132     sym_info->prefix = fml_exec_space;
133     sym_info = fml_sym_add (fml->sym_tab, " ");
134     sym_info->kind = FML_CPREFIX;
135     sym_info->prefix = fml_exec_space;
136     sym_info = fml_sym_add (fml->sym_tab, "n");
137     sym_info->kind = FML_CPREFIX;
138     sym_info->prefix = fml_exec_nl;
139
140     return fml;
141 }
142
143 static Fml fml_pop_handler = NULL;
144 static void pop_handler (struct fml_sym_info *info)
145 {
146     assert (fml_pop_handler);
147     switch (info->kind)
148     {
149     case FML_VAR:
150         fml_node_delete (fml_pop_handler, info->body);
151         break;
152     }
153 }
154 static void fml_do_pop (Fml fml)
155 {
156     fml_pop_handler = fml;
157     fml_sym_pop (fml->sym_tab, pop_handler);
158 }
159
160 int fml_preprocess (Fml fml)
161 {
162     fml->list = fml_tokenize (fml);
163     return 0;
164 }
165
166
167 void fml_init_token (struct token *tp, Fml fml)
168 {
169     tp->maxbuf = FML_ATOM_BUF*2;
170     tp->offset = 0;
171     tp->atombuf = tp->sbuf;
172     tp->tokenbuf = tp->sbuf + tp->maxbuf;
173     tp->escape_char = fml->escape_char;
174 }
175
176 void fml_del_token (struct token *tp, Fml fml)
177 {
178     if (tp->maxbuf != FML_ATOM_BUF*2)
179         free (tp->atombuf);
180 }
181
182 void fml_cmd_lex (struct fml_node **np, struct token *tp)
183 {
184     char *cp;
185     char *dst;
186     if (!*np)
187     {
188         tp->kind = '\0';
189         return;
190     }
191     if (tp->offset == 0)
192     {
193         tp->separate = 1;
194         if ((*np)->is_atom)
195         {
196             tp->atom = (*np)->p[0];
197             if (!tp->atom->next)
198                 fml_atom_str (tp->atom, tp->atombuf);
199             else
200             {
201                 int l = fml_atom_str (tp->atom, NULL);
202                 if (l >= tp->maxbuf-1)
203                 {
204                     if (tp->maxbuf != FML_ATOM_BUF*2)
205                         free (tp->atombuf);
206                     tp->maxbuf = l + 40;
207                     tp->atombuf = malloc (tp->maxbuf*2);
208                     tp->tokenbuf = tp->atombuf + tp->maxbuf;
209                 }
210                 fml_atom_str (tp->atom, tp->atombuf);
211             }
212         }
213         else
214         {
215             tp->sub = (*np)->p[0];
216             tp->kind = 'g';
217             *np = (*np)->p[1];
218             return ;
219         }
220     }
221     else
222         tp->separate = 0;
223     cp = tp->atombuf + tp->offset;
224     dst = tp->tokenbuf;
225     if (*cp == tp->escape_char)
226     {
227         tp->kind = 'e';
228         cp++;
229         if (*cp == '\0')
230         {
231             strcpy (dst, " ");
232             tp->offset = 0;
233             *np = (*np)->p[1];
234             return ;
235         }
236     }
237     else
238     {
239         tp->kind = 't';
240     }
241     while (*cp)
242     {
243         if (*cp == tp->escape_char)
244         {
245             *dst = '\0';
246             tp->offset = cp - tp->atombuf;
247             return ;
248         }
249         *dst++ = *cp++;
250     }
251     *dst = '\0';
252     tp->offset = 0;
253     *np = (*np)->p[1];
254 }
255
256 struct fml_node *fml_expr_term (Fml fml, struct fml_node **lp, 
257                                 struct token *tp)
258 {
259     struct fml_node *fn;
260     if (tp->kind == 'g')
261     {
262         fn = fml_sub0 (fml, tp->sub);
263         fml_cmd_lex (lp, tp);
264     }
265     else
266         fn = fml_sub2 (fml, lp, tp);
267     return fn;
268 }
269
270 void fml_lr_values (Fml fml, struct fml_node *l, int *left_val,
271                            struct fml_node *r, int *right_val)
272 {
273     if (l && l->is_atom)
274         *left_val = fml_atom_val (l->p[0]);
275     else
276         *left_val = 0;
277     if (r && r->is_atom)
278         *right_val = fml_atom_val (r->p[0]);
279     else
280         *right_val = 0;
281     fml_node_delete (fml, l);
282     fml_node_delete (fml, r);
283 }
284
285 static struct fml_node *fml_exec_space (Fml fml, struct fml_node **lp, 
286                                         struct token *tp)
287 {
288     fml_cmd_lex (lp, tp);
289     if (fml->debug & 1)
290         putchar ('_');
291     else
292         putchar (' ');
293     return NULL;
294 }
295
296 static struct fml_node *fml_exec_nl (Fml fml, struct fml_node **lp, 
297                                      struct token *tp)
298 {
299     fml_cmd_lex (lp, tp);
300     putchar ('\n');
301     return NULL;
302 }
303
304 static struct fml_node *fml_exec_prefix (struct fml_sym_info *info, Fml fml,
305                                          struct fml_node **lp,
306                                          struct token *tp)
307 {
308     struct fml_node *fn;
309     struct fml_sym_info *arg_info;
310     struct fml_node *return_value;
311     static char arg[128];
312
313     if (fml->debug & 1)
314     {
315         pr_indent (1);
316         printf ("exec_prefix ");
317     }
318     fml_sym_push (fml->sym_tab);
319     fml_cmd_lex (lp, tp);
320     for (fn = info->args; fn; fn = fn->p[1])
321     {
322
323         assert (fn->is_atom);
324         fml_atom_strx (fn->p[0], arg, 127);
325         if (fml->debug & 1)
326         {
327             pr_indent (1);
328             printf ("%s=", arg);
329         }
330         arg_info = fml_sym_add_local (fml->sym_tab, arg);
331         arg_info->kind = FML_VAR;
332
333         if (tp->kind == 'g')
334         {
335             arg_info->body = fml_sub0 (fml, tp->sub);
336             fml_cmd_lex (lp, tp);
337         }
338         else
339             arg_info->body = fml_sub2 (fml, lp, tp);
340         if (fml->debug & 1)
341         {
342             fml_pr_list (arg_info->body);
343             pr_indent (-1);
344         }
345     }
346     return_value = fml_exec_group (info->body, fml);
347     if (fml->debug & 1)
348     {
349         pr_indent(0);
350         pr_indent (-1);
351     }
352     fml_do_pop (fml);
353     return return_value;
354 }
355
356
357 static void fml_emit (struct fml_node *list)
358 {
359     int s = 0;
360     while (list)
361     {
362         if (list->is_atom)
363         {
364             struct fml_atom *a;
365             if (s)
366                 printf (" ");
367             s++;
368             for (a = list->p[0]; a; a=a->next)
369                 printf ("%.*s", FML_ATOM_BUF, a->buf);
370         }
371         else
372             fml_emit (list->p[0]);
373         list = list->p[1];
374     }
375 }
376
377
378 static struct fml_node *fml_sub2 (Fml fml, struct fml_node **lp,
379                                   struct token *tp)
380 {
381     struct fml_node *fn;
382     struct fml_sym_info *info;
383     if (tp->kind == 'e')
384     {
385         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
386         assert (info);
387         switch (info->kind)
388         {
389         case FML_VAR:
390             fn = fml_node_copy (fml, info->body);           
391             fml_cmd_lex (lp, tp);
392             break;
393         case FML_PREFIX:
394             fn = fml_exec_prefix (info, fml, lp, tp);
395             break;
396         case FML_CPREFIX:
397             fn = (*info->prefix) (fml, lp, tp);
398             break;
399         default:
400             fml_cmd_lex (lp, tp);
401             fn = NULL;
402         }
403     }
404     else if (tp->kind == 'g')
405     {
406         if (tp->sub)
407             fn = fml_sub0 (fml, tp->sub);
408         else
409             fn = NULL;
410         fml_cmd_lex (lp, tp);
411     }
412     else if (tp->kind == 't')
413     {
414         fn = fml_node_alloc (fml);
415         fn->is_atom = 1;
416         fn->p[0] = fml_atom_alloc (fml, tp->tokenbuf);
417         fml_cmd_lex (lp, tp);
418     }
419     else
420         fn = NULL;
421     return fn;
422 }
423
424 static struct fml_node *fml_sub1 (Fml fml, struct fml_node **lp,
425                                   struct token *tp)
426 {
427     struct fml_node *f1, *f2, *fn;
428     struct fml_sym_info *info;
429
430     f1 = fml_sub2 (fml, lp, tp);
431     while (tp->kind == 'e')
432     {
433         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
434         if (!info)
435         {
436             fprintf (stderr, "cannot locate `%s'", tp->tokenbuf);
437             exit (1);
438         }
439         if (info->kind == FML_CBINARY)
440         {
441             fml_cmd_lex (lp, tp);
442             f2 = fml_sub2 (fml, lp, tp);
443             fn = (*info->binary) (fml, f1, f2);
444             f1 = fn;
445             continue;
446         }
447         else if (info->kind == FML_BINARY)
448         {
449             struct fml_sym_info *arg_info;
450             char arg[127];
451
452             if (fml->debug & 1)
453             {
454                 pr_indent (1);
455                 printf ("exec binary %s", tp->tokenbuf);
456             }
457             fml_cmd_lex (lp, tp);
458             f2 = fml_sub2 (fml, lp, tp);
459             fml_sym_push (fml->sym_tab);
460
461             fml_atom_strx (info->args->p[0], arg, 127);
462             arg_info = fml_sym_add_local (fml->sym_tab, arg);
463             arg_info->kind = FML_VAR;
464             arg_info->body = f1;
465             if (fml->debug & 1)
466             {
467                 printf (" left=");
468                 fml_pr_list (f1);
469             }
470             fml_atom_strx ( ((struct fml_node *) info->args->p[1])->p[0],
471                            arg, 127);
472             arg_info = fml_sym_add_local (fml->sym_tab, arg);
473             arg_info->kind = FML_VAR;
474             arg_info->body = f2;
475             if (fml->debug & 1)
476             {
477                 printf (" right=");
478                 fml_pr_list (f2);
479                 putchar ('\n');
480             }
481             f1 = fml_exec_group (info->body, fml);
482             fml_do_pop (fml);
483             if (fml->debug & 1)
484             {
485                 pr_indent (0);
486                 pr_indent (-1);
487             }
488         }
489         else
490             break;
491     }
492     return f1;
493 }
494
495 #if 0
496 static struct fml_node *fml_sub0 (Fml fml, struct fml_node *list)
497 {
498     struct token token;
499     struct fml_node *fn, *fn1;
500
501     fml_init_token (&token, fml);
502     assert (list);
503     fml_cmd_lex (&list, &token);
504     fn = fml_sub1 (fml, &list, &token);
505     if (token.kind == '\0')
506     {
507         fml_del_token (&token, fml);
508         return fn;
509     }
510     fn1 = fml_node_alloc (fml);
511     fn1->p[0] = fn;
512     fn = fn1;
513     while (token.kind != '\0')
514     {
515         fn1 = fn1->p[1] = fml_node_alloc (fml);
516         fn1->p[0] = fml_sub1 (fml, &list, &token);
517     }
518     fml_del_token (&token, fml);
519     return fn;
520 }
521 #else
522 static struct fml_node *fml_sub0 (Fml fml, struct fml_node *list)
523 {
524     struct token token;
525     struct fml_node *fn, *fn0, *fn1;
526
527     if (!list)
528         return NULL;
529     fml_init_token (&token, fml);
530     assert (list);
531     fml_cmd_lex (&list, &token);
532     fn1 = fn = fml_sub1 (fml, &list, &token);
533     if (fn->p[1] && token.kind != '\0')
534     {
535         fn1 = fml_node_alloc (fml);
536         fn1->p[0] = fn;
537     }
538     fn0 = fn1;
539     while (token.kind != '\0')
540     {
541         fn = fml_sub1 (fml, &list, &token);
542         if (fn->p[1])
543         {
544             fn1 = fn1->p[1] = fml_node_alloc (fml);
545             fn1->p[0] = fn;
546         }
547         else
548         {
549             fn1 = fn1->p[1] = fn;
550         }
551     }
552     fml_del_token (&token, fml);
553     return fn0;
554 }
555 #endif
556
557 static struct fml_node *fml_exec_foreach (struct fml_sym_info *info, Fml fml,
558                                           struct fml_node **lp,
559                                           struct token *tp)
560 {
561     struct fml_sym_info *info_var;
562     struct fml_node *fn, *body;
563     struct fml_node *return_value = NULL, *rv;
564
565     fml_cmd_lex (lp, tp);
566     assert (tp->kind == 't');
567     
568     info_var = fml_sym_lookup_local (fml->sym_tab, tp->tokenbuf);
569     if (!info_var)
570     {
571         info_var = fml_sym_add_local (fml->sym_tab, tp->tokenbuf);
572         info_var->body = NULL;
573         info_var->kind = FML_VAR;
574     }
575     else
576     {
577         if (info_var->kind == FML_VAR)
578             fml_node_delete (fml, info_var->body);
579         info_var->body = NULL;
580     }
581     if (fml->debug & 1)
582     {
583         pr_indent (1);
584         printf ("[foreach %s ", tp->tokenbuf);
585     }
586     fml_cmd_lex (lp, tp);
587     assert (tp->kind == 'g');
588     fn = fml_sub0 (fml, tp->sub);
589  
590     fml_cmd_lex (lp, tp);
591     assert (tp->kind == 'g');
592     body = tp->sub;
593  
594     while (fn)
595     {
596         struct fml_node *fn1;
597
598         fn1 = fn->p[1];
599         fn->p[1] = NULL;
600         if (fn->is_atom)
601             info_var->body = fn;
602         else
603             info_var->body = fn->p[0];
604         if (fml->debug & 1)
605         {
606             pr_indent (1);
607             printf ("[foreach loop var=");
608             fml_pr_list (info_var->body);
609             pr_indent (-1);
610         }
611         rv = fml_exec_group (body, fml);
612         if (rv)
613             return_value = rv;
614         fml_node_delete (fml, fn);
615         fn = fn1;
616     }
617     info_var->body = NULL;
618     if (fml->debug & 1)
619         pr_indent (-1);
620     return return_value;
621 }
622
623 static struct fml_node *fml_exec_if (struct fml_sym_info *info, Fml fml,
624                                      struct fml_node **lp, struct token *tp)
625 {
626     struct fml_node *fn, *body;
627     struct fml_node *rv, *return_value = NULL;
628
629     fml_cmd_lex (lp, tp);
630     assert (tp->kind == 'g');
631     fn = fml_sub0 (fml, tp->sub);
632     fml_cmd_lex (lp, tp);
633     assert (tp->kind == 'g');
634     if (fn)
635     {
636         rv = fml_exec_group (tp->sub, fml);
637         if (rv)
638             return_value = rv;
639     }
640     fml_cmd_lex (lp, tp);
641     if (tp->kind == 'e')
642     {
643         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
644         if (info->kind == FML_ELSE)
645         {
646             fml_cmd_lex (lp, tp);
647             assert (tp->kind == 'g');
648             body = tp->sub;
649             if (!fn)
650             {
651                 rv = fml_exec_group (body, fml);
652                 if (rv)
653                     return_value = rv;
654             }
655             fml_cmd_lex (lp, tp);
656         }
657     }
658     fml_node_delete (fml, fn);
659     return return_value;
660 }
661
662 static struct fml_node *fml_exec_while (struct fml_sym_info *info, Fml fml,
663                                         struct fml_node **lp, struct token *tp)
664 {
665     struct fml_node *fn, *body;
666     struct fml_node *return_value = NULL;
667
668     fml_cmd_lex (lp, tp);
669     assert (tp->kind == 'g');
670     fn = tp->sub;
671
672     fml_cmd_lex (lp, tp);
673     assert (tp->kind == 'g');
674     body = tp->sub;
675     assert (tp->sub);
676     while (1)
677     {
678         struct fml_node *fn_expr;
679         struct fml_node *rv;
680         if (!fn)
681             break;
682         fn_expr = fml_sub0 (fml, fn);
683         if (!fn_expr)
684             break;
685         fml_node_delete (fml, fn_expr);
686         rv = fml_exec_group (body, fml);
687         if (rv)
688             return_value = rv;
689     }
690     return return_value;
691 }
692
693 static void fml_exec_set (struct fml_sym_info *info, Fml fml,
694                     struct fml_node **lp, struct token *tp)
695 {
696     struct fml_node *fn;
697     struct fml_sym_info *info_var;
698     
699     fml_cmd_lex (lp, tp);
700     info_var = fml_sym_lookup_local (fml->sym_tab, tp->tokenbuf);
701     if (!info_var)
702     {
703         info_var = fml_sym_add_local (fml->sym_tab, tp->tokenbuf);
704         info_var->body = NULL;
705     }
706     if (fml->debug & 1)
707     {
708         pr_indent (1);
709         printf ("set %s ", tp->tokenbuf);
710     }
711     info_var->kind = FML_VAR;
712     fml_cmd_lex (lp, tp);
713
714     if (tp->kind == 'g')
715     {
716         fn = fml_sub0 (fml, tp->sub);
717         fml_cmd_lex (lp, tp);
718     }
719     else
720         fn = fml_sub2 (fml, lp, tp);
721     fml_node_delete (fml, info_var->body); 
722     info_var->body = fn;
723     if (fml->debug & 1)
724     {
725         fml_pr_list (info_var->body);
726         pr_indent (-1);
727     }
728 }
729
730 static void fml_emit_expr (Fml fml, struct fml_node **lp, struct token *tp)
731 {
732     struct fml_node *fn;
733
734     fn = fml_sub1 (fml, lp, tp);
735     fml_emit (fn);
736     fml_node_delete (fml, fn);
737 }
738
739 struct fml_node *fml_exec_group (struct fml_node *list, Fml fml)
740 {
741     struct token token;
742     struct fml_sym_info *info;
743     int first = 1;
744     struct fml_node *return_value = NULL, *rv;
745
746     if (!list)
747         return NULL;
748     fml_init_token (&token, fml);
749     fml_cmd_lex (&list, &token);
750     while (token.kind)
751     {
752         switch (token.kind)
753         {
754         case 'g':
755             rv = fml_exec_group (token.sub, fml);
756             if (rv)
757                 return_value = rv;
758             break;
759         case 'e':
760             info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
761             if (info)
762             {
763                 struct fml_node *fn;
764
765                 switch (info->kind)
766                 {
767                 case FML_FUNC:
768                     fml_cmd_lex (&list, &token);
769                     assert (token.kind == 't');
770                     info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
771                     if (!info)
772                         info = fml_sym_add (fml->sym_tab, token.tokenbuf);
773                     info->kind = FML_PREFIX;
774                     info->args = NULL;
775                     while (1)
776                     {
777                         fml_cmd_lex (&list, &token);
778                         if (token.kind != 't')
779                             break;
780                         if (!info->args)
781                         {
782                             info->args = fn = fml_node_alloc (fml);
783                         }
784                         else
785                         {
786                             for (fn = info->args; fn->p[1]; fn=fn->p[1])
787                                 ;
788                             fn = fn->p[1] = fml_node_alloc (fml);
789                         }
790                         fn->p[0] = token.atom;
791                         fn->is_atom = 1;
792                     }
793                     assert (token.kind == 'g');
794                     info->body = token.sub;
795                     break;
796                 case FML_BIN:
797                     fml_cmd_lex (&list, &token);
798                     assert (token.kind == 't');
799                     info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
800                     if (!info)
801                         info = fml_sym_add (fml->sym_tab, token.tokenbuf);
802                     info->kind = FML_BINARY;
803
804                     fml_cmd_lex (&list, &token);
805                     assert (token.kind == 't');
806                     info->args = fn = fml_node_alloc (fml);
807                     fn->p[0] = token.atom;
808                     fn->is_atom = 1;
809
810                     fml_cmd_lex (&list, &token);
811                     assert (token.kind == 't');
812                     fn = fn->p[1] = fml_node_alloc (fml);
813                     fn->p[0] = token.atom;
814                     fn->is_atom = 1;
815
816                     fml_cmd_lex (&list, &token);
817                     assert (token.kind == 'g');
818                     info->body = token.sub;
819                     break;
820                 case FML_VAR:
821                 case FML_PREFIX:
822                 case FML_CPREFIX:
823                     if (token.separate && !first)
824                         putchar (' ');
825                     first = 1;
826                     fml_emit_expr (fml, &list, &token);
827                     fml_node_stat (fml);
828                     continue;
829                 case FML_FOREACH:
830                     rv = fml_exec_foreach (info, fml, &list, &token);
831                     if (rv)
832                         return_value = rv;
833                     break;
834                 case FML_IF:
835                     rv = fml_exec_if (info, fml, &list, &token);
836                     if (rv)
837                         return_value = rv;
838                     continue;
839                 case FML_SET:
840                     fml_exec_set (info, fml, &list, &token);
841                     fml_node_stat (fml);
842                     continue;
843                 case FML_WHILE:
844                     rv = fml_exec_while (info, fml, &list, &token);
845                     if (rv)
846                         return_value = rv;
847                     break;
848                 case FML_RETURN:
849                     fml_cmd_lex (&list, &token);
850
851                     if (token.kind == 'g')
852                     {
853                         return_value = fml_sub0 (fml, token.sub);
854                         fml_cmd_lex (&list, &token);
855                     }
856                     else
857                         return_value = fml_sub2 (fml, &list, &token);
858                     if (fml->debug & 1)
859                     {
860                         pr_indent (1);
861                         printf ("return of:");
862                         fml_pr_list (return_value);
863                         pr_indent (-1);
864                     }
865                     continue;
866                 default:
867                     printf ("unknown token: `%s'", token.tokenbuf);
868                     fml_cmd_lex (&list, &token);
869                 }
870             }
871             else
872             {
873                 printf ("<unknown>");
874             }
875             break;
876         case 't':
877             if (token.separate && !first)
878                 putchar (' ');
879             first = 0;
880             fml_emit_expr (fml, &list, &token);
881             fml_node_stat (fml);
882             continue;
883         }
884         fml_cmd_lex (&list, &token);
885     }
886     fml_del_token (&token, fml);
887     return return_value;
888 }
889
890 void fml_exec (Fml fml)
891 {
892     fml_node_stat (fml);
893     fml_exec_group (fml->list, fml);
894     if (fml->debug & 1)
895         putchar ('\n');
896 }