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