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