Initial revision
[egate.git] / fml / fml.c
1 /*
2  * FML interpreter. Europagate, 1995
3  *
4  * $Log: fml.c,v $
5  * Revision 1.1  1995/02/06 13:48:09  adam
6  * Initial revision
7  *
8  */
9 #include <assert.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12
13 #include "fmlp.h"
14
15 static int default_read_func (void)
16 {
17     return getchar ();
18 }
19
20 static void default_err_handle (int no)
21 {
22     fprintf (stderr, "Error: %d\n", no);
23 }
24
25 static struct fml_node *fml_exec_space (Fml fml, struct fml_node **lp, 
26                                         struct token *tp);
27 static struct fml_node *fml_exec_nl (Fml fml, struct fml_node **lp, 
28                                      struct token *tp);
29 #if 0
30 static struct fml_node *fml_sub_bad (Fml fml, struct fml_node *list);
31 #endif
32 static struct fml_node *fml_sub0 (Fml fml, struct fml_node *list);
33
34 static struct fml_node *fml_exec_plus (Fml fml, struct fml_node *l,
35                                        struct fml_node *r);
36 static struct fml_node *fml_exec_minus (Fml fml, struct fml_node *l,
37                                         struct fml_node *r);
38 static struct fml_node *fml_exec_gt (Fml fml, struct fml_node *l,
39                                      struct fml_node *r);
40 static struct fml_node *fml_exec_lt (Fml fml, struct fml_node *l,
41                                      struct fml_node *r);
42 static struct fml_node *fml_exec_eq (Fml fml, struct fml_node *l,
43                                      struct fml_node *r);
44 static struct fml_node *fml_exec_and (Fml fml, struct fml_node *l,
45                                       struct fml_node *r);
46 static struct fml_node *fml_exec_or (Fml fml, struct fml_node *l,
47                                      struct fml_node *r);
48 static struct fml_node *fml_exec_indx (Fml fml, struct fml_node *l,
49                                      struct fml_node *r);
50                                   
51 static int indent = 0;
52
53 static void pr_indent (int n)
54 {
55     assert (indent >= 0);
56     if (n >= 0)
57     {
58         int i = indent;
59         while (--i >= 0)
60             putchar (' ');
61     }
62     if (n > 0)
63     {
64         printf ("[");
65         ++indent;
66     } 
67     else if (n < 0)
68     {
69         printf ("]\n");
70         --indent;
71     }
72 }
73
74 Fml fml_open (void)
75 {
76     struct fml_sym_info *sym_info;
77
78     Fml fml = malloc (sizeof(*fml));
79
80     if (!fml)
81         return NULL;
82
83     fml->escape_char = '\\';
84     fml->comment_char = '#';
85     fml->eof_mark = EOF;
86     fml->white_chars = " \t\f\r\n";
87     fml->read_func = default_read_func;
88     fml->err_handle = default_err_handle;
89
90     fml->list = NULL;
91     fml->sym_tab = fml_sym_open ();
92     fml->atom_free_list = NULL;
93     fml->node_free_list = NULL;
94     fml->debug = 0;
95
96     sym_info = fml_sym_add (fml->sym_tab, "func");
97     sym_info->kind = FML_FUNC;
98     sym_info = fml_sym_add (fml->sym_tab, "bin");
99     sym_info->kind = FML_BIN;
100     sym_info = fml_sym_add (fml->sym_tab, "if");
101     sym_info->kind = FML_IF;
102     sym_info = fml_sym_add (fml->sym_tab, "else");
103     sym_info->kind = FML_ELSE;
104     sym_info = fml_sym_add (fml->sym_tab, "foreach");
105     sym_info->kind = FML_FOREACH;
106     sym_info = fml_sym_add (fml->sym_tab, "set");
107     sym_info->kind = FML_SET;
108     sym_info = fml_sym_add (fml->sym_tab, "while");
109     sym_info->kind = FML_WHILE;
110     sym_info = fml_sym_add (fml->sym_tab, "return");
111     sym_info->kind = FML_RETURN;
112
113
114     sym_info = fml_sym_add (fml->sym_tab, "and");
115     sym_info->kind = FML_CBINARY;
116     sym_info->binary = fml_exec_and;
117     sym_info = fml_sym_add (fml->sym_tab, "or");
118     sym_info->kind = FML_CBINARY;
119     sym_info->binary = fml_exec_or;
120     sym_info = fml_sym_add (fml->sym_tab, "index");
121     sym_info->kind = FML_CBINARY;
122     sym_info->binary = fml_exec_indx;
123
124     sym_info = fml_sym_add (fml->sym_tab, "plus");
125     sym_info->kind = FML_CBINARY;
126     sym_info->binary = fml_exec_plus;
127     sym_info = fml_sym_add (fml->sym_tab, "minus");
128     sym_info->kind = FML_CBINARY;
129     sym_info->binary = fml_exec_minus;
130
131     sym_info = fml_sym_add (fml->sym_tab, "gt");
132     sym_info->kind = FML_CBINARY;
133     sym_info->binary = fml_exec_gt;
134     sym_info = fml_sym_add (fml->sym_tab, "lt");
135     sym_info->kind = FML_CBINARY;
136     sym_info->binary = fml_exec_lt;
137     sym_info = fml_sym_add (fml->sym_tab, "eq");
138     sym_info->kind = FML_CBINARY;
139     sym_info->binary = fml_exec_eq;
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 static 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 static 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 static 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         if ((*np)->is_atom)
205         {
206             tp->atom = (*np)->p[0];
207             if (!tp->atom->next)
208                 fml_atom_str (tp->atom, tp->atombuf);
209             else
210             {
211                 int l = fml_atom_str (tp->atom, NULL);
212                 if (l >= tp->maxbuf-1)
213                 {
214                     if (tp->maxbuf != FML_ATOM_BUF*2)
215                         free (tp->atombuf);
216                     tp->maxbuf = l + 40;
217                     tp->atombuf = malloc (tp->maxbuf*2);
218                     tp->tokenbuf = tp->atombuf + tp->maxbuf;
219                 }
220                 fml_atom_str (tp->atom, tp->atombuf);
221             }
222         }
223         else
224         {
225             tp->sub = (*np)->p[0];
226             tp->kind = 'g';
227             *np = (*np)->p[1];
228             return ;
229         }
230     }
231     cp = tp->atombuf + tp->offset;
232     dst = tp->tokenbuf;
233     if (*cp == tp->escape_char)
234     {
235         tp->kind = 'e';
236         tp->after_char = '\0';
237         cp++;
238         if (*cp == '\0')
239         {
240             strcpy (dst, " ");
241             tp->offset = 0;
242             *np = (*np)->p[1];
243             return ;
244         }
245     }
246     else
247     {
248         tp->kind = 't';
249         tp->after_char = ' ';
250     }
251     while (*cp)
252     {
253         if (*cp == tp->escape_char)
254         {
255             *dst = '\0';
256 #if 0
257             if (cp[1] == '\0')
258             {
259                 tp->after_char = ' ';
260                 break;
261             }
262 #endif
263             if (tp->kind == 'e')
264             {
265                 cp++;
266                 if (! *cp)
267                     break;
268             }
269             tp->offset = cp - tp->atombuf;
270             tp->after_char = '\0';
271             return ;
272         }
273         *dst++ = *cp++;
274     }
275     *dst = '\0';
276     tp->offset = 0;
277     *np = (*np)->p[1];
278 }
279
280 static struct fml_node *fml_lex_list (Fml fml, struct token *tp)
281 {
282     struct fml_node *fn;
283
284     if (tp->kind == 'g')
285         return tp->sub;
286     fn = fml_node_alloc (fml);
287     fn->is_atom = 1;
288     fn->p[0] = tp->atom;
289     return fn;
290 }
291
292 static struct fml_node *fml_exec_group (struct fml_node *list, Fml fml);
293
294 static void fml_lr_values (struct fml_node *l, int *left_val,
295                            struct fml_node *r, int *right_val)
296 {
297     static char arg[128];
298     if (l->is_atom)
299     {
300         fml_atom_strx (l->p[0], arg, 127);
301         *left_val = atoi (arg);
302     }
303     else
304         *left_val = 0;
305     if (r->is_atom)
306     {
307         fml_atom_strx (r->p[0], arg, 127);
308         *right_val = atoi (arg);
309     }
310     else
311         *right_val = 0;
312 }
313
314 static struct fml_node *fml_exec_and (Fml fml, struct fml_node *l,
315                                       struct fml_node *r)
316 {
317     if (l && r)
318         return r;
319     else
320         return NULL;
321 }
322
323 static struct fml_node *fml_exec_or (Fml fml, struct fml_node *l,
324                                       struct fml_node *r)
325 {
326     if (l)
327         return l;
328     return r;
329 }
330
331 static struct fml_node *fml_exec_indx (Fml fml, struct fml_node *l,
332                                        struct fml_node *r)
333 {
334     struct fml_node *list = l;
335     int indx;
336
337     if (!l || !r || !r->is_atom)
338         return NULL;
339     indx = fml_atom_val (r->p[0]);
340     while (--indx >= 0 && list)
341         list = list->p[1];
342     if (!list)
343         return NULL;
344     if (list->is_atom)
345     {
346         struct fml_node *fn = fml_node_alloc (fml);
347         fn->is_atom = 1;
348         fn->p[0] = list->p[0];
349         return fn;
350     }
351     else
352         return list->p[0];
353 }
354
355 static struct fml_node *fml_exec_plus (Fml fml, struct fml_node *l,
356                                        struct fml_node *r)
357 {
358     int left_val, right_val;
359     char arg[20];
360     struct fml_node *fn;
361
362     fml_lr_values (l, &left_val, r, &right_val);
363     sprintf (arg, "%d", left_val + right_val);
364     fn = fml_node_alloc (fml);
365     fn->is_atom = 1;
366     fn->p[0] = fml_atom_alloc (fml, arg);
367     return fn;
368 }
369
370 static struct fml_node *fml_exec_minus (Fml fml, struct fml_node *l,
371                                        struct fml_node *r)
372 {
373     int left_val, right_val;
374     char arg[20];
375     struct fml_node *fn;
376
377     fml_lr_values (l, &left_val, r, &right_val);
378     sprintf (arg, "%d", left_val - right_val);
379     fn = fml_node_alloc (fml);
380     fn->is_atom = 1;
381     fn->p[0] = fml_atom_alloc (fml, arg);
382     return fn;
383 }
384
385
386 static struct fml_node *fml_exec_gt (Fml fml, struct fml_node *l,
387                                      struct fml_node *r)
388 {
389     int left_val, right_val;
390     struct fml_node *fn;
391     fml_lr_values (l, &left_val, r, &right_val);
392     if (left_val > right_val)
393     {
394         fn = fml_node_alloc (fml);
395         fn->is_atom = 1;
396         fn->p[0] = fml_atom_alloc (fml, "1");
397     }
398     else
399         fn = NULL;
400     return fn;
401 }
402
403
404 static struct fml_node *fml_exec_lt (Fml fml, struct fml_node *l,
405                                      struct fml_node *r)
406 {
407     int left_val, right_val;
408     struct fml_node *fn;
409     fml_lr_values (l, &left_val, r, &right_val);
410     if (left_val < right_val)
411     {
412         fn = fml_node_alloc (fml);
413         fn->is_atom = 1;
414         fn->p[0] = fml_atom_alloc (fml, "1");
415     }
416     else
417         fn = NULL;
418     return fn;
419 }
420
421 static struct fml_node *fml_exec_eq (Fml fml, struct fml_node *l,
422                                      struct fml_node *r)
423 {
424     int left_val, right_val;
425     struct fml_node *fn;
426     fml_lr_values (l, &left_val, r, &right_val);
427     if (left_val == right_val)
428     {
429         fn = fml_node_alloc (fml);
430         fn->is_atom = 1;
431         fn->p[0] = fml_atom_alloc (fml, "1");
432     }
433     else
434         fn = NULL;
435     return fn;
436 }
437
438
439 static struct fml_node *fml_exec_space (Fml fml, struct fml_node **lp, 
440                                         struct token *tp)
441 {
442     return NULL;
443 }
444
445 static struct fml_node *fml_exec_nl (Fml fml, struct fml_node **lp, 
446                                      struct token *tp)
447 {
448     putchar ('\n');
449     return NULL;
450 }
451
452 static struct fml_node *fml_exec_prefix (struct fml_sym_info *info, Fml fml,
453                                          struct fml_node **lp,
454                                          struct token *tp)
455 {
456     struct fml_node *fn;
457     struct fml_sym_info *arg_info;
458     struct fml_node *return_value;
459     static char arg[128];
460
461     if (fml->debug)
462     {
463         pr_indent (1);
464         printf ("exec_prefix ");
465     }
466     fml_sym_push (fml->sym_tab);
467     for (fn = info->args; fn; fn = fn->p[1])
468     {
469         fml_cmd_lex (lp, tp);
470
471         assert (fn->is_atom);
472         fml_atom_strx (fn->p[0], arg, 127);
473         if (fml->debug)
474         {
475             
476             pr_indent (1);
477             printf ("%s=", arg);
478         }
479         arg_info = fml_sym_add_local (fml->sym_tab, arg);
480         arg_info->kind = FML_VAR;
481         arg_info->body = fml_lex_list (fml, tp);
482         if (arg_info->body)
483             arg_info->body = fml_sub0 (fml, arg_info->body);
484         if (fml->debug)
485         {
486             fml_pr_list (arg_info->body);
487             pr_indent (-1);
488         }
489     }
490     return_value = fml_exec_group (info->body, fml);
491     if (fml->debug)
492     {
493         pr_indent(0);
494         pr_indent (-1);
495     }
496     fml_do_pop (fml);
497     return return_value;
498 }
499
500
501 static void fml_emit (struct fml_node *list)
502 {
503     int s = 0;
504     while (list)
505     {
506         if (list->is_atom)
507         {
508             struct fml_atom *a;
509             if (s)
510                 printf (" ");
511             s++;
512             for (a = list->p[0]; a; a=a->next)
513                 printf ("%s", a->buf);
514         }
515         else
516             fml_emit (list->p[0]);
517         list = list->p[1];
518     }
519 }
520
521 static struct fml_node *fml_sub1 (Fml fml, struct fml_node **lp,
522                                   struct token *tp);
523
524
525 static struct fml_node *fml_sub2 (Fml fml, struct fml_node **lp,
526                                   struct token *tp)
527 {
528     struct fml_node *fn;
529     struct fml_sym_info *info;
530     if (tp->kind == 'e')
531     {
532         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
533         assert (info);
534         switch (info->kind)
535         {
536         case FML_VAR:
537             fn = info->body;
538             fml_cmd_lex (lp, tp);
539             break;
540         case FML_PREFIX:
541             fn = fml_exec_prefix (info, fml, lp, tp);
542             fml_cmd_lex (lp, tp);
543             break;
544         case FML_CPREFIX:
545             fn = (*info->prefix) (fml, lp, tp);
546             fml_cmd_lex (lp, tp);
547             break;
548         default:
549             fml_cmd_lex (lp, tp);
550             fn = NULL;
551         }
552     }
553     else if (tp->kind == 'g')
554     {
555         if (tp->sub)
556             fn = fml_sub0 (fml, tp->sub);
557         else
558             fn = NULL;
559         fml_cmd_lex (lp, tp);
560     }
561     else if (tp->kind == 't')
562     {
563         fn = fml_node_alloc (fml);
564         fn->is_atom = 1;
565         fn->p[0] = fml_atom_alloc (fml, tp->tokenbuf);
566         fml_cmd_lex (lp, tp);
567     }
568     else
569         fn = NULL;
570     return fn;
571 }
572
573 static struct fml_node *fml_sub1 (Fml fml, struct fml_node **lp,
574                                   struct token *tp)
575 {
576     struct fml_node *f1, *f2;
577     struct fml_sym_info *info;
578
579     f1 = fml_sub2 (fml, lp, tp);
580     while (tp->kind == 'e')
581     {
582         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
583         if (!info)
584         {
585             fprintf (stderr, "cannot locate `%s'", tp->tokenbuf);
586             exit (1);
587         }
588         if (info->kind == FML_CBINARY)
589         {
590             fml_cmd_lex (lp, tp);
591             f2 = fml_sub2 (fml, lp, tp);
592             f1 = (*info->binary) (fml, f1, f2);
593             continue;
594         }
595         else if (info->kind == FML_BINARY)
596         {
597             struct fml_sym_info *arg_info;
598             char arg[127];
599
600             if (fml->debug)
601             {
602                 pr_indent (1);
603                 printf ("exec binary %s", tp->tokenbuf);
604             }
605             fml_cmd_lex (lp, tp);
606             f2 = fml_sub2 (fml, lp, tp);
607             fml_sym_push (fml->sym_tab);
608
609             fml_atom_strx (info->args->p[0], arg, 127);
610             arg_info = fml_sym_add_local (fml->sym_tab, arg);
611             arg_info->kind = FML_VAR;
612             arg_info->body = f1;
613             if (fml->debug)
614             {
615                 printf (" left=");
616                 fml_pr_list (f1);
617             }
618             fml_atom_strx ( ((struct fml_node *) info->args->p[1])->p[0],
619                            arg, 127);
620             arg_info = fml_sym_add_local (fml->sym_tab, arg);
621             arg_info->kind = FML_VAR;
622             arg_info->body = f2;
623             if (fml->debug)
624             {
625                 printf (" right=");
626                 fml_pr_list (f2);
627                 putchar ('\n');
628             }
629             f1 = fml_exec_group (info->body, fml);
630             fml_do_pop (fml);
631             if (fml->debug)
632             {
633                 pr_indent (0);
634                 pr_indent (-1);
635             }
636         }
637         else
638             break;
639     }
640     return f1;
641 }
642
643 #if 0
644 static struct fml_node *fml_sub_bad (Fml fml, struct fml_node *list)
645 {
646     struct token token;
647     struct fml_node *fn, *fn1;
648
649     fml_init_token (&token, fml);
650     assert (list);
651     fml_cmd_lex (&list, &token);
652     fn = fml_sub1 (fml, &list, &token);
653     if (token.kind == '\0')
654     {
655         fml_del_token (&token, fml);
656         return fn;
657     }
658     fn1 = fml_node_alloc (fml);
659     fn1->p[0] = fn;
660     fn = fn1;
661     while (token.kind != '\0')
662     {
663         fn1 = fn1->p[1] = fml_node_alloc (fml);
664         fn1->p[0] = fml_sub1 (fml, &list, &token);
665     }
666     fml_del_token (&token, fml);
667     return fn;
668 }
669 #endif
670
671 static struct fml_node *fml_sub0 (Fml fml, struct fml_node *list)
672 {
673     struct token token;
674     struct fml_node *fn, *fn1;
675
676     fml_init_token (&token, fml);
677     assert (list);
678     fml_cmd_lex (&list, &token);
679     fn1 = fn = fml_sub1 (fml, &list, &token);
680
681     while (token.kind != '\0')
682         fn1 = fn1->p[1] = fml_sub1 (fml, &list, &token);
683     fml_del_token (&token, fml);
684     return fn;
685 }
686
687 static struct fml_node *fml_exec_foreach (struct fml_sym_info *info, Fml fml,
688                                           struct fml_node **lp,
689                                           struct token *tp)
690 {
691     struct fml_sym_info *info_var;
692     struct fml_node *fn, *body;
693     struct fml_node *return_value = NULL, *rv;
694
695     fml_cmd_lex (lp, tp);
696     assert (tp->kind == 't');
697     
698     info_var = fml_sym_lookup_local (fml->sym_tab, tp->tokenbuf);
699     if (!info_var)
700     {
701         info_var = fml_sym_add_local (fml->sym_tab, tp->tokenbuf);
702         info_var->body = NULL;
703         info_var->kind = FML_VAR;
704     }
705     if (fml->debug)
706     {
707         pr_indent (1);
708         printf ("[foreach %s ", tp->tokenbuf);
709     }
710     fml_cmd_lex (lp, tp);
711
712     fn = fml_lex_list (fml, tp);
713     if (fn)
714         fn = fml_sub0 (fml, fn);
715  
716     fml_cmd_lex (lp, tp);
717
718     body = fml_lex_list (fml, tp);
719  
720     while (fn)
721     {
722         if (fn->is_atom)
723         {
724             struct fml_node *fn1;
725             fn1 = fml_node_alloc (fml);
726             fn1->is_atom=1;
727             fn1->p[0] = fn->p[0];
728             info_var->body = fn1;
729         }
730         else
731             info_var->body = fn->p[0];
732
733         if (fml->debug)
734         {
735             pr_indent (1);
736             printf ("[foreach loop var=");
737             fml_pr_list (info_var->body);
738             pr_indent (-1);
739         }
740         rv = fml_exec_group (body, fml);
741         if (rv)
742             return_value = rv;
743         fn = fn->p[1];
744     }
745     if (fml->debug)
746         pr_indent (-1);
747     return return_value;
748 }
749
750 static struct fml_node *fml_exec_if (struct fml_sym_info *info, Fml fml,
751                                      struct fml_node **lp, struct token *tp)
752 {
753     struct fml_node *fn, *body;
754     struct fml_node *rv, *return_value = NULL;
755
756     fml_cmd_lex (lp, tp);
757     fn = fml_lex_list (fml, tp);
758     if (fn)
759         fn = fml_sub0 (fml, fn);
760     fml_cmd_lex (lp, tp);
761     if (fn)
762     {
763         body = fml_lex_list (fml, tp);
764         rv = fml_exec_group (body, fml);
765         if (rv)
766             return_value = rv;
767     }
768     fml_cmd_lex (lp, tp);
769     if (tp->kind == 'e')
770     {
771         info = fml_sym_lookup (fml->sym_tab, tp->tokenbuf);
772         if (info->kind == FML_ELSE)
773         {
774             fml_cmd_lex (lp, tp);
775             body = fml_lex_list (fml, tp);
776             fml_cmd_lex (lp, tp);
777             if (!fn)
778             {
779                 rv = fml_exec_group (body, fml);
780                 if (rv)
781                     return_value = rv;
782             }
783         }
784     }
785     return return_value;
786 }
787
788 static struct fml_node *fml_exec_while (struct fml_sym_info *info, Fml fml,
789                                         struct fml_node **lp, struct token *tp)
790 {
791     struct fml_node *fn, *body;
792     struct fml_node *return_value = NULL;
793
794     fml_cmd_lex (lp, tp);
795     fn = fml_lex_list (fml, tp);
796
797     fml_cmd_lex (lp, tp);
798     body = fml_lex_list (fml, tp);
799     while (1)
800     {
801         struct fml_node *fn_expr;
802         struct fml_node *rv;
803         if (!fn)
804             break;
805         fn_expr = fml_sub0 (fml, fn);
806         if (!fn_expr)
807             break;
808         rv = fml_exec_group (body, fml);
809         if (rv)
810             return_value = rv;
811     }
812     return return_value;
813 }
814
815 static void fml_exec_set (struct fml_sym_info *info, Fml fml,
816                     struct fml_node **lp, struct token *tp)
817 {
818     struct fml_node *fn;
819     struct fml_sym_info *info_var;
820
821     fml_cmd_lex (lp, tp);
822     info_var = fml_sym_lookup_local (fml->sym_tab, tp->tokenbuf);
823     if (!info_var)
824     {
825         info_var = fml_sym_add_local (fml->sym_tab, tp->tokenbuf);
826         info_var->body = NULL;
827     }
828     if (fml->debug)
829     {
830         pr_indent (1);
831         printf ("set %s ", tp->tokenbuf);
832     }
833     info_var->kind = FML_VAR;
834     fml_cmd_lex (lp, tp);
835     fn = fml_lex_list (fml, tp);
836     assert (fn);
837     if (fn)
838         fn = fml_sub0 (fml, fn);
839     info_var->body = fn;
840     if (fml->debug)
841     {
842         fml_pr_list (info_var->body);
843         pr_indent (-1);
844     }
845 }
846
847 static void fml_emit_expr (Fml fml, struct fml_node **lp, struct token *tp)
848 {
849     struct fml_node *fn;
850
851     fn = fml_sub1 (fml, lp, tp);
852     fml_emit (fn);
853 #if 0
854     if (fn && fn->is_atom)
855     {
856         char arg[128];
857         fml_atom_strx (fn->p[0], arg, 127);
858         printf ("%s", arg);
859     }
860 #endif
861 }
862
863 static struct fml_node *fml_exec_group (struct fml_node *list, Fml fml)
864 {
865     struct token token;
866     struct fml_sym_info *info;
867     int separate = 0;
868     struct fml_node *return_value = NULL, *rv;
869
870     if (!list)
871         return NULL;
872     fml_init_token (&token, fml);
873     fml_cmd_lex (&list, &token);
874     while (token.kind)
875     {
876         switch (token.kind)
877         {
878         case 'g':
879             rv = fml_exec_group (token.sub, fml);
880             if (rv)
881                 return_value = rv;
882             break;
883         case 'e':
884             info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
885             if (info)
886             {
887                 struct fml_node *fn;
888
889                 switch (info->kind)
890                 {
891                 case FML_FUNC:
892                     fml_cmd_lex (&list, &token);
893                     assert (token.kind == 't');
894                     info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
895                     if (!info)
896                         info = fml_sym_add (fml->sym_tab, token.tokenbuf);
897                     info->kind = FML_PREFIX;
898                     info->args = NULL;
899                     while (1)
900                     {
901                         fml_cmd_lex (&list, &token);
902                         if (token.kind != 't')
903                             break;
904                         if (!info->args)
905                         {
906                             info->args = fn = fml_node_alloc (fml);
907                         }
908                         else
909                         {
910                             for (fn = info->args; fn->p[1]; fn=fn->p[1])
911                                 ;
912                             fn = fn->p[1] = fml_node_alloc (fml);
913                         }
914                         fn->p[0] = token.atom;
915                         fn->is_atom = 1;
916                     }
917                     assert (token.kind == 'g');
918                     info->body = token.sub;
919                     break;
920                 case FML_BIN:
921                     fml_cmd_lex (&list, &token);
922                     assert (token.kind == 't');
923                     info = fml_sym_lookup (fml->sym_tab, token.tokenbuf);
924                     if (!info)
925                         info = fml_sym_add (fml->sym_tab, token.tokenbuf);
926                     info->kind = FML_BINARY;
927
928                     fml_cmd_lex (&list, &token);
929                     assert (token.kind == 't');
930                     info->args = fn = fml_node_alloc (fml);
931                     fn->p[0] = token.atom;
932                     fn->is_atom = 1;
933
934                     fml_cmd_lex (&list, &token);
935                     assert (token.kind == 't');
936                     fn = fn->p[1] = fml_node_alloc (fml);
937                     fn->p[0] = token.atom;
938                     fn->is_atom = 1;
939
940                     fml_cmd_lex (&list, &token);
941                     assert (token.kind == 'g');
942                     info->body = token.sub;
943                     break;
944 #if 0
945                 case FML_PREFIX:
946                     after_char = token.after_char;
947                     fml_exec_prefix (info, fml, &list, &token);
948                     if (after_char)
949                         putchar (after_char);
950                     break;
951                 case FML_VAR:
952                     fml_emit (info->body);
953                     if (token.after_char)
954                         putchar (token.after_char);
955                     break;
956 #endif
957                 case FML_VAR:
958                 case FML_PREFIX:
959                 case FML_CPREFIX:
960                     if (separate)
961                         putchar (' ');
962                     if (token.offset == 0)
963                         separate = ' ';
964                     else
965                         separate = 0;
966                     fml_emit_expr (fml, &list, &token);
967                     continue;
968                 case FML_FOREACH:
969                     rv = fml_exec_foreach (info, fml, &list, &token);
970                     if (rv)
971                         return_value = rv;
972                     break;
973                 case FML_IF:
974                     rv = fml_exec_if (info, fml, &list, &token);
975                     if (rv)
976                         return_value = rv;
977                     break;
978                 case FML_SET:
979                     fml_exec_set (info, fml, &list, &token);
980                     break;
981                 case FML_WHILE:
982                     rv = fml_exec_while (info, fml, &list, &token);
983                     if (rv)
984                         return_value = rv;
985                     break;
986                 case FML_RETURN:
987                     fml_cmd_lex (&list, &token);
988                     return_value = fml_lex_list (fml, &token);
989                     if (return_value)
990                         return_value = fml_sub0 (fml, return_value);
991                     if (fml->debug)
992                     {
993                         pr_indent (1);
994                         printf ("return of:");
995                         fml_pr_list (return_value);
996                         pr_indent (-1);
997                     }
998                     break;
999                 default:
1000                     printf ("unknown token: `%s'", token.tokenbuf);
1001                     fml_cmd_lex (&list, &token);
1002                 }
1003             }
1004             else
1005             {
1006                 printf ("<unknown>");
1007             }
1008             break;
1009         case 't':
1010             if (separate)
1011                 putchar (' ');
1012             if (token.offset == 0)
1013                 separate = ' ';
1014             else
1015                 separate = 0;
1016             fml_emit_expr (fml, &list, &token);
1017             continue;
1018 #if 0               
1019             printf ("%s", token.tokenbuf);
1020             if (token.after_char)
1021                 putchar (token.after_char);
1022 #endif
1023         }
1024         fml_cmd_lex (&list, &token);
1025     }
1026     fml_del_token (&token, fml);
1027     return return_value;
1028 }
1029
1030 void fml_exec (Fml fml)
1031 {
1032     fml_exec_group (fml->list, fml);
1033     if (fml->debug)
1034         printf ("\n");
1035 }
1036
1037