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