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