Pristine Ack-5.5
[Ack-5.5.git] / util / LLgen / src / name.c
1 /* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
2  * For full copyright and restrictions on use see the file COPYING in the top
3  * level of the LLgen tree.
4  */
5
6 /*
7  *  L L G E N
8  *
9  *  An Extended LL(1) Parser Generator
10  *
11  *  Author : Ceriel J.H. Jacobs
12  */
13
14 /*
15  * name.c
16  * Defines the symboltable search routine, a name store routine and an
17  * initialising routine.
18  */
19
20 # include "types.h"
21 # include "extern.h"
22 # include "assert.h"
23 # include "io.h"
24
25 # ifndef NORCSID
26 static string rcsid7 = "$Id: name.c,v 2.11 1997/02/21 11:27:53 ceriel Exp $";
27 # endif
28
29 # define HASHSIZE 128
30 # define NMSIZ 2048     /* Room for names allocated NMSIZ bytes at a time */
31
32 static char     *name, *maxname;
33 static p_entry  h_root[HASHSIZE];               /* hash table */
34 static string   e_literal = "Illegal literal";
35 static p_entry  entries, maxentries;
36 static t_info   token_info, nont_info;
37
38 /* Defined in this file are: */
39 extern string   store();
40 extern          name_init();
41 STATIC int      hash();
42 STATIC p_entry  newentry();
43 extern p_gram   search();
44
45 p_mem alloc();
46 p_mem new_mem();
47
48 name_init() {
49         token_info.i_esize = sizeof (t_token);
50         token_info.i_incr = 50;
51         nont_info.i_esize = sizeof (t_nont);
52         nont_info.i_incr = 50;
53         search(TERMINAL,"EOFILE",ENTERING);
54 #ifdef NON_CORRECTING
55         illegal_gram = search(TERMINAL,"LLILLEGAL",ENTERING);
56 #endif
57 }
58
59 STATIC p_entry
60 newentry(str, next) string str; p_entry next; {
61         register p_entry p;
62
63         if ((p = entries) == maxentries) {
64                 p = (p_entry) alloc(50 * sizeof(t_entry));
65                 maxentries = p + 50;
66         }
67         entries = p + 1;
68         p->h_name = str;
69         p->h_next = next;
70         p->h_type.g_lineno = linecount;
71 #ifdef NON_CORRECTING
72         p->h_type.g_erroneous = 0;
73 #endif
74         return p;
75 }
76
77 string
78 store(s) string s; {
79         /*
80          * Store a string s in the name table
81          */
82         register string s1, t ,u;
83
84         u = name;
85         t = s;
86         s1 = u;
87         do {
88                 if (u >= maxname) {
89                         u = alloc(NMSIZ);
90                         maxname = u + NMSIZ;
91                         t = s;
92                         s1 = u;
93                 }
94                 *u++ = *t;
95         } while (*t++);
96         name = u;
97         return s1;
98 }
99
100 STATIC int
101 hash(str) string str; {
102         /*
103          * Compute the hash for string str
104          */
105         register int    i;
106         register string l;
107
108         l = str;
109         i = 0;
110         while (*l != '\0') i += *l++ & 0377;
111         i += l - str;
112         return i % HASHSIZE;
113 }
114
115 p_gram
116 search(type,str,option) register string str; {
117         /*
118          * Search for object str.
119          * It has type UNKNOWN, LITERAL, TERMINAL or NONTERM.
120          * option can be ENTERING or BOTH (also looking).
121          */
122         register int            val = 0;
123         register p_entry        p;
124         register int            i;
125         int                     type1;
126
127         i = hash(str);
128         /*
129          * Walk hash chain
130          */
131         for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) {
132                 if(!strcmp(p->h_name,str)) {
133                         type1 = g_gettype(&(p->h_type));
134                         if (type1 != type) {
135                                 if (type1 == LITERAL || type == LITERAL) {
136                                         continue;
137                                 }
138                                 if (type == TERMINAL) {
139                                         error(linecount,
140                                                 "%s: is already a nonterminal",
141                                                 str);
142                                         continue;
143                                 }
144                                 else if (type == NONTERM) {
145                                         error(linecount,
146                                                 "%s : is already a token",
147                                                 str);
148                                         continue;
149                                 }
150                         }
151                         if (option==ENTERING)  {
152                                 error(linecount,
153                                         "%s : is already defined",str);
154                         }
155                         p->h_type.g_lineno = linecount;
156                         return &(p->h_type);
157                 }
158         }
159         p = newentry(store(str), h_root[i]);
160         h_root[i] = p;
161         if (type == TERMINAL || type == LITERAL) {
162                 register p_token pt;
163
164                 pt = (p_token) new_mem(&token_info);
165                 tokens = (p_token) token_info.i_ptr;
166                 pt->t_string = p->h_name;
167                 if (type == LITERAL) {
168                         if (str[0] == '\\') {
169                                 /*
170                                  * Handle escapes in literals
171                                  */
172                                 if (str[2] == '\0') {
173                                         switch(str[1]) {
174                                           case 'n' :
175                                                 val = '\n';
176                                                 break;
177                                           case 'r' :
178                                                 val = '\r';
179                                                 break;
180                                           case 'b' :
181                                                 val = '\b';
182                                                 break;
183                                           case 'f' :
184                                                 val = '\f';
185                                                 break;
186                                           case 't' :
187                                                 val = '\t';
188                                                 break;
189                                           case '\'':
190                                                 val = '\'';
191                                                 break;
192                                           case '\\':
193                                                 val = '\\';
194                                                 break;
195                                           default  :
196                                                 error(linecount,e_literal);
197                                         }
198                                 } else {
199                                         /*
200                                          * Here, str[2] != '\0'
201                                          */
202                                         if (str[1] > '3' || str[1] < '0' ||
203                                             str[2] > '7' || str[2] < '0' ||
204                                             str[3] > '7' || str[3] < '0' ||
205                                             str[4] != '\0') error(linecount,e_literal);
206                                         val = 64*str[1] - 73*'0' +
207                                               8*str[2] + str[3];
208                                 }
209                         } else {
210                                 /*
211                                  * No escape in literal
212                                  */
213                                 if (str[1] == '\0') val = str[0];
214                                 else error(linecount,e_literal);
215                         }
216                         pt->t_tokno = val;
217                         g_settype(&(p->h_type), LITERAL);
218                 } else {
219                         /*
220                          * Here, type = TERMINAL
221                          */
222                         pt->t_tokno = assval++;
223                         g_settype(&(p->h_type), TERMINAL);
224                 }
225                 g_setcont(&(p->h_type), ntokens);
226                 ntokens++;
227                 return &(p->h_type);
228         }
229         /*
230          * type == NONTERM || type == UNKNOWN
231          * UNKNOWN and not yet declared means : NONTERM
232          */
233         {
234                 register p_nont q;
235
236                 q = (p_nont) new_mem(&nont_info);
237                 nonterms = (p_nont) nont_info.i_ptr;
238                 q->n_name = p->h_name;
239                 q->n_rule = 0;
240                 q->n_lineno = linecount;
241                 q->n_string = f_input;
242                 q->n_follow = 0;
243                 q->n_flags = 0;
244                 q->n_contains = 0;
245                 g_settype(&(p->h_type), NONTERM);
246                 g_setcont(&(p->h_type), nnonterms);
247                 g_setnpar(&(p->h_type), 0);
248                 nnonterms++;
249                 return &(p->h_type);
250         }
251 }