summaryrefslogtreecommitdiffstats
path: root/tools/rpcgen/rpc_parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/rpcgen/rpc_parse.c')
-rw-r--r--tools/rpcgen/rpc_parse.c686
1 files changed, 686 insertions, 0 deletions
diff --git a/tools/rpcgen/rpc_parse.c b/tools/rpcgen/rpc_parse.c
new file mode 100644
index 0000000..ee37430
--- /dev/null
+++ b/tools/rpcgen/rpc_parse.c
@@ -0,0 +1,686 @@
+/*
+ * From: @(#)rpc_parse.c 1.8 89/02/22
+ *
+ * Copyright (c) 2010, Oracle America, Inc.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ * * Neither the name of the "Oracle America, Inc." nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * rpc_parse.c, Parser for the RPC protocol compiler
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "proto.h"
+
+#define ARGNAME "arg"
+
+static void isdefined (definition * defp);
+static void def_struct (definition * defp);
+static void def_program (definition * defp);
+static void def_enum (definition * defp);
+static void def_const (definition * defp);
+static void def_union (definition * defp);
+static void check_type_name (const char *name, int new_type);
+static void def_typedef (definition * defp);
+static void get_declaration (declaration * dec, defkind dkind);
+static void get_prog_declaration (declaration * dec, defkind dkind, int num);
+static void get_type (const char **prefixp, const char **typep, defkind dkind);
+static void unsigned_dec (const char **typep);
+
+/*
+ * return the next definition you see
+ */
+definition *
+get_definition (void)
+{
+ 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:
+ free (defp);
+ return (NULL);
+ default:
+ error ("definition keyword expected");
+ }
+ scan (TOK_SEMICOLON, &tok);
+ isdefined (defp);
+ return (defp);
+}
+
+static void
+isdefined (definition * defp)
+{
+ STOREVAL (&defined, defp);
+}
+
+static void
+def_struct (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 void
+def_program (definition * defp)
+{
+ token tok;
+ declaration dec;
+ decl_list *decls;
+ decl_list **tailp;
+ version_list *vlist;
+ version_list **vtailp;
+ proc_list *plist;
+ proc_list **ptailp;
+ int num_args;
+ int isvoid = 0; /* whether first argument is void */
+ defp->def_kind = DEF_PROGRAM;
+ scan (TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan (TOK_LBRACE, &tok);
+ vtailp = &defp->def.pr.versions;
+ tailp = &defp->def.st.decls;
+ 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
+ {
+ /* get result type */
+ 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 args - first one */
+ num_args = 1;
+ isvoid = 0;
+ /* type of DEF_PROGRAM in the first
+ * get_prog_declaration and DEF_STURCT in the next
+ * allows void as argument if it is the only argument
+ */
+ get_prog_declaration (&dec, DEF_PROGRAM, num_args);
+ if (streq (dec.type, "void"))
+ isvoid = 1;
+ decls = ALLOC (decl_list);
+ plist->args.decls = decls;
+ decls->decl = dec;
+ tailp = &decls->next;
+ /* get args */
+ while (peekscan (TOK_COMMA, &tok))
+ {
+ num_args++;
+ get_prog_declaration (&dec, DEF_STRUCT,
+ num_args);
+ decls = ALLOC (decl_list);
+ decls->decl = dec;
+ *tailp = decls;
+ if (streq (dec.type, "void"))
+ isvoid = 1;
+ tailp = &decls->next;
+ }
+ /* multiple arguments are only allowed in newstyle */
+ if (!newstyle && num_args > 1)
+ {
+ error ("only one argument is allowed");
+ }
+ if (isvoid && num_args > 1)
+ {
+ error ("illegal use of void in program definition");
+ }
+ *tailp = NULL;
+ scan (TOK_RPAREN, &tok);
+ scan (TOK_EQUAL, &tok);
+ scan_num (&tok);
+ scan (TOK_SEMICOLON, &tok);
+ plist->proc_num = tok.str;
+ plist->arg_num = num_args;
+ *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;
+ /* make the argument structure name for each arg */
+ for (plist = vlist->procs; plist != NULL;
+ plist = plist->next)
+ {
+ plist->args.argname = make_argname (plist->proc_name,
+ vlist->vers_num);
+ /* free the memory ?? */
+ }
+ 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 void
+def_enum (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 void
+def_const (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 void
+def_union (definition *defp)
+{
+ token tok;
+ declaration dec;
+ case_list *cases;
+/* case_list *tcase; */
+ case_list **tailp;
+#if 0
+ int flag;
+#endif
+
+ 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);
+ /* now peek at next token */
+#if 0
+ flag = 0;
+#endif
+ if (peekscan (TOK_CASE, &tok))
+ {
+
+ do
+ {
+ scan2 (TOK_IDENT, TOK_CHARCONST, &tok);
+ cases->contflag = 1; /* continued case statement */
+ *tailp = cases;
+ tailp = &cases->next;
+ cases = ALLOC (case_list);
+ cases->case_name = tok.str;
+ scan (TOK_COLON, &tok);
+
+ }
+ while (peekscan (TOK_CASE, &tok));
+ }
+#if 0
+ else if (flag)
+ {
+
+ *tailp = cases;
+ tailp = &cases->next;
+ cases = ALLOC (case_list);
+ };
+#endif
+
+ get_declaration (&dec, DEF_UNION);
+ cases->case_decl = dec;
+ cases->contflag = 0; /* no continued case statement */
+ *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 const char *reserved_words[] =
+{
+ "array",
+ "bytes",
+ "destroy",
+ "free",
+ "getpos",
+ "inline",
+ "pointer",
+ "reference",
+ "setpos",
+ "sizeof",
+ "union",
+ "vector",
+ NULL
+};
+
+static const char *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;
+ char tmp[100];
+
+ for (i = 0; reserved_words[i] != NULL; i++)
+ {
+ if (strcmp (name, reserved_words[i]) == 0)
+ {
+ sprintf (tmp,
+ "illegal (reserved) name :\'%s\' in type definition", name);
+ error (tmp);
+ }
+ }
+ if (new_type)
+ {
+ for (i = 0; reserved_types[i] != NULL; i++)
+ {
+ if (strcmp (name, reserved_types[i]) == 0)
+ {
+ sprintf (tmp,
+ "illegal (reserved) name :\'%s\' in type definition", name);
+ error (tmp);
+ }
+ }
+ }
+}
+
+
+
+static void
+def_typedef (definition * defp)
+{
+ declaration dec;
+
+ defp->def_kind = DEF_TYPEDEF;
+ get_declaration (&dec, DEF_TYPEDEF);
+ defp->def_name = dec.name;
+ check_type_name (dec.name, 1);
+ 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 void
+get_declaration (declaration * dec, defkind dkind)
+{
+ token tok;
+
+ get_type (&dec->prefix, &dec->type, dkind);
+ dec->rel = REL_ALIAS;
+ if (streq (dec->type, "void"))
+ {
+ return;
+ }
+
+ check_type_name (dec->type, 0);
+
+ 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 void
+get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
+{
+ token tok;
+ char name[MAXLINESIZE]; /* 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 = (char *) 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 = "~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 = "~0"; /* unspecified size, use max */
+ }
+ }
+}
+
+static void
+get_type (const char **prefixp, const 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_HYPER:
+ *typep = "quad_t";
+ (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 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:
+ *typep = tok.str;
+ break;
+ default:
+ error ("expected type specifier");
+ }
+}
+
+static void
+unsigned_dec (const 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_HYPER:
+ get_token (&tok);
+ *typep = "u_quad_t";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_INT:
+ get_token (&tok);
+ *typep = "u_int";
+ break;
+ default:
+ *typep = "u_int";
+ break;
+ }
+}