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