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