#ifndef lint static char sccsid[] = "@(#)rpc←parse.c 1.1 90/10/29 (C) 1987 SMI"; #endif /* * rpc←parse.c, Parser for the RPC protocol compiler * Copyright (C) 1987 Sun Microsystems, Inc. */ #include <stdio.h> #include "rpc←util.h" #include "rpc←scan.h" #include "rpc←parse.h" /* * return the next definition you see */ definition * get←definition() { definition *defp; token tok; defp = ALLOC(definition); get←token(&tok); switch (tok.kind) { case TOK←STRUCT: def←struct(defp); break; case TOK←UNION: def←union(defp); break; case TOK←TYPEDEF: def←typedef(defp); break; case TOK←ENUM: def←enum(defp); break; case TOK←PROGRAM: def←program(defp); break; case TOK←CONST: def←const(defp); break; case TOK←EOF: return (NULL); default: error("definition keyword expected"); } scan(TOK←SEMICOLON, &tok); isdefined(defp); return (defp); } static isdefined(defp) definition *defp; { STOREVAL(&CurrentContext->defined, defp); } static def←struct(defp) definition *defp; { token tok; declaration dec; decl←list *decls; decl←list **tailp; defp->def←kind = DEF←STRUCT; scan(TOK←IDENT, &tok); defp->def←name = tok.str; scan(TOK←LBRACE, &tok); tailp = &defp->def.st.decls; do { get←declaration(&dec, DEF←STRUCT); decls = ALLOC(decl←list); decls->decl = dec; *tailp = decls; tailp = &decls->next; scan(TOK←SEMICOLON, &tok); peek(&tok); } while (tok.kind != TOK←RBRACE); get←token(&tok); *tailp = NULL; } static def←program(defp) definition *defp; { token tok; version←list *vlist; version←list **vtailp; proc←list *plist; proc←list **ptailp; defp->def←kind = DEF←PROGRAM; scan(TOK←IDENT, &tok); defp->def←name = tok.str; scan(TOK←LBRACE, &tok); vtailp = &defp->def.pr.versions; scan(TOK←VERSION, &tok); do { scan(TOK←IDENT, &tok); vlist = ALLOC(version←list); vlist->vers←name = tok.str; scan(TOK←LBRACE, &tok); ptailp = &vlist->procs; do { plist = ALLOC(proc←list); get←type(&plist->res←prefix, &plist->res←type, DEF←PROGRAM); if (streq(plist->res←type, "opaque")) { error("illegal result type"); } scan(TOK←IDENT, &tok); plist->proc←name = tok.str; scan(TOK←LPAREN, &tok); get←type(&plist->arg←prefix, &plist->arg←type, DEF←PROGRAM); if (streq(plist->arg←type, "opaque")) { error("illegal argument type"); } scan(TOK←RPAREN, &tok); scan(TOK←EQUAL, &tok); scan←num(&tok); scan(TOK←SEMICOLON, &tok); plist->proc←num = tok.str; *ptailp = plist; ptailp = &plist->next; peek(&tok); } while (tok.kind != TOK←RBRACE); *ptailp = NULL; *vtailp = vlist; vtailp = &vlist->next; scan(TOK←RBRACE, &tok); scan(TOK←EQUAL, &tok); scan←num(&tok); vlist->vers←num = tok.str; scan(TOK←SEMICOLON, &tok); scan2(TOK←VERSION, TOK←RBRACE, &tok); } while (tok.kind == TOK←VERSION); scan(TOK←EQUAL, &tok); scan←num(&tok); defp->def.pr.prog←num = tok.str; *vtailp = NULL; } static def←enum(defp) definition *defp; { token tok; enumval←list *elist; enumval←list **tailp; defp->def←kind = DEF←ENUM; scan(TOK←IDENT, &tok); defp->def←name = tok.str; scan(TOK←LBRACE, &tok); tailp = &defp->def.en.vals; do { scan(TOK←IDENT, &tok); elist = ALLOC(enumval←list); elist->name = tok.str; elist->assignment = NULL; scan3(TOK←COMMA, TOK←RBRACE, TOK←EQUAL, &tok); if (tok.kind == TOK←EQUAL) { scan←num(&tok); elist->assignment = tok.str; scan2(TOK←COMMA, TOK←RBRACE, &tok); } *tailp = elist; tailp = &elist->next; } while (tok.kind != TOK←RBRACE); *tailp = NULL; } static def←const(defp) definition *defp; { token tok; defp->def←kind = DEF←CONST; scan(TOK←IDENT, &tok); defp->def←name = tok.str; scan(TOK←EQUAL, &tok); scan2(TOK←IDENT, TOK←STRCONST, &tok); defp->def.co = tok.str; } static def←union(defp) definition *defp; { token tok; declaration dec; case←list *cases; case←list **tailp; defp->def←kind = DEF←UNION; scan(TOK←IDENT, &tok); defp->def←name = tok.str; scan(TOK←SWITCH, &tok); scan(TOK←LPAREN, &tok); get←declaration(&dec, DEF←UNION); defp->def.un.enum←decl = dec; tailp = &defp->def.un.cases; scan(TOK←RPAREN, &tok); scan(TOK←LBRACE, &tok); scan(TOK←CASE, &tok); while (tok.kind == TOK←CASE) { scan2(TOK←IDENT, TOK←CHARCONST, &tok); cases = ALLOC(case←list); cases->case←name = tok.str; scan(TOK←COLON, &tok); get←declaration(&dec, DEF←UNION); cases->case←decl = dec; *tailp = cases; tailp = &cases->next; scan(TOK←SEMICOLON, &tok); scan3(TOK←CASE, TOK←DEFAULT, TOK←RBRACE, &tok); } *tailp = NULL; if (tok.kind == TOK←DEFAULT) { scan(TOK←COLON, &tok); get←declaration(&dec, DEF←UNION); defp->def.un.default←decl = ALLOC(declaration); *defp->def.un.default←decl = dec; scan(TOK←SEMICOLON, &tok); scan(TOK←RBRACE, &tok); } else { defp->def.un.default←decl = NULL; } } static def←typedef(defp) definition *defp; { declaration dec; defp->def←kind = DEF←TYPEDEF; get←declaration(&dec, DEF←TYPEDEF); defp->def←name = dec.name; defp->def.ty.old←prefix = dec.prefix; defp->def.ty.old←type = dec.type; defp->def.ty.rel = dec.rel; defp->def.ty.array←max = dec.array←max; } static get←declaration(dec, dkind) declaration *dec; defkind dkind; { token tok; get←type(&dec->prefix, &dec->type, dkind); dec->rel = REL←ALIAS; if (streq(dec->type, "void")) { return; } scan2(TOK←STAR, TOK←IDENT, &tok); if (tok.kind == TOK←STAR) { dec->rel = REL←POINTER; scan(TOK←IDENT, &tok); } dec->name = tok.str; if (peekscan(TOK←LBRACKET, &tok)) { if (dec->rel == REL←POINTER) { error("no array-of-pointer declarations -- use typedef"); } dec->rel = REL←VECTOR; scan←num(&tok); dec->array←max = tok.str; scan(TOK←RBRACKET, &tok); } else if (peekscan(TOK←LANGLE, &tok)) { if (dec->rel == REL←POINTER) { error("no array-of-pointer declarations -- use typedef"); } dec->rel = REL←ARRAY; if (peekscan(TOK←RANGLE, &tok)) { dec->array←max = "~0"; /* unspecified size, use max */ } else { scan←num(&tok); dec->array←max = tok.str; scan(TOK←RANGLE, &tok); } } if (streq(dec->type, "opaque")) { if (dec->rel != REL←ARRAY && dec->rel != REL←VECTOR) { error("array declaration expected"); } } else if (streq(dec->type, "string")) { if (dec->rel != REL←ARRAY) { error("variable-length array declaration expected"); } } } static get←type(prefixp, typep, dkind) char **prefixp; char **typep; defkind dkind; { token tok; *prefixp = NULL; get←token(&tok); switch (tok.kind) { case TOK←IDENT: *typep = tok.str; break; case TOK←STRUCT: case TOK←ENUM: case TOK←UNION: *prefixp = tok.str; scan(TOK←IDENT, &tok); *typep = tok.str; break; case TOK←UNSIGNED: unsigned←dec(typep); break; case TOK←SHORT: *typep = "short"; (void) peekscan(TOK←INT, &tok); break; case TOK←LONG: *typep = "long"; (void) peekscan(TOK←INT, &tok); break; case TOK←VOID: if (dkind != DEF←UNION && dkind != DEF←PROGRAM) { error("voids allowed only inside union and program definitions"); } *typep = tok.str; break; case TOK←STRING: case TOK←OPAQUE: case TOK←CHAR: case TOK←INT: case TOK←FLOAT: case TOK←DOUBLE: case TOK←BOOL: *typep = tok.str; break; default: error("expected type specifier"); } } static unsigned←dec(typep) char **typep; { token tok; peek(&tok); switch (tok.kind) { case TOK←CHAR: get←token(&tok); *typep = "u←char"; break; case TOK←SHORT: get←token(&tok); *typep = "u←short"; (void) peekscan(TOK←INT, &tok); break; case TOK←LONG: get←token(&tok); *typep = "u←long"; (void) peekscan(TOK←INT, &tok); break; case TOK←INT: get←token(&tok); *typep = "u←int"; break; default: *typep = "u←int"; break; } }