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