/* $NetBSD: rpc_parse.c,v 1.23 2022/01/11 22:45:56 andvar Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
static const char *const reserved_types[] = {
"opaque",
"string",
NULL
};
/* check that the given name is not one that would eventually result in
xdr routines that would conflict with internal XDR routines. */
static void
check_type_name(const char *name, int new_type)
{
int i;
for (i = 0; reserved_words[i] != NULL; i++) {
if (strcmp(name, reserved_words[i]) == 0) {
error("Illegal (reserved) name '%s' in type definition", name);
}
}
if (new_type) {
for (i = 0; reserved_types[i] != NULL; i++) {
if (strcmp(name, reserved_types[i]) == 0) {
error("Illegal (reserved) name '%s' in type definition", name);
}
}
}
}
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 = "(unsigned int)~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 void
get_prog_declaration(declaration *dec, defkind dkind, int num /* arg number */)
{
token tok;
char name[255]; /* argument name */
if (dkind == DEF_PROGRAM) {
peek(&tok);
if (tok.kind == TOK_RPAREN) { /* no arguments */
dec->rel = REL_ALIAS;
dec->type = "void";
dec->prefix = NULL;
dec->name = NULL;
return;
}
}
get_type(&dec->prefix, &dec->type, dkind);
dec->rel = REL_ALIAS;
if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
strcpy(name, tok.str);
else
sprintf(name, "%s%d", ARGNAME, num); /* default name of
* argument */
dec->name = strdup(name);
if (streq(dec->type, "void")) {
return;
}
if (streq(dec->type, "opaque")) {
error("Opaque -- illegal argument type");
}
if (peekscan(TOK_STAR, &tok)) {
if (streq(dec->type, "string")) {
error("Pointer to string not allowed in program arguments\n");
}
dec->rel = REL_POINTER;
if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
dec->name = strdup(tok.str);
}
if (peekscan(TOK_LANGLE, &tok)) {
if (!streq(dec->type, "string")) {
error("Arrays cannot be declared as arguments to procedures -- use typedef");
}
dec->rel = REL_ARRAY;
if (peekscan(TOK_RANGLE, &tok)) {
dec->array_max = "(unsigned int)~0";
/* unspecified size, use max */
} else {
scan_num(&tok);
dec->array_max = tok.str;
scan(TOK_RANGLE, &tok);
}
}
if (streq(dec->type, "string")) {
if (dec->rel != REL_ARRAY) { /* .x specifies just string as
* type of argument - make it
* string<> */
dec->rel = REL_ARRAY;
dec->array_max = "(unsigned int)~0";
/* unspecified size, use max */
}
}
}
*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_HYPER:
*typep = "longlong_t";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_VOID:
if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
error("Void is allowed only inside union and program definitions with one argument");
}
*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:
case TOK_QUAD:
*typep = tok.str;
break;
default:
error("Type specifier expected");
}
}