#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;
}
}