|
1 /********************************************************************* |
|
2 * RPC for the Windows NT Operating System |
|
3 * 1993 by Martin F. Gergeleit |
|
4 * Users may use, copy or modify Sun RPC for the Windows NT Operating |
|
5 * System according to the Sun copyright below. |
|
6 * |
|
7 * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO |
|
8 * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE |
|
9 * USE OF. USE ENTIRELY AT YOUR OWN RISK!!! |
|
10 *********************************************************************/ |
|
11 |
|
12 /* @(#)rpc_parse.c 2.1 88/08/01 4.0 RPCSRC */ |
|
13 /* |
|
14 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for |
|
15 * unrestricted use provided that this legend is included on all tape |
|
16 * media and as a part of the software program in whole or part. Users |
|
17 * may copy or modify Sun RPC without charge, but are not authorized |
|
18 * to license or distribute it to anyone else except as part of a product or |
|
19 * program developed by the user. |
|
20 * |
|
21 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE |
|
22 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR |
|
23 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. |
|
24 * |
|
25 * Sun RPC is provided with no support and without any obligation on the |
|
26 * part of Sun Microsystems, Inc. to assist in its use, correction, |
|
27 * modification or enhancement. |
|
28 * |
|
29 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE |
|
30 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC |
|
31 * OR ANY PART THEREOF. |
|
32 * |
|
33 * In no event will Sun Microsystems, Inc. be liable for any lost revenue |
|
34 * or profits or other special, indirect and consequential damages, even if |
|
35 * Sun has been advised of the possibility of such damages. |
|
36 * |
|
37 * Sun Microsystems, Inc. |
|
38 * 2550 Garcia Avenue |
|
39 * Mountain View, California 94043 |
|
40 */ |
|
41 //#ifndef lint |
|
42 //static char sccsid[] = "@(#)rpc_parse.c 1.4 87/04/28 (C) 1987 SMI"; |
|
43 //#endif |
|
44 |
|
45 /* |
|
46 * rpc_parse.c, Parser for the RPC protocol compiler |
|
47 * Copyright (C) 1987 Sun Microsystems, Inc. |
|
48 */ |
|
49 #include <stdio.h> |
|
50 #include <stdlib.h> |
|
51 #include "rpc_util.h" |
|
52 #include "rpc_scan.h" |
|
53 #include "rpc_pars.h" |
|
54 |
|
55 /* prototypes */ |
|
56 static void get_declaration( declaration *dec, defkind dkind ); |
|
57 static void get_type( char **prefixp, char **typep, defkind dkind ); |
|
58 static void unsigned_dec( char **typep ); |
|
59 |
|
60 |
|
61 /* implementation */ |
|
62 static void |
|
63 isdefined(defp) |
|
64 definition *defp; |
|
65 { |
|
66 STOREVAL(&defined, defp); |
|
67 } |
|
68 |
|
69 |
|
70 static void |
|
71 def_struct(defp) |
|
72 definition *defp; |
|
73 { |
|
74 token tok; |
|
75 declaration dec; |
|
76 decl_list *decls; |
|
77 decl_list **tailp; |
|
78 |
|
79 defp->def_kind = DEF_STRUCT; |
|
80 |
|
81 scan(TOK_IDENT, &tok); |
|
82 defp->def_name = tok.str; |
|
83 scan(TOK_LBRACE, &tok); |
|
84 tailp = &defp->def.st.decls; |
|
85 do { |
|
86 get_declaration(&dec, DEF_STRUCT); |
|
87 decls = ALLOC(decl_list); |
|
88 decls->decl = dec; |
|
89 *tailp = decls; |
|
90 tailp = &decls->next; |
|
91 scan(TOK_SEMICOLON, &tok); |
|
92 peek(&tok); |
|
93 } while (tok.kind != TOK_RBRACE); |
|
94 get_token(&tok); |
|
95 *tailp = NULL; |
|
96 } |
|
97 |
|
98 static void |
|
99 def_program(defp) |
|
100 definition *defp; |
|
101 { |
|
102 token tok; |
|
103 version_list *vlist; |
|
104 version_list **vtailp; |
|
105 proc_list *plist; |
|
106 proc_list **ptailp; |
|
107 |
|
108 defp->def_kind = DEF_PROGRAM; |
|
109 scan(TOK_IDENT, &tok); |
|
110 defp->def_name = tok.str; |
|
111 scan(TOK_LBRACE, &tok); |
|
112 vtailp = &defp->def.pr.versions; |
|
113 scan(TOK_VERSION, &tok); |
|
114 do { |
|
115 scan(TOK_IDENT, &tok); |
|
116 vlist = ALLOC(version_list); |
|
117 vlist->vers_name = tok.str; |
|
118 scan(TOK_LBRACE, &tok); |
|
119 ptailp = &vlist->procs; |
|
120 do { |
|
121 plist = ALLOC(proc_list); |
|
122 plist->next = NULL; |
|
123 get_type(&plist->res_prefix, &plist->res_type, DEF_PROGRAM); |
|
124 if (streq(plist->res_type, "opaque")) { |
|
125 error("illegal result type"); |
|
126 } |
|
127 scan(TOK_IDENT, &tok); |
|
128 plist->proc_name = tok.str; |
|
129 scan(TOK_LPAREN, &tok); |
|
130 get_type(&plist->arg_prefix, &plist->arg_type, DEF_PROGRAM); |
|
131 if (streq(plist->arg_type, "opaque")) { |
|
132 error("illegal argument type"); |
|
133 } |
|
134 scan(TOK_RPAREN, &tok); |
|
135 scan(TOK_EQUAL, &tok); |
|
136 scan_num(&tok); |
|
137 scan(TOK_SEMICOLON, &tok); |
|
138 plist->proc_num = tok.str; |
|
139 *ptailp = plist; |
|
140 ptailp = &plist->next; |
|
141 peek(&tok); |
|
142 } while (tok.kind != TOK_RBRACE); |
|
143 *vtailp = vlist; |
|
144 vtailp = &vlist->next; |
|
145 scan(TOK_RBRACE, &tok); |
|
146 scan(TOK_EQUAL, &tok); |
|
147 scan_num(&tok); |
|
148 vlist->vers_num = tok.str; |
|
149 scan(TOK_SEMICOLON, &tok); |
|
150 scan2(TOK_VERSION, TOK_RBRACE, &tok); |
|
151 } while (tok.kind == TOK_VERSION); |
|
152 scan(TOK_EQUAL, &tok); |
|
153 scan_num(&tok); |
|
154 defp->def.pr.prog_num = tok.str; |
|
155 *vtailp = NULL; |
|
156 } |
|
157 |
|
158 static void |
|
159 def_enum(defp) |
|
160 definition *defp; |
|
161 { |
|
162 token tok; |
|
163 enumval_list *elist; |
|
164 enumval_list **tailp; |
|
165 |
|
166 defp->def_kind = DEF_ENUM; |
|
167 scan(TOK_IDENT, &tok); |
|
168 defp->def_name = tok.str; |
|
169 scan(TOK_LBRACE, &tok); |
|
170 tailp = &defp->def.en.vals; |
|
171 do { |
|
172 scan(TOK_IDENT, &tok); |
|
173 elist = ALLOC(enumval_list); |
|
174 elist->name = tok.str; |
|
175 elist->assignment = NULL; |
|
176 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); |
|
177 if (tok.kind == TOK_EQUAL) { |
|
178 scan_num(&tok); |
|
179 elist->assignment = tok.str; |
|
180 scan2(TOK_COMMA, TOK_RBRACE, &tok); |
|
181 } |
|
182 *tailp = elist; |
|
183 tailp = &elist->next; |
|
184 } while (tok.kind != TOK_RBRACE); |
|
185 *tailp = NULL; |
|
186 } |
|
187 |
|
188 static void |
|
189 def_const(defp) |
|
190 definition *defp; |
|
191 { |
|
192 token tok; |
|
193 defp->def_kind = DEF_CONST; |
|
194 scan(TOK_IDENT, &tok); |
|
195 defp->def_name = tok.str; |
|
196 scan(TOK_EQUAL, &tok); |
|
197 scan2(TOK_IDENT, TOK_STRCONST, &tok); |
|
198 defp->def.co = tok.str; |
|
199 } |
|
200 |
|
201 static void |
|
202 def_union(defp) |
|
203 definition *defp; |
|
204 { |
|
205 token tok; |
|
206 declaration dec; |
|
207 case_list *cases; |
|
208 case_list **tailp; |
|
209 |
|
210 defp->def_kind = DEF_UNION; |
|
211 scan(TOK_IDENT, &tok); |
|
212 defp->def_name = tok.str; |
|
213 scan(TOK_SWITCH, &tok); |
|
214 scan(TOK_LPAREN, &tok); |
|
215 get_declaration(&dec, DEF_UNION); |
|
216 defp->def.un.enum_decl = dec; |
|
217 tailp = &defp->def.un.cases; |
|
218 scan(TOK_RPAREN, &tok); |
|
219 scan(TOK_LBRACE, &tok); |
|
220 scan(TOK_CASE, &tok); |
|
221 while (tok.kind == TOK_CASE) { |
|
222 scan(TOK_IDENT, &tok); |
|
223 cases = ALLOC(case_list); |
|
224 cases->case_name = tok.str; |
|
225 scan(TOK_COLON, &tok); |
|
226 get_declaration(&dec, DEF_UNION); |
|
227 cases->case_decl = dec; |
|
228 *tailp = cases; |
|
229 tailp = &cases->next; |
|
230 scan(TOK_SEMICOLON, &tok); |
|
231 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); |
|
232 } |
|
233 *tailp = NULL; |
|
234 if (tok.kind == TOK_DEFAULT) { |
|
235 scan(TOK_COLON, &tok); |
|
236 get_declaration(&dec, DEF_UNION); |
|
237 defp->def.un.default_decl = ALLOC(declaration); |
|
238 *defp->def.un.default_decl = dec; |
|
239 scan(TOK_SEMICOLON, &tok); |
|
240 scan(TOK_RBRACE, &tok); |
|
241 } else { |
|
242 defp->def.un.default_decl = NULL; |
|
243 } |
|
244 } |
|
245 |
|
246 |
|
247 static void |
|
248 def_typedef(defp) |
|
249 definition *defp; |
|
250 { |
|
251 declaration dec; |
|
252 |
|
253 defp->def_kind = DEF_TYPEDEF; |
|
254 get_declaration(&dec, DEF_TYPEDEF); |
|
255 defp->def_name = dec.name; |
|
256 defp->def.ty.old_prefix = dec.prefix; |
|
257 defp->def.ty.old_type = dec.type; |
|
258 defp->def.ty.rel = dec.rel; |
|
259 defp->def.ty.array_max = dec.array_max; |
|
260 } |
|
261 |
|
262 |
|
263 static void |
|
264 get_declaration(dec, dkind) |
|
265 declaration *dec; |
|
266 defkind dkind; |
|
267 { |
|
268 token tok; |
|
269 |
|
270 get_type(&dec->prefix, &dec->type, dkind); |
|
271 dec->rel = REL_ALIAS; |
|
272 if (streq(dec->type, "void")) { |
|
273 return; |
|
274 } |
|
275 scan2(TOK_STAR, TOK_IDENT, &tok); |
|
276 if (tok.kind == TOK_STAR) { |
|
277 dec->rel = REL_POINTER; |
|
278 scan(TOK_IDENT, &tok); |
|
279 } |
|
280 dec->name = tok.str; |
|
281 if (peekscan(TOK_LBRACKET, &tok)) { |
|
282 if (dec->rel == REL_POINTER) { |
|
283 error("no array-of-pointer declarations -- use typedef"); |
|
284 } |
|
285 dec->rel = REL_VECTOR; |
|
286 scan_num(&tok); |
|
287 dec->array_max = tok.str; |
|
288 scan(TOK_RBRACKET, &tok); |
|
289 } else if (peekscan(TOK_LANGLE, &tok)) { |
|
290 if (dec->rel == REL_POINTER) { |
|
291 error("no array-of-pointer declarations -- use typedef"); |
|
292 } |
|
293 dec->rel = REL_ARRAY; |
|
294 if (peekscan(TOK_RANGLE, &tok)) { |
|
295 dec->array_max = "~0"; /* unspecified size, use max */ |
|
296 } else { |
|
297 scan_num(&tok); |
|
298 dec->array_max = tok.str; |
|
299 scan(TOK_RANGLE, &tok); |
|
300 } |
|
301 } |
|
302 if (streq(dec->type, "opaque")) { |
|
303 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { |
|
304 error("array declaration expected"); |
|
305 } |
|
306 } else if (streq(dec->type, "string")) { |
|
307 if (dec->rel != REL_ARRAY) { |
|
308 error("variable-length array declaration expected"); |
|
309 } |
|
310 } |
|
311 } |
|
312 |
|
313 |
|
314 static void |
|
315 get_type(prefixp, typep, dkind) |
|
316 char **prefixp; |
|
317 char **typep; |
|
318 defkind dkind; |
|
319 { |
|
320 token tok; |
|
321 |
|
322 *prefixp = NULL; |
|
323 get_token(&tok); |
|
324 switch (tok.kind) { |
|
325 case TOK_IDENT: |
|
326 *typep = tok.str; |
|
327 break; |
|
328 case TOK_STRUCT: |
|
329 case TOK_ENUM: |
|
330 case TOK_UNION: |
|
331 *prefixp = tok.str; |
|
332 scan(TOK_IDENT, &tok); |
|
333 *typep = tok.str; |
|
334 break; |
|
335 case TOK_UNSIGNED: |
|
336 unsigned_dec(typep); |
|
337 break; |
|
338 case TOK_SHORT: |
|
339 *typep = "short"; |
|
340 (void) peekscan(TOK_INT, &tok); |
|
341 break; |
|
342 case TOK_LONG: |
|
343 *typep = "long"; |
|
344 (void) peekscan(TOK_INT, &tok); |
|
345 break; |
|
346 case TOK_VOID: |
|
347 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { |
|
348 error("voids allowed only inside union and program definitions"); |
|
349 } |
|
350 *typep = tok.str; |
|
351 break; |
|
352 case TOK_STRING: |
|
353 case TOK_OPAQUE: |
|
354 case TOK_CHAR: |
|
355 case TOK_INT: |
|
356 case TOK_FLOAT: |
|
357 case TOK_DOUBLE: |
|
358 case TOK_BOOL: |
|
359 *typep = tok.str; |
|
360 break; |
|
361 default: |
|
362 error("expected type specifier"); |
|
363 } |
|
364 } |
|
365 |
|
366 |
|
367 static void |
|
368 unsigned_dec(typep) |
|
369 char **typep; |
|
370 { |
|
371 token tok; |
|
372 |
|
373 peek(&tok); |
|
374 switch (tok.kind) { |
|
375 case TOK_CHAR: |
|
376 get_token(&tok); |
|
377 *typep = "u_char"; |
|
378 break; |
|
379 case TOK_SHORT: |
|
380 get_token(&tok); |
|
381 *typep = "u_short"; |
|
382 (void) peekscan(TOK_INT, &tok); |
|
383 break; |
|
384 case TOK_LONG: |
|
385 get_token(&tok); |
|
386 *typep = "u_long"; |
|
387 (void) peekscan(TOK_INT, &tok); |
|
388 break; |
|
389 case TOK_INT: |
|
390 get_token(&tok); |
|
391 *typep = "u_int"; |
|
392 break; |
|
393 default: |
|
394 *typep = "u_int"; |
|
395 break; |
|
396 } |
|
397 } |
|
398 |
|
399 |
|
400 /* |
|
401 * return the next definition you see |
|
402 */ |
|
403 definition * |
|
404 get_definition() |
|
405 { |
|
406 definition *defp; |
|
407 token tok; |
|
408 |
|
409 defp = ALLOC(definition); |
|
410 get_token(&tok); |
|
411 switch (tok.kind) { |
|
412 case TOK_STRUCT: |
|
413 def_struct(defp); |
|
414 break; |
|
415 case TOK_UNION: |
|
416 def_union(defp); |
|
417 break; |
|
418 case TOK_TYPEDEF: |
|
419 def_typedef(defp); |
|
420 break; |
|
421 case TOK_ENUM: |
|
422 def_enum(defp); |
|
423 break; |
|
424 case TOK_PROGRAM: |
|
425 def_program(defp); |
|
426 break; |
|
427 case TOK_CONST: |
|
428 def_const(defp); |
|
429 break; |
|
430 case TOK_EOF: |
|
431 return (NULL); |
|
432 break; |
|
433 default: |
|
434 error("definition keyword expected"); |
|
435 } |
|
436 scan(TOK_SEMICOLON, &tok); |
|
437 isdefined(defp); |
|
438 return (defp); |
|
439 } |