rpc_parse.c revision 1.16.6.1 1 /* $NetBSD: rpc_parse.c,v 1.16.6.1 2014/05/22 11:42:49 yamt 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.16.6.1 2014/05/22 11:42:49 yamt 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 *
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("definition keyword expected");
107 }
108 scan(TOK_SEMICOLON, &tok);
109 isdefined(defp);
110 return (defp);
111 }
112
113 static void
114 isdefined(definition *defp)
115 {
116 STOREVAL(&defined, defp);
117 }
118
119 static void
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
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_STURCT 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
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
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
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
377 check_type_name(const char *name, int new_type)
378 {
379 int i;
380 char tmp[100];
381
382 for (i = 0; reserved_words[i] != NULL; i++) {
383 if (strcmp(name, reserved_words[i]) == 0) {
384 sprintf(tmp,
385 "illegal (reserved) name :\'%s\' in type definition", name);
386 error(tmp);
387 }
388 }
389 if (new_type) {
390 for (i = 0; reserved_types[i] != NULL; i++) {
391 if (strcmp(name, reserved_types[i]) == 0) {
392 sprintf(tmp,
393 "illegal (reserved) name :\'%s\' in type definition", name);
394 error(tmp);
395 }
396 }
397 }
398 }
399
400 static void
401 def_typedef(definition *defp)
402 {
403 declaration dec;
404
405 defp->def_kind = DEF_TYPEDEF;
406 get_declaration(&dec, DEF_TYPEDEF);
407 defp->def_name = dec.name;
408 check_type_name(dec.name, 1);
409 defp->def.ty.old_prefix = dec.prefix;
410 defp->def.ty.old_type = dec.type;
411 defp->def.ty.rel = dec.rel;
412 defp->def.ty.array_max = dec.array_max;
413 }
414
415 static void
416 get_declaration(declaration *dec, defkind dkind)
417 {
418 token tok;
419
420 get_type(&dec->prefix, &dec->type, dkind);
421 dec->rel = REL_ALIAS;
422 if (streq(dec->type, "void")) {
423 return;
424 }
425 check_type_name(dec->type, 0);
426
427 scan2(TOK_STAR, TOK_IDENT, &tok);
428 if (tok.kind == TOK_STAR) {
429 dec->rel = REL_POINTER;
430 scan(TOK_IDENT, &tok);
431 }
432 dec->name = tok.str;
433 if (peekscan(TOK_LBRACKET, &tok)) {
434 if (dec->rel == REL_POINTER) {
435 error("no array-of-pointer declarations -- use typedef");
436 }
437 dec->rel = REL_VECTOR;
438 scan_num(&tok);
439 dec->array_max = tok.str;
440 scan(TOK_RBRACKET, &tok);
441 } else
442 if (peekscan(TOK_LANGLE, &tok)) {
443 if (dec->rel == REL_POINTER) {
444 error("no array-of-pointer declarations -- use typedef");
445 }
446 dec->rel = REL_ARRAY;
447 if (peekscan(TOK_RANGLE, &tok)) {
448 dec->array_max = "(u_int)~0";
449 /* unspecified size, use * max */
450 } else {
451 scan_num(&tok);
452 dec->array_max = tok.str;
453 scan(TOK_RANGLE, &tok);
454 }
455 }
456 if (streq(dec->type, "opaque")) {
457 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
458 error("array declaration expected");
459 }
460 } else
461 if (streq(dec->type, "string")) {
462 if (dec->rel != REL_ARRAY) {
463 error("variable-length array declaration expected");
464 }
465 }
466 }
467
468 static void
469 get_prog_declaration(declaration *dec, defkind dkind, int num /* arg number */)
470 {
471 token tok;
472 char name[255]; /* argument name */
473
474 if (dkind == DEF_PROGRAM) {
475 peek(&tok);
476 if (tok.kind == TOK_RPAREN) { /* no arguments */
477 dec->rel = REL_ALIAS;
478 dec->type = "void";
479 dec->prefix = NULL;
480 dec->name = NULL;
481 return;
482 }
483 }
484 get_type(&dec->prefix, &dec->type, dkind);
485 dec->rel = REL_ALIAS;
486 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
487 strcpy(name, tok.str);
488 else
489 sprintf(name, "%s%d", ARGNAME, num); /* default name of
490 * argument */
491
492 dec->name = (char *) strdup(name);
493
494 if (streq(dec->type, "void")) {
495 return;
496 }
497 if (streq(dec->type, "opaque")) {
498 error("opaque -- illegal argument type");
499 }
500 if (peekscan(TOK_STAR, &tok)) {
501 if (streq(dec->type, "string")) {
502 error("pointer to string not allowed in program arguments\n");
503 }
504 dec->rel = REL_POINTER;
505 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
506 dec->name = (char *) strdup(tok.str);
507 }
508 if (peekscan(TOK_LANGLE, &tok)) {
509 if (!streq(dec->type, "string")) {
510 error("arrays cannot be declared as arguments to procedures -- use typedef");
511 }
512 dec->rel = REL_ARRAY;
513 if (peekscan(TOK_RANGLE, &tok)) {
514 dec->array_max = "(u_int)~0";
515 /* unspecified size, use max */
516 } else {
517 scan_num(&tok);
518 dec->array_max = tok.str;
519 scan(TOK_RANGLE, &tok);
520 }
521 }
522 if (streq(dec->type, "string")) {
523 if (dec->rel != REL_ARRAY) { /* .x specifies just string as
524 * type of argument - make it
525 * string<> */
526 dec->rel = REL_ARRAY;
527 dec->array_max = "(u_int)~0";
528 /* unspecified size, use max */
529 }
530 }
531 }
532
533
534
535 static void
536 get_type(const char **prefixp, const char **typep, defkind dkind)
537 {
538 token tok;
539
540 *prefixp = NULL;
541 get_token(&tok);
542 switch (tok.kind) {
543 case TOK_IDENT:
544 *typep = tok.str;
545 break;
546 case TOK_STRUCT:
547 case TOK_ENUM:
548 case TOK_UNION:
549 *prefixp = tok.str;
550 scan(TOK_IDENT, &tok);
551 *typep = tok.str;
552 break;
553 case TOK_UNSIGNED:
554 unsigned_dec(typep);
555 break;
556 case TOK_SHORT:
557 *typep = "short";
558 (void) peekscan(TOK_INT, &tok);
559 break;
560 case TOK_LONG:
561 *typep = "long";
562 (void) peekscan(TOK_INT, &tok);
563 break;
564 case TOK_HYPER:
565 *typep = "longlong_t";
566 (void) peekscan(TOK_INT, &tok);
567 break;
568 case TOK_VOID:
569 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
570 error("voids allowed only inside union and program definitions with one argument");
571 }
572 *typep = tok.str;
573 break;
574 case TOK_STRING:
575 case TOK_OPAQUE:
576 case TOK_CHAR:
577 case TOK_INT:
578 case TOK_FLOAT:
579 case TOK_DOUBLE:
580 case TOK_BOOL:
581 case TOK_QUAD:
582 *typep = tok.str;
583 break;
584 default:
585 error("expected type specifier");
586 }
587 }
588
589 static void
590 unsigned_dec(const char **typep)
591 {
592 token tok;
593
594 peek(&tok);
595 switch (tok.kind) {
596 case TOK_CHAR:
597 get_token(&tok);
598 *typep = "u_char";
599 break;
600 case TOK_SHORT:
601 get_token(&tok);
602 *typep = "u_short";
603 (void) peekscan(TOK_INT, &tok);
604 break;
605 case TOK_LONG:
606 get_token(&tok);
607 *typep = "u_long";
608 (void) peekscan(TOK_INT, &tok);
609 break;
610 case TOK_HYPER:
611 get_token(&tok);
612 *typep = "u_longlong_t";
613 (void) peekscan(TOK_INT, &tok);
614 break;
615 case TOK_INT:
616 get_token(&tok);
617 *typep = "u_int";
618 break;
619 default:
620 *typep = "u_int";
621 break;
622 }
623 }
624