8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / rpcgen / rpc_parse.c
blob872f8002584cee0865a230a54257f8a342311674
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 * University Copyright- Copyright (c) 1982, 1986, 1988
30 * The Regents of the University of California
31 * All Rights Reserved
33 * University Acknowledgment- Portions of this document are derived from
34 * software developed by the University of California, Berkeley, and its
35 * contributors.
39 * rpc_parse.c, Parser for the RPC protocol compiler
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include "rpc/types.h"
45 #include "rpc_scan.h"
46 #include "rpc_parse.h"
47 #include "rpc_util.h"
49 #define ARGNAME "arg"
51 extern char *make_argname(char *, char *);
53 static void isdefined(definition *);
54 static void def_struct(definition *);
55 static void def_program(definition *);
56 static void def_enum(definition *);
57 static void def_const(definition *);
58 static void def_union(definition *);
59 static void def_typedef(definition *);
60 static void get_declaration(declaration *, defkind);
61 static void get_prog_declaration(declaration *, defkind, int);
62 static void get_type(char **, char **, defkind);
63 static void unsigned_dec(char **);
66 * return the next definition you see
68 definition *
69 get_definition(void)
71 definition *defp;
72 token tok;
74 defp = calloc(1, sizeof (definition));
75 get_token(&tok);
76 switch (tok.kind) {
77 case TOK_STRUCT:
78 def_struct(defp);
79 break;
80 case TOK_UNION:
81 def_union(defp);
82 break;
83 case TOK_TYPEDEF:
84 def_typedef(defp);
85 break;
86 case TOK_ENUM:
87 def_enum(defp);
88 break;
89 case TOK_PROGRAM:
90 def_program(defp);
91 break;
92 case TOK_CONST:
93 def_const(defp);
94 break;
95 case TOK_EOF:
96 return (NULL);
97 default:
98 error("definition keyword expected");
100 scan(TOK_SEMICOLON, &tok);
101 isdefined(defp);
102 return (defp);
105 static void
106 isdefined(definition *defp)
108 STOREVAL(&defined, defp);
112 * We treat s == NULL the same as *s == '\0'
114 static int
115 streqn(const char *s1, const char *s2)
117 if (s1 == NULL)
118 s1 = "";
119 if (s2 == NULL)
120 s2 = "";
121 if (s1 == s2)
122 return (1);
124 return (strcmp(s1, s2) == 0);
127 static int
128 cmptype(definition *defp, char *type)
130 /* We only want typedef definitions */
131 if (streq(defp->def_name, type) && defp->def_kind == DEF_TYPEDEF)
132 return (1);
133 return (0);
136 static int
137 check_self_reference(const char *name, const declaration *decp, int first)
140 * Now check for the following special case if first is true:
142 * struct foo {
143 * ...
144 * foo *next;
145 * };
148 * In the above cases foo has not yet been entered in the type list,
149 * defined. So there is no typedef entry. The prefix in that case
150 * could be empty.
152 if (decp->rel == REL_POINTER &&
153 (streqn(decp->prefix, "struct") ||
154 (first && streqn(decp->prefix, ""))) &&
155 streqn(name, decp->type))
156 return (1);
157 return (0);
160 static int
161 is_self_reference(definition *defp, declaration *decp)
163 declaration current;
164 definition *dp;
166 if (check_self_reference(defp->def_name, decp, 1))
167 return (1);
170 * Check for valid declaration:
171 * Only prefixes allowed are none and struct.
172 * Only relations allowed are pointer or alias.
174 if (!streqn(decp->prefix, "struct") && !streqn(decp->prefix, ""))
175 return (0);
176 if (decp->rel != REL_POINTER && decp->rel != REL_ALIAS)
177 return (0);
179 current.rel = decp->rel;
180 current.prefix = decp->prefix;
181 current.type = decp->type;
182 current.name = decp->name;
183 decp = &current;
184 while (!check_self_reference(defp->def_name, decp, 0)) {
185 dp = FINDVAL(defined, decp->type, cmptype);
188 * Check if we found a definition.
190 if (dp == NULL)
191 return (0);
194 * Check for valid prefix. We eventually need to see one
195 * and only one struct.
197 if (streqn(decp->prefix, "")) {
199 * If the current declaration prefix in empty
200 * then the definition found must have an empty
201 * prefix or a struct prefix
203 if (!streqn(dp->def.ty.old_prefix, "") &&
204 !streqn(dp->def.ty.old_prefix, "struct"))
205 return (0);
206 } else if (streqn(decp->prefix, "struct") &&
207 !streqn(dp->def.ty.old_prefix, ""))
209 * if the current prefix is struct tne new prefix
210 * must be empty
212 return (0);
213 else if (!streqn(decp->prefix, "struct"))
214 /* Should never get here */
215 return (0);
218 * Check for valid relation. We need to see one and
219 * only one REL_POINTER. The only valid relation types
220 * are REL_POINTER and REL_ALIAS.
222 if (decp->rel == REL_POINTER && dp->def.ty.rel != REL_ALIAS)
223 return (0);
224 if (decp->rel == REL_ALIAS &&
225 (dp->def.ty.rel != REL_ALIAS &&
226 dp->def.ty.rel != REL_POINTER))
227 return (0);
228 if (decp->rel != REL_ALIAS && decp->rel != REL_POINTER)
229 /* Should never get here */
230 return (0);
232 /* Set up the current declaration */
233 if (streqn(decp->prefix, ""))
234 decp->prefix = dp->def.ty.old_prefix;
235 decp->type = dp->def.ty.old_type;
236 if (decp->rel == REL_ALIAS)
237 decp->rel = dp->def.ty.rel;
240 /* We have a self reference type */
241 return (1);
244 static void
245 def_struct(definition *defp)
247 token tok;
248 declaration dec;
249 decl_list *decls;
250 decl_list **tailp, *endp;
252 defp->def_kind = DEF_STRUCT;
254 scan(TOK_IDENT, &tok);
255 defp->def_name = tok.str;
256 scan(TOK_LBRACE, &tok);
257 tailp = &defp->def.st.decls;
258 defp->def.st.tail = NULL;
259 do {
260 get_declaration(&dec, DEF_STRUCT);
261 decls = calloc(1, sizeof (decl_list));
262 decls->decl = dec;
264 * Keep a referenct to the last declaration to check for
265 * tail recurrsion.
267 endp = *tailp = decls;
268 tailp = &decls->next;
269 scan(TOK_SEMICOLON, &tok);
270 peek(&tok);
271 } while (tok.kind != TOK_RBRACE);
272 *tailp = NULL;
274 * Check for tail recurse. If the last declaration refers to this
275 * structure then mark this stucture to convert the tail recursion
276 * to itteration.
278 defp->def.st.self_pointer = is_self_reference(defp, &endp->decl);
279 get_token(&tok);
280 defp->def.st.tail = endp;
283 static void
284 def_program(definition *defp)
286 token tok;
287 declaration dec;
288 decl_list *decls;
289 decl_list **tailp;
290 version_list *vlist;
291 version_list **vtailp;
292 proc_list *plist;
293 proc_list **ptailp;
294 int num_args;
295 bool_t isvoid = FALSE; /* whether first argument is void */
296 defp->def_kind = DEF_PROGRAM;
297 scan(TOK_IDENT, &tok);
298 defp->def_name = tok.str;
299 scan(TOK_LBRACE, &tok);
300 vtailp = &defp->def.pr.versions;
301 tailp = &defp->def.st.decls;
302 scan(TOK_VERSION, &tok);
303 do {
304 scan(TOK_IDENT, &tok);
305 vlist = calloc(1, sizeof (version_list));
306 vlist->vers_name = tok.str;
307 scan(TOK_LBRACE, &tok);
308 ptailp = &vlist->procs;
309 do {
310 /* get result type */
311 plist = calloc(1, sizeof (proc_list));
312 get_type(&plist->res_prefix, &plist->res_type,
313 DEF_RESULT);
314 if (streq(plist->res_type, "opaque")) {
315 error("illegal result type");
317 scan(TOK_IDENT, &tok);
318 plist->proc_name = tok.str;
319 scan(TOK_LPAREN, &tok);
320 /* get args - first one */
321 num_args = 1;
322 isvoid = FALSE;
324 * type of DEF_PROGRAM in the first
325 * get_prog_declaration and DEF_STURCT in the next
326 * allows void as argument if it is the only argument
328 get_prog_declaration(&dec, DEF_PROGRAM, num_args);
329 if (streq(dec.type, "void"))
330 isvoid = TRUE;
331 decls = calloc(1, sizeof (decl_list));
332 plist->args.decls = decls;
333 decls->decl = dec;
334 tailp = &decls->next;
335 /* get args */
336 while (peekscan(TOK_COMMA, &tok)) {
337 num_args++;
338 get_prog_declaration(&dec, DEF_STRUCT,
339 num_args);
340 decls = calloc(1, sizeof (decl_list));
341 decls->decl = dec;
342 *tailp = decls;
343 if (streq(dec.type, "void"))
344 isvoid = TRUE;
345 tailp = &decls->next;
347 /* multiple arguments are only allowed in newstyle */
348 if (!newstyle && num_args > 1) {
349 error("only one argument is allowed");
351 if (isvoid && num_args > 1) {
352 error("illegal use of void "
353 "in program definition");
355 *tailp = NULL;
356 scan(TOK_RPAREN, &tok);
357 scan(TOK_EQUAL, &tok);
358 scan_num(&tok);
359 scan(TOK_SEMICOLON, &tok);
360 plist->proc_num = tok.str;
361 plist->arg_num = num_args;
362 *ptailp = plist;
363 ptailp = &plist->next;
364 peek(&tok);
365 } while (tok.kind != TOK_RBRACE);
366 *ptailp = NULL;
367 *vtailp = vlist;
368 vtailp = &vlist->next;
369 scan(TOK_RBRACE, &tok);
370 scan(TOK_EQUAL, &tok);
371 scan_num(&tok);
372 vlist->vers_num = tok.str;
373 /* make the argument structure name for each arg */
374 for (plist = vlist->procs; plist != NULL; plist = plist->next) {
375 plist->args.argname = make_argname(plist->proc_name,
376 vlist->vers_num);
377 /* free the memory ?? */
379 scan(TOK_SEMICOLON, &tok);
380 scan2(TOK_VERSION, TOK_RBRACE, &tok);
381 } while (tok.kind == TOK_VERSION);
382 scan(TOK_EQUAL, &tok);
383 scan_num(&tok);
384 defp->def.pr.prog_num = tok.str;
385 *vtailp = NULL;
388 static void
389 def_enum(definition *defp)
391 token tok;
392 enumval_list *elist;
393 enumval_list **tailp;
395 defp->def_kind = DEF_ENUM;
396 scan(TOK_IDENT, &tok);
397 defp->def_name = tok.str;
398 scan(TOK_LBRACE, &tok);
399 tailp = &defp->def.en.vals;
400 do {
401 scan(TOK_IDENT, &tok);
402 elist = calloc(1, sizeof (enumval_list));
403 elist->name = tok.str;
404 elist->assignment = NULL;
405 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
406 if (tok.kind == TOK_EQUAL) {
407 scan_num(&tok);
408 elist->assignment = tok.str;
409 scan2(TOK_COMMA, TOK_RBRACE, &tok);
411 *tailp = elist;
412 tailp = &elist->next;
413 } while (tok.kind != TOK_RBRACE);
414 *tailp = NULL;
417 static void
418 def_const(definition *defp)
420 token tok;
422 defp->def_kind = DEF_CONST;
423 scan(TOK_IDENT, &tok);
424 defp->def_name = tok.str;
425 scan(TOK_EQUAL, &tok);
426 scan2(TOK_IDENT, TOK_STRCONST, &tok);
427 defp->def.co = tok.str;
430 static void
431 def_union(definition *defp)
433 token tok;
434 declaration dec;
435 case_list *cases;
436 case_list **tailp;
437 int flag;
439 defp->def_kind = DEF_UNION;
440 scan(TOK_IDENT, &tok);
441 defp->def_name = tok.str;
442 scan(TOK_SWITCH, &tok);
443 scan(TOK_LPAREN, &tok);
444 get_declaration(&dec, DEF_UNION);
445 defp->def.un.enum_decl = dec;
446 tailp = &defp->def.un.cases;
447 scan(TOK_RPAREN, &tok);
448 scan(TOK_LBRACE, &tok);
449 scan(TOK_CASE, &tok);
450 while (tok.kind == TOK_CASE) {
451 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
452 cases = calloc(1, sizeof (case_list));
453 cases->case_name = tok.str;
454 scan(TOK_COLON, &tok);
455 /* now peek at next token */
456 flag = 0;
457 if (peekscan(TOK_CASE, &tok)) {
458 do {
459 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
460 cases->contflag = 1;
461 /* continued case statement */
462 *tailp = cases;
463 tailp = &cases->next;
464 cases = calloc(1, sizeof (case_list));
465 cases->case_name = tok.str;
466 scan(TOK_COLON, &tok);
467 } while (peekscan(TOK_CASE, &tok));
468 } else if (flag) {
469 *tailp = cases;
470 tailp = &cases->next;
471 cases = calloc(1, sizeof (case_list));
474 get_declaration(&dec, DEF_UNION);
475 cases->case_decl = dec;
476 cases->contflag = 0; /* no continued case statement */
477 *tailp = cases;
478 tailp = &cases->next;
479 scan(TOK_SEMICOLON, &tok);
481 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
483 *tailp = NULL;
484 if (tok.kind == TOK_DEFAULT) {
485 scan(TOK_COLON, &tok);
486 get_declaration(&dec, DEF_UNION);
487 defp->def.un.default_decl = calloc(1, sizeof (declaration));
488 *defp->def.un.default_decl = dec;
489 scan(TOK_SEMICOLON, &tok);
490 scan(TOK_RBRACE, &tok);
491 } else {
492 defp->def.un.default_decl = NULL;
496 static char *reserved_words[] = {
497 "array",
498 "bytes",
499 "destroy",
500 "free",
501 "getpos",
502 "inline",
503 "pointer",
504 "reference",
505 "setpos",
506 "sizeof",
507 "union",
508 "vector",
509 NULL
512 static char *reserved_types[] = {
513 "opaque",
514 "string",
515 NULL
519 * check that the given name is not one that would eventually result in
520 * xdr routines that would conflict with internal XDR routines.
522 static void
523 check_type_name(char *name, int new_type)
525 int i;
526 char tmp[100];
528 for (i = 0; reserved_words[i] != NULL; i++) {
529 if (strcmp(name, reserved_words[i]) == 0) {
530 (void) snprintf(tmp, sizeof (tmp),
531 "illegal (reserved) name :\'%s\' "
532 "in type definition",
533 name);
534 error(tmp);
537 if (new_type) {
538 for (i = 0; reserved_types[i] != NULL; i++) {
539 if (strcmp(name, reserved_types[i]) == 0) {
540 (void) snprintf(tmp, sizeof (tmp),
541 "illegal (reserved) name :\'%s\' "
542 "in type definition",
543 name);
544 error(tmp);
550 static void
551 def_typedef(definition *defp)
553 declaration dec;
555 defp->def_kind = DEF_TYPEDEF;
556 get_declaration(&dec, DEF_TYPEDEF);
557 defp->def_name = dec.name;
558 check_type_name(dec.name, 1);
559 defp->def.ty.old_prefix = dec.prefix;
560 defp->def.ty.old_type = dec.type;
561 defp->def.ty.rel = dec.rel;
562 defp->def.ty.array_max = dec.array_max;
565 static void
566 get_declaration(declaration *dec, defkind dkind)
568 token tok;
570 get_type(&dec->prefix, &dec->type, dkind);
571 dec->rel = REL_ALIAS;
572 if (streq(dec->type, "void"))
573 return;
575 check_type_name(dec->type, 0);
576 scan2(TOK_STAR, TOK_IDENT, &tok);
577 if (tok.kind == TOK_STAR) {
578 dec->rel = REL_POINTER;
579 scan(TOK_IDENT, &tok);
581 dec->name = tok.str;
582 if (peekscan(TOK_LBRACKET, &tok)) {
583 if (dec->rel == REL_POINTER)
584 error("no array-of-pointer declarations "
585 "-- use typedef");
586 dec->rel = REL_VECTOR;
587 scan_num(&tok);
588 dec->array_max = tok.str;
589 scan(TOK_RBRACKET, &tok);
590 } else if (peekscan(TOK_LANGLE, &tok)) {
591 if (dec->rel == REL_POINTER)
592 error("no array-of-pointer declarations "
593 "-- use typedef");
594 dec->rel = REL_ARRAY;
595 if (peekscan(TOK_RANGLE, &tok)) {
596 dec->array_max = "~0"; /* unspecified size, use max */
597 } else {
598 scan_num(&tok);
599 dec->array_max = tok.str;
600 scan(TOK_RANGLE, &tok);
603 if (streq(dec->type, "opaque")) {
604 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
605 error("array declaration expected");
607 } else if (streq(dec->type, "string")) {
608 if (dec->rel != REL_ARRAY) {
609 error("variable-length array declaration expected");
614 static void
615 get_prog_declaration(declaration *dec, defkind dkind, int num)
617 token tok;
618 char name[sizeof (ARGNAME) + 10];
620 if (dkind == DEF_PROGRAM) {
621 peek(&tok);
622 if (tok.kind == TOK_RPAREN) { /* no arguments */
623 dec->rel = REL_ALIAS;
624 dec->type = "void";
625 dec->prefix = NULL;
626 dec->name = NULL;
627 return;
630 get_type(&dec->prefix, &dec->type, dkind);
631 dec->rel = REL_ALIAS;
632 if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
633 dec->name = strdup(tok.str);
634 else {
635 /* default name of argument */
636 (void) snprintf(name, sizeof (name), "%s%d", ARGNAME, num);
637 dec->name = strdup(name);
639 if (dec->name == NULL)
640 error("internal error -- out of memory");
642 if (streq(dec->type, "void"))
643 return;
645 if (streq(dec->type, "opaque"))
646 error("opaque -- illegal argument type");
647 if (peekscan(TOK_STAR, &tok)) {
648 if (streq(dec->type, "string")) {
649 error("pointer to string not allowed "
650 "in program arguments\n");
652 dec->rel = REL_POINTER;
653 if (peekscan(TOK_IDENT, &tok))
654 /* optional name of argument */
655 dec->name = strdup(tok.str);
657 if (peekscan(TOK_LANGLE, &tok)) {
658 if (!streq(dec->type, "string")) {
659 error("arrays cannot be declared as arguments "
660 "to procedures -- use typedef");
662 dec->rel = REL_ARRAY;
663 if (peekscan(TOK_RANGLE, &tok)) {
664 dec->array_max = "~0";
665 /* unspecified size, use max */
666 } else {
667 scan_num(&tok);
668 dec->array_max = tok.str;
669 scan(TOK_RANGLE, &tok);
672 if (streq(dec->type, "string")) {
673 if (dec->rel != REL_ARRAY) {
675 * .x specifies just string as
676 * type of argument
677 * - make it string<>
679 dec->rel = REL_ARRAY;
680 dec->array_max = "~0"; /* unspecified size, use max */
685 static void
686 get_type(char **prefixp, char **typep, defkind dkind)
688 token tok;
690 *prefixp = NULL;
691 get_token(&tok);
692 switch (tok.kind) {
693 case TOK_IDENT:
694 *typep = tok.str;
695 break;
696 case TOK_STRUCT:
697 case TOK_ENUM:
698 case TOK_UNION:
699 *prefixp = tok.str;
700 scan(TOK_IDENT, &tok);
701 *typep = tok.str;
702 break;
703 case TOK_UNSIGNED:
704 unsigned_dec(typep);
705 break;
706 case TOK_SHORT:
707 *typep = "short";
708 (void) peekscan(TOK_INT, &tok);
709 break;
710 case TOK_LONG:
711 *typep = "long";
712 (void) peekscan(TOK_INT, &tok);
713 break;
714 case TOK_HYPER:
715 *typep = "longlong_t";
716 (void) peekscan(TOK_INT, &tok);
717 break;
719 case TOK_VOID:
720 if (dkind != DEF_UNION && dkind != DEF_PROGRAM &&
721 dkind != DEF_RESULT) {
722 error("voids allowed only inside union and "
723 "program definitions with one argument");
725 *typep = tok.str;
726 break;
727 case TOK_ONEWAY:
728 if (dkind != DEF_RESULT) {
729 error("oneways allowed only inside result definitions");
731 *typep = tok.str;
732 break;
733 case TOK_STRING:
734 case TOK_OPAQUE:
735 case TOK_CHAR:
736 case TOK_INT:
737 case TOK_FLOAT:
738 case TOK_DOUBLE:
739 case TOK_BOOL:
740 case TOK_QUAD:
741 *typep = tok.str;
742 break;
743 default:
744 error("expected type specifier");
748 static void
749 unsigned_dec(char **typep)
751 token tok;
753 peek(&tok);
754 switch (tok.kind) {
755 case TOK_CHAR:
756 get_token(&tok);
757 *typep = "u_char";
758 break;
759 case TOK_SHORT:
760 get_token(&tok);
761 *typep = "u_short";
762 (void) peekscan(TOK_INT, &tok);
763 break;
764 case TOK_LONG:
765 get_token(&tok);
766 *typep = "u_long";
767 (void) peekscan(TOK_INT, &tok);
768 break;
769 case TOK_HYPER:
770 get_token(&tok);
771 *typep = "u_longlong_t";
772 (void) peekscan(TOK_INT, &tok);
773 break;
774 case TOK_INT:
775 get_token(&tok);
776 *typep = "u_int";
777 break;
778 default:
779 *typep = "u_int";
780 break;