First version of the FML interpreter. It's slow and memory isn't
[egate.git] / fml / fmlsym.c
1 /*
2  * FML interpreter. Europagate, 1995
3  *
4  * $Log: fmlsym.c,v $
5  * Revision 1.1.1.1  1995/02/06 13:48:10  adam
6  * First version of the FML interpreter. It's slow and memory isn't
7  * freed properly. In particular, the FML nodes aren't released yet.
8  *
9  */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <assert.h>
13
14 #include "fmlp.h"
15
16 struct fml_sym {
17     struct fml_sym_info info;
18     struct fml_sym *next;
19     int level;
20     char *name;
21 };
22
23 struct fml_sym_tab {
24     int level;
25     int hash;
26     struct fml_sym **array;
27 };
28
29 struct fml_sym_tab *fml_sym_open (void)
30 {
31     struct fml_sym_tab *tab;
32     int i;
33
34     tab = malloc (sizeof (*tab));
35     if (!tab)
36         return NULL;
37     tab->level = 1;
38     tab->hash = 101;
39     tab->array = malloc (sizeof(*tab->array) * tab->hash);
40     if (!tab->array)
41     {
42         free (tab);
43         return NULL;
44     }
45     for (i = 0; i<tab->hash; i++)
46         tab->array[i] = NULL;
47     return tab;
48 }
49
50 void fml_sym_close (struct fml_sym_tab **tabp)
51 {
52     struct fml_sym *sym, *sym1;
53     int i;
54     for (i = (*tabp)->hash; --i >= 0; )
55         for (sym = (*tabp)->array[i]; sym; sym = sym1)
56         {
57             sym1 = sym->next;
58             free (sym->name);
59             free (sym);
60         }
61     free (*tabp);
62     *tabp = NULL;
63 }
64
65 void fml_sym_push (struct fml_sym_tab *tab)
66 {
67     tab->level ++;
68 }
69
70 void fml_sym_pop (struct fml_sym_tab *tab, void (*ph)(struct fml_sym_info *i))
71 {
72     struct fml_sym **fsp;
73     int i;
74
75     assert (tab->level > 0);
76     for (i = tab->hash; --i >= 0; )
77     {
78         fsp = tab->array + i;
79         while (*fsp)
80         {
81             if ((*fsp)->level == tab->level)
82             {
83                 struct fml_sym *fs;
84
85                 fs = *fsp;
86                 if (ph)
87                     (*ph)(&fs->info);
88                 *fsp = (*fsp)->next;
89                 free (fs->name);
90                 free (fs);
91             }
92             else
93                 fsp = &(*fsp)->next;
94         }
95     }
96     tab->level--;
97 }
98
99 static unsigned fml_sym_hash (const char *s, unsigned hash)
100 {
101     unsigned long v = 0;
102     while (*s)
103         v = v*65599 + *s++;
104     return v % hash;
105 }
106
107
108 static struct fml_sym_info *sym_add (struct fml_sym_tab *tab,
109                                      const char *s, int level)
110 {
111     char *cp;
112     struct fml_sym *sym;
113     struct fml_sym **sym_entry;
114
115     cp = malloc (strlen(s)+1);
116     if (!cp)
117         return NULL;
118     strcpy (cp, s);
119
120     sym = malloc (sizeof (*sym));
121     if (!sym)
122     {
123         free (cp);
124         return NULL;
125     }
126     sym_entry = tab->array + fml_sym_hash (s, tab->hash);
127     sym->name = cp;
128     sym->next = *sym_entry;
129     *sym_entry = sym;
130     sym->level = level;
131     return &sym->info;
132 }
133
134 struct fml_sym_info *fml_sym_add (struct fml_sym_tab *tab, const char *s)
135 {
136     return sym_add (tab, s, 0);
137 }
138
139 struct fml_sym_info *fml_sym_add_local (struct fml_sym_tab *tab, const char *s)
140 {
141     return sym_add (tab, s, tab->level);
142 }
143
144 static struct fml_sym_info *sym_lookup (struct fml_sym_tab *tab,
145                                         const char *s, int level)
146 {
147     struct fml_sym *sym;
148     struct fml_sym *sym0 = NULL;
149     struct fml_sym **sym_entry;
150
151     sym_entry = tab->array + fml_sym_hash (s, tab->hash);
152     for (sym = *sym_entry; sym; sym = sym->next)
153         if (!strcmp (sym->name, s))
154             if (!sym0 || sym->level > sym0->level)
155                 sym0 = sym;
156     if (sym0)
157     {
158         assert (sym0->level <= tab->level);
159         if (level && sym0->level != level)
160             return NULL;
161         return &sym0->info;
162     }
163     else
164         return NULL;
165 }
166
167 struct fml_sym_info *fml_sym_lookup (struct fml_sym_tab *tab, const char *s)
168 {
169     return sym_lookup (tab, s, 0);
170 }
171
172 struct fml_sym_info *fml_sym_lookup_local (struct fml_sym_tab *tab,
173                                            const char *s)
174 {
175     return sym_lookup (tab, s, tab->level);
176 }
177