1 /* $NetBSD: rpc_parse.c,v 1.23 2022/01/11 22:45:56 andvar Exp $ */
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 or with the express written consent of
9 * Sun Microsystems, Inc.
10 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
18 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
22 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
26 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California 94043
30 */
31
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
35
36 #include <sys/cdefs.h>
37 #if defined(__RCSID) && !defined(lint)
38 #if 0
39 static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
40 #else
41 __RCSID("$NetBSD: rpc_parse.c,v 1.23 2022/01/11 22:45:56 andvar Exp $");
42 #endif
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 <string.h>
52 #include "rpc/types.h"
53 #include "rpc_scan.h"
54 #include "rpc_parse.h"
55 #include "rpc_util.h"
56
57 #define ARGNAME "arg"
58
59 static void isdefined(definition *);
60 static void def_struct(definition *);
61 static void def_program(definition *);
62 static void def_enum(definition *);
63 static void def_const(definition *);
64 static void def_union(definition *);
65 static void check_type_name(const char *, int);
66 static void def_typedef(definition *);
67 static void get_declaration(declaration *, defkind);
68 static void get_prog_declaration(declaration *, defkind, int);
69 static void get_type(const char **, const char **, defkind);
70 static void unsigned_dec(const char **);
71
72 /*
73 * return the next definition you see
74 */
75 definition *
get_definition(void)76 get_definition(void)
77 {
78 definition *defp;
79 token tok;
80
81 defp = ALLOC(definition);
82 get_token(&tok);
83 switch (tok.kind) {
84 case TOK_STRUCT:
85 def_struct(defp);
86 break;
87 case TOK_UNION:
88 def_union(defp);
89 break;
90 case TOK_TYPEDEF:
91 def_typedef(defp);
92 break;
93 case TOK_ENUM:
94 def_enum(defp);
95 break;
96 case TOK_PROGRAM:
97 def_program(defp);
98 break;
99 case TOK_CONST:
100 def_const(defp);
101 break;
102 case TOK_EOF:
103 free(defp);
104 return (NULL);
105 default:
106 error("Expected definition keyword");
107 }
108 scan(TOK_SEMICOLON, &tok);
109 isdefined(defp);
110 return (defp);
111 }
112
113 static void
isdefined(definition * defp)114 isdefined(definition *defp)
115 {
116 STOREVAL(&defined, defp);
117 }
118
119 static void
def_struct(definition * defp)120 def_struct(definition *defp)
121 {
122 token tok;
123 declaration dec;
124 decl_list *decls;
125 decl_list **tailp;
126
127 defp->def_kind = DEF_STRUCT;
128
129 scan(TOK_IDENT, &tok);
130 defp->def_name = tok.str;
131 scan(TOK_LBRACE, &tok);
132 tailp = &defp->def.st.decls;
133 do {
134 get_declaration(&dec, DEF_STRUCT);
135 decls = ALLOC(decl_list);
136 decls->decl = dec;
137 *tailp = decls;
138 tailp = &decls->next;
139 scan(TOK_SEMICOLON, &tok);
140 peek(&tok);
141 } while (tok.kind != TOK_RBRACE);
142 get_token(&tok);
143 *tailp = NULL;
144 }
145
146 static void
def_program(definition * defp)147 def_program(definition *defp)
148 {
149 token tok;
150 declaration dec;
151 decl_list *decls;
152 decl_list **tailp;
153 version_list *vlist;
154 version_list **vtailp;
155 proc_list *plist;
156 proc_list **ptailp;
157 int num_args;
158 bool_t isvoid = FALSE; /* whether first argument is void */
159 defp->def_kind = DEF_PROGRAM;
160 scan(TOK_IDENT, &tok);
161 defp->def_name = tok.str;
162 scan(TOK_LBRACE, &tok);
163 vtailp = &defp->def.pr.versions;
164 tailp = &defp->def.st.decls;
165 scan(TOK_VERSION, &tok);
166 do {
167 scan(TOK_IDENT, &tok);
168 vlist = ALLOC(version_list);
169 vlist->vers_name = tok.str;
170 scan(TOK_LBRACE, &tok);
171 ptailp = &vlist->procs;
172 do {
173 /* get result type */
174 plist = ALLOC(proc_list);
175 get_type(&plist->res_prefix, &plist->res_type,
176 DEF_PROGRAM);
177 if (streq(plist->res_type, "opaque")) {
178 error("Illegal result type");
179 }
180 scan(TOK_IDENT, &tok);
181 plist->proc_name = tok.str;
182 scan(TOK_LPAREN, &tok);
183 /* get args - first one */
184 num_args = 1;
185 isvoid = FALSE;
186 /* type of DEF_PROGRAM in the first
187 * get_prog_declaration and DEF_STRUCT in the next
188 * allows void as argument if it is the only argument */
189 get_prog_declaration(&dec, DEF_PROGRAM, num_args);
190 if (streq(dec.type, "void"))
191 isvoid = TRUE;
192 decls = ALLOC(decl_list);
193 plist->args.decls = decls;
194 decls->decl = dec;
195 tailp = &decls->next;
196 /* get args */
197 while (peekscan(TOK_COMMA, &tok)) {
198 num_args++;
199 get_prog_declaration(&dec, DEF_STRUCT,
200 num_args);
201 decls = ALLOC(decl_list);
202 decls->decl = dec;
203 *tailp = decls;
204 if (streq(dec.type, "void"))
205 isvoid = TRUE;
206 tailp = &decls->next;
207 }
208 /* multiple arguments are only allowed in newstyle */
209 if (!newstyle && num_args > 1) {
210 error("Only one argument is allowed");
211 }
212 if (isvoid && num_args > 1) {
213 error("Illegal use of void in program definition");
214 }
215 *tailp = NULL;
216 scan(TOK_RPAREN, &tok);
217 scan(TOK_EQUAL, &tok);
218 scan_num(&tok);
219 scan(TOK_SEMICOLON, &tok);
220 plist->proc_num = tok.str;
221 plist->arg_num = num_args;
222 *ptailp = plist;
223 ptailp = &plist->next;
224 peek(&tok);
225 } while (tok.kind != TOK_RBRACE);
226 *ptailp = NULL;
227 *vtailp = vlist;
228 vtailp = &vlist->next;
229 scan(TOK_RBRACE, &tok);
230 scan(TOK_EQUAL, &tok);
231 scan_num(&tok);
232 vlist->vers_num = tok.str;
233 /* make the argument structure name for each arg */
234 for (plist = vlist->procs; plist != NULL;
235 plist = plist->next) {
236 plist->args.argname = make_argname(plist->proc_name,
237 vlist->vers_num);
238 /* free the memory ?? */
239 }
240 scan(TOK_SEMICOLON, &tok);
241 scan2(TOK_VERSION, TOK_RBRACE, &tok);
242 } while (tok.kind == TOK_VERSION);
243 scan(TOK_EQUAL, &tok);
244 scan_num(&tok);
245 defp->def.pr.prog_num = tok.str;
246 *vtailp = NULL;
247 }
248
249
250 static void
def_enum(definition * defp)251 def_enum(definition *defp)
252 {
253 token tok;
254 enumval_list *elist;
255 enumval_list **tailp;
256
257 defp->def_kind = DEF_ENUM;
258 scan(TOK_IDENT, &tok);
259 defp->def_name = tok.str;
260 scan(TOK_LBRACE, &tok);
261 tailp = &defp->def.en.vals;
262 do {
263 scan(TOK_IDENT, &tok);
264 elist = ALLOC(enumval_list);
265 elist->name = tok.str;
266 elist->assignment = NULL;
267 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
268 if (tok.kind == TOK_EQUAL) {
269 scan_num(&tok);
270 elist->assignment = tok.str;
271 scan2(TOK_COMMA, TOK_RBRACE, &tok);
272 }
273 *tailp = elist;
274 tailp = &elist->next;
275 } while (tok.kind != TOK_RBRACE);
276 *tailp = NULL;
277 }
278
279 static void
def_const(definition * defp)280 def_const(definition *defp)
281 {
282 token tok;
283
284 defp->def_kind = DEF_CONST;
285 scan(TOK_IDENT, &tok);
286 defp->def_name = tok.str;
287 scan(TOK_EQUAL, &tok);
288 scan2(TOK_IDENT, TOK_STRCONST, &tok);
289 defp->def.co = tok.str;
290 }
291
292 static void
def_union(definition * defp)293 def_union(definition *defp)
294 {
295 token tok;
296 declaration dec;
297 case_list *cases;
298 case_list **tailp;
299
300 defp->def_kind = DEF_UNION;
301 scan(TOK_IDENT, &tok);
302 defp->def_name = tok.str;
303 scan(TOK_SWITCH, &tok);
304 scan(TOK_LPAREN, &tok);
305 get_declaration(&dec, DEF_UNION);
306 defp->def.un.enum_decl = dec;
307 tailp = &defp->def.un.cases;
308 scan(TOK_RPAREN, &tok);
309 scan(TOK_LBRACE, &tok);
310 scan(TOK_CASE, &tok);
311 while (tok.kind == TOK_CASE) {
312 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
313 cases = ALLOC(case_list);
314 cases->case_name = tok.str;
315 scan(TOK_COLON, &tok);
316 /* now peek at next token */
317 if (peekscan(TOK_CASE, &tok)) {
318
319 do {
320 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
321 cases->contflag = 1; /* continued case
322 * statement */
323 *tailp = cases;
324 tailp = &cases->next;
325 cases = ALLOC(case_list);
326 cases->case_name = tok.str;
327 scan(TOK_COLON, &tok);
328
329 } while (peekscan(TOK_CASE, &tok));
330 }
331 get_declaration(&dec, DEF_UNION);
332 cases->case_decl = dec;
333 cases->contflag = 0; /* no continued case statement */
334 *tailp = cases;
335 tailp = &cases->next;
336 scan(TOK_SEMICOLON, &tok);
337
338 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
339 }
340 *tailp = NULL;
341 if (tok.kind == TOK_DEFAULT) {
342 scan(TOK_COLON, &tok);
343 get_declaration(&dec, DEF_UNION);
344 defp->def.un.default_decl = ALLOC(declaration);
345 *defp->def.un.default_decl = dec;
346 scan(TOK_SEMICOLON, &tok);
347 scan(TOK_RBRACE, &tok);
348 } else {
349 defp->def.un.default_decl = NULL;
350 }
351 }
352
353 static const char *const reserved_words[] = {
354 "array",
355 "bytes",
356 "destroy",
357 "free",
358 "getpos",
359 "inline",
360 "pointer",
361 "reference",
362 "setpos",
363 "sizeof",
364 "union",
365 "vector",
366 NULL
367 };
368
369 static const char *const reserved_types[] = {
370 "opaque",
371 "string",
372 NULL
373 };
374 /* check that the given name is not one that would eventually result in
375 xdr routines that would conflict with internal XDR routines. */
376 static void
check_type_name(const char * name,int new_type)377 check_type_name(const char *name, int new_type)
378 {
379 int i;
380
381 for (i = 0; reserved_words[i] != NULL; i++) {
382 if (strcmp(name, reserved_words[i]) == 0) {
383 error("Illegal (reserved) name '%s' in type definition", name);
384 }
385 }
386 if (new_type) {
387 for (i = 0; reserved_types[i] != NULL; i++) {
388 if (strcmp(name, reserved_types[i]) == 0) {
389 error("Illegal (reserved) name '%s' in type definition", name);
390 }
391 }
392 }
393 }
394
395 static void
def_typedef(definition * defp)396 def_typedef(definition *defp)
397 {
398 declaration dec;
399
400 defp->def_kind = DEF_TYPEDEF;
401 get_declaration(&dec, DEF_TYPEDEF);
402 defp->def_name = dec.name;
403 check_type_name(dec.name, 1);
404 defp->def.ty.old_prefix = dec.prefix;
405 defp->def.ty.old_type = dec.type;
406 defp->def.ty.rel = dec.rel;
407 defp->def.ty.array_max = dec.array_max;
408 }
409
410 static void
get_declaration(declaration * dec,defkind dkind)411 get_declaration(declaration *dec, defkind dkind)
412 {
413 token tok;
414
415 get_type(&dec->prefix, &dec->type, dkind);
416 dec->rel = REL_ALIAS;
417 if (streq(dec->type, "void")) {
418 return;
419 }
420 check_type_name(dec->type, 0);
421
422 scan2(TOK_STAR, TOK_IDENT, &tok);
423 if (tok.kind == TOK_STAR) {
424 dec->rel = REL_POINTER;
425 scan(TOK_IDENT, &tok);
426 }
427 dec->name = tok.str;
428 if (peekscan(TOK_LBRACKET, &tok)) {
429 if (dec->rel == REL_POINTER) {
430 error("No array-of-pointer declarations -- use typedef");
431 }
432 dec->rel = REL_VECTOR;
433 scan_num(&tok);
434 dec->array_max = tok.str;
435 scan(TOK_RBRACKET, &tok);
436 } else
437 if (peekscan(TOK_LANGLE, &tok)) {
438 if (dec->rel == REL_POINTER) {
439 error("No array-of-pointer declarations -- use typedef");
440 }
441 dec->rel = REL_ARRAY;
442 if (peekscan(TOK_RANGLE, &tok)) {
443 dec->array_max = "(unsigned int)~0";
444 /* unspecified size, use * max */
445 } else {
446 scan_num(&tok);
447 dec->array_max = tok.str;
448 scan(TOK_RANGLE, &tok);
449 }
450 }
451 if (streq(dec->type, "opaque")) {
452 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
453 error("Array declaration expected");
454 }
455 } else
456 if (streq(dec->type, "string")) {
457 if (dec->rel != REL_ARRAY) {
458 error("Variable-length array declaration expected");
459 }
460 }
461 }
462
463 static void
get_prog_declaration(declaration * dec,defkind dkind,int num)464 get_prog_declaration(declaration *dec, defkind dkind, int num /* arg number */)
465 {
466 token tok;
467 char name[255]; /* argument name */
468
469 if (dkind == DEF_PROGRAM) {
470 peek(&tok);
471 if (tok.kind == TOK_RPAREN) { /* no arguments */
472 dec->rel = REL_ALIAS;
473 dec->type = "void";
474 dec->prefix = NULL;
475 dec->name = NULL;
476 return;
477 }
478 }
479 get_type(&dec->prefix, &dec->type, dkind);
480 dec->rel = REL_ALIAS;
481 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
482 strcpy(name, tok.str);
483 else
484 sprintf(name, "%s%d", ARGNAME, num); /* default name of
485 * argument */
486
487 dec->name = strdup(name);
488
489 if (streq(dec->type, "void")) {
490 return;
491 }
492 if (streq(dec->type, "opaque")) {
493 error("Opaque -- illegal argument type");
494 }
495 if (peekscan(TOK_STAR, &tok)) {
496 if (streq(dec->type, "string")) {
497 error("Pointer to string not allowed in program arguments\n");
498 }
499 dec->rel = REL_POINTER;
500 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
501 dec->name = strdup(tok.str);
502 }
503 if (peekscan(TOK_LANGLE, &tok)) {
504 if (!streq(dec->type, "string")) {
505 error("Arrays cannot be declared as arguments to procedures -- use typedef");
506 }
507 dec->rel = REL_ARRAY;
508 if (peekscan(TOK_RANGLE, &tok)) {
509 dec->array_max = "(unsigned int)~0";
510 /* unspecified size, use max */
511 } else {
512 scan_num(&tok);
513 dec->array_max = tok.str;
514 scan(TOK_RANGLE, &tok);
515 }
516 }
517 if (streq(dec->type, "string")) {
518 if (dec->rel != REL_ARRAY) { /* .x specifies just string as
519 * type of argument - make it
520 * string<> */
521 dec->rel = REL_ARRAY;
522 dec->array_max = "(unsigned int)~0";
523 /* unspecified size, use max */
524 }
525 }
526 }
527
528
529
530 static void
get_type(const char ** prefixp,const char ** typep,defkind dkind)531 get_type(const char **prefixp, const char **typep, defkind dkind)
532 {
533 token tok;
534
535 *prefixp = NULL;
536 get_token(&tok);
537 switch (tok.kind) {
538 case TOK_IDENT:
539 *typep = tok.str;
540 break;
541 case TOK_STRUCT:
542 case TOK_ENUM:
543 case TOK_UNION:
544 *prefixp = tok.str;
545 scan(TOK_IDENT, &tok);
546 *typep = tok.str;
547 break;
548 case TOK_UNSIGNED:
549 unsigned_dec(typep);
550 break;
551 case TOK_SHORT:
552 *typep = "short";
553 (void) peekscan(TOK_INT, &tok);
554 break;
555 case TOK_LONG:
556 *typep = "long";
557 (void) peekscan(TOK_INT, &tok);
558 break;
559 case TOK_HYPER:
560 *typep = "longlong_t";
561 (void) peekscan(TOK_INT, &tok);
562 break;
563 case TOK_VOID:
564 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
565 error("Void is allowed only inside union and program definitions with one argument");
566 }
567 *typep = tok.str;
568 break;
569 case TOK_STRING:
570 case TOK_OPAQUE:
571 case TOK_CHAR:
572 case TOK_INT:
573 case TOK_FLOAT:
574 case TOK_DOUBLE:
575 case TOK_BOOL:
576 case TOK_QUAD:
577 *typep = tok.str;
578 break;
579 default:
580 error("Type specifier expected");
581 }
582 }
583
584 static void
unsigned_dec(const char ** typep)585 unsigned_dec(const char **typep)
586 {
587 token tok;
588
589 peek(&tok);
590 switch (tok.kind) {
591 case TOK_CHAR:
592 get_token(&tok);
593 *typep = "u_char";
594 break;
595 case TOK_SHORT:
596 get_token(&tok);
597 *typep = "u_short";
598 (void) peekscan(TOK_INT, &tok);
599 break;
600 case TOK_LONG:
601 get_token(&tok);
602 *typep = "u_long";
603 (void) peekscan(TOK_INT, &tok);
604 break;
605 case TOK_HYPER:
606 get_token(&tok);
607 *typep = "u_longlong_t";
608 (void) peekscan(TOK_INT, &tok);
609 break;
610 case TOK_INT:
611 get_token(&tok);
612 *typep = "u_int";
613 break;
614 default:
615 *typep = "u_int";
616 break;
617 }
618 }
619