Blame sunrpc/rpc_parse.c

Packit 6c4009
/*
Packit 6c4009
 * From: @(#)rpc_parse.c 1.8 89/02/22
Packit 6c4009
 *
Packit 6c4009
 * Copyright (c) 2010, Oracle America, Inc.
Packit 6c4009
 * Redistribution and use in source and binary forms, with or without
Packit 6c4009
 * modification, are permitted provided that the following conditions are
Packit 6c4009
 * met:
Packit 6c4009
 *
Packit 6c4009
 *     * Redistributions of source code must retain the above copyright
Packit 6c4009
 *       notice, this list of conditions and the following disclaimer.
Packit 6c4009
 *     * Redistributions in binary form must reproduce the above
Packit 6c4009
 *       copyright notice, this list of conditions and the following
Packit 6c4009
 *       disclaimer in the documentation and/or other materials
Packit 6c4009
 *       provided with the distribution.
Packit 6c4009
 *     * Neither the name of the "Oracle America, Inc." nor the names of its
Packit 6c4009
 *       contributors may be used to endorse or promote products derived
Packit 6c4009
 *       from this software without specific prior written permission.
Packit 6c4009
 *
Packit 6c4009
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 6c4009
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 6c4009
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit 6c4009
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit 6c4009
 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Packit 6c4009
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 6c4009
 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
Packit 6c4009
 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit 6c4009
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit 6c4009
 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 6c4009
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 6c4009
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * rpc_parse.c, Parser for the RPC protocol compiler
Packit 6c4009
 * Copyright (C) 1987 Sun Microsystems, Inc.
Packit 6c4009
 */
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include "rpc/types.h"
Packit 6c4009
#include "rpc_scan.h"
Packit 6c4009
#include "rpc_parse.h"
Packit 6c4009
#include "rpc_util.h"
Packit 6c4009
#include "proto.h"
Packit 6c4009
Packit 6c4009
#define ARGNAME "arg"
Packit 6c4009
Packit 6c4009
static void isdefined (definition * defp);
Packit 6c4009
static void def_struct (definition * defp);
Packit 6c4009
static void def_program (definition * defp);
Packit 6c4009
static void def_enum (definition * defp);
Packit 6c4009
static void def_const (definition * defp);
Packit 6c4009
static void def_union (definition * defp);
Packit 6c4009
static void check_type_name (const char *name, int new_type);
Packit 6c4009
static void def_typedef (definition * defp);
Packit 6c4009
static void get_declaration (declaration * dec, defkind dkind);
Packit 6c4009
static void get_prog_declaration (declaration * dec, defkind dkind, int num);
Packit 6c4009
static void get_type (const char **prefixp, const char **typep, defkind dkind);
Packit 6c4009
static void unsigned_dec (const char **typep);
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * return the next definition you see
Packit 6c4009
 */
Packit 6c4009
definition *
Packit 6c4009
get_definition (void)
Packit 6c4009
{
Packit 6c4009
  definition *defp;
Packit 6c4009
  token tok;
Packit 6c4009
Packit 6c4009
  defp = ALLOC (definition);
Packit 6c4009
  get_token (&tok;;
Packit 6c4009
  switch (tok.kind)
Packit 6c4009
    {
Packit 6c4009
    case TOK_STRUCT:
Packit 6c4009
      def_struct (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_UNION:
Packit 6c4009
      def_union (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_TYPEDEF:
Packit 6c4009
      def_typedef (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_ENUM:
Packit 6c4009
      def_enum (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_PROGRAM:
Packit 6c4009
      def_program (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_CONST:
Packit 6c4009
      def_const (defp);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_EOF:
Packit 6c4009
      free (defp);
Packit 6c4009
      return (NULL);
Packit 6c4009
    default:
Packit 6c4009
      error ("definition keyword expected");
Packit 6c4009
    }
Packit 6c4009
  scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
  isdefined (defp);
Packit 6c4009
  return (defp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
isdefined (definition * defp)
Packit 6c4009
{
Packit 6c4009
  STOREVAL (&defined, defp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_struct (definition * defp)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
  declaration dec;
Packit 6c4009
  decl_list *decls;
Packit 6c4009
  decl_list **tailp;
Packit 6c4009
Packit 6c4009
  defp->def_kind = DEF_STRUCT;
Packit 6c4009
Packit 6c4009
  scan (TOK_IDENT, &tok;;
Packit 6c4009
  defp->def_name = tok.str;
Packit 6c4009
  scan (TOK_LBRACE, &tok;;
Packit 6c4009
  tailp = &defp->def.st.decls;
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      get_declaration (&dec, DEF_STRUCT);
Packit 6c4009
      decls = ALLOC (decl_list);
Packit 6c4009
      decls->decl = dec;
Packit 6c4009
      *tailp = decls;
Packit 6c4009
      tailp = &decls->next;
Packit 6c4009
      scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
      peek (&tok;;
Packit 6c4009
    }
Packit 6c4009
  while (tok.kind != TOK_RBRACE);
Packit 6c4009
  get_token (&tok;;
Packit 6c4009
  *tailp = NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_program (definition * defp)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
  declaration dec;
Packit 6c4009
  decl_list *decls;
Packit 6c4009
  decl_list **tailp;
Packit 6c4009
  version_list *vlist;
Packit 6c4009
  version_list **vtailp;
Packit 6c4009
  proc_list *plist;
Packit 6c4009
  proc_list **ptailp;
Packit 6c4009
  int num_args;
Packit 6c4009
  bool_t isvoid = FALSE;	/* whether first argument is void */
Packit 6c4009
  defp->def_kind = DEF_PROGRAM;
Packit 6c4009
  scan (TOK_IDENT, &tok;;
Packit 6c4009
  defp->def_name = tok.str;
Packit 6c4009
  scan (TOK_LBRACE, &tok;;
Packit 6c4009
  vtailp = &defp->def.pr.versions;
Packit 6c4009
  tailp = &defp->def.st.decls;
Packit 6c4009
  scan (TOK_VERSION, &tok;;
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      scan (TOK_IDENT, &tok;;
Packit 6c4009
      vlist = ALLOC (version_list);
Packit 6c4009
      vlist->vers_name = tok.str;
Packit 6c4009
      scan (TOK_LBRACE, &tok;;
Packit 6c4009
      ptailp = &vlist->procs;
Packit 6c4009
      do
Packit 6c4009
	{
Packit 6c4009
	  /* get result type */
Packit 6c4009
	  plist = ALLOC (proc_list);
Packit 6c4009
	  get_type (&plist->res_prefix, &plist->res_type,
Packit 6c4009
		    DEF_PROGRAM);
Packit 6c4009
	  if (streq (plist->res_type, "opaque"))
Packit 6c4009
	    {
Packit 6c4009
	      error ("illegal result type");
Packit 6c4009
	    }
Packit 6c4009
	  scan (TOK_IDENT, &tok;;
Packit 6c4009
	  plist->proc_name = tok.str;
Packit 6c4009
	  scan (TOK_LPAREN, &tok;;
Packit 6c4009
	  /* get args - first one */
Packit 6c4009
	  num_args = 1;
Packit 6c4009
	  isvoid = FALSE;
Packit 6c4009
	  /* type of DEF_PROGRAM in the first
Packit 6c4009
	   * get_prog_declaration and DEF_STURCT in the next
Packit 6c4009
	   * allows void as argument if it is the only argument
Packit 6c4009
	   */
Packit 6c4009
	  get_prog_declaration (&dec, DEF_PROGRAM, num_args);
Packit 6c4009
	  if (streq (dec.type, "void"))
Packit 6c4009
	    isvoid = TRUE;
Packit 6c4009
	  decls = ALLOC (decl_list);
Packit 6c4009
	  plist->args.decls = decls;
Packit 6c4009
	  decls->decl = dec;
Packit 6c4009
	  tailp = &decls->next;
Packit 6c4009
	  /* get args */
Packit 6c4009
	  while (peekscan (TOK_COMMA, &tok))
Packit 6c4009
	    {
Packit 6c4009
	      num_args++;
Packit 6c4009
	      get_prog_declaration (&dec, DEF_STRUCT,
Packit 6c4009
				    num_args);
Packit 6c4009
	      decls = ALLOC (decl_list);
Packit 6c4009
	      decls->decl = dec;
Packit 6c4009
	      *tailp = decls;
Packit 6c4009
	      if (streq (dec.type, "void"))
Packit 6c4009
		isvoid = TRUE;
Packit 6c4009
	      tailp = &decls->next;
Packit 6c4009
	    }
Packit 6c4009
	  /* multiple arguments are only allowed in newstyle */
Packit 6c4009
	  if (!newstyle && num_args > 1)
Packit 6c4009
	    {
Packit 6c4009
	      error ("only one argument is allowed");
Packit 6c4009
	    }
Packit 6c4009
	  if (isvoid && num_args > 1)
Packit 6c4009
	    {
Packit 6c4009
	      error ("illegal use of void in program definition");
Packit 6c4009
	    }
Packit 6c4009
	  *tailp = NULL;
Packit 6c4009
	  scan (TOK_RPAREN, &tok;;
Packit 6c4009
	  scan (TOK_EQUAL, &tok;;
Packit 6c4009
	  scan_num (&tok;;
Packit 6c4009
	  scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
	  plist->proc_num = tok.str;
Packit 6c4009
	  plist->arg_num = num_args;
Packit 6c4009
	  *ptailp = plist;
Packit 6c4009
	  ptailp = &plist->next;
Packit 6c4009
	  peek (&tok;;
Packit 6c4009
	}
Packit 6c4009
      while (tok.kind != TOK_RBRACE);
Packit 6c4009
      *ptailp = NULL;
Packit 6c4009
      *vtailp = vlist;
Packit 6c4009
      vtailp = &vlist->next;
Packit 6c4009
      scan (TOK_RBRACE, &tok;;
Packit 6c4009
      scan (TOK_EQUAL, &tok;;
Packit 6c4009
      scan_num (&tok;;
Packit 6c4009
      vlist->vers_num = tok.str;
Packit 6c4009
      /* make the argument structure name for each arg */
Packit 6c4009
      for (plist = vlist->procs; plist != NULL;
Packit 6c4009
	   plist = plist->next)
Packit 6c4009
	{
Packit 6c4009
	  plist->args.argname = make_argname (plist->proc_name,
Packit 6c4009
					      vlist->vers_num);
Packit 6c4009
	  /* free the memory ?? */
Packit 6c4009
	}
Packit 6c4009
      scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
      scan2 (TOK_VERSION, TOK_RBRACE, &tok;;
Packit 6c4009
    }
Packit 6c4009
  while (tok.kind == TOK_VERSION);
Packit 6c4009
  scan (TOK_EQUAL, &tok;;
Packit 6c4009
  scan_num (&tok;;
Packit 6c4009
  defp->def.pr.prog_num = tok.str;
Packit 6c4009
  *vtailp = NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_enum (definition * defp)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
  enumval_list *elist;
Packit 6c4009
  enumval_list **tailp;
Packit 6c4009
Packit 6c4009
  defp->def_kind = DEF_ENUM;
Packit 6c4009
  scan (TOK_IDENT, &tok;;
Packit 6c4009
  defp->def_name = tok.str;
Packit 6c4009
  scan (TOK_LBRACE, &tok;;
Packit 6c4009
  tailp = &defp->def.en.vals;
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      scan (TOK_IDENT, &tok;;
Packit 6c4009
      elist = ALLOC (enumval_list);
Packit 6c4009
      elist->name = tok.str;
Packit 6c4009
      elist->assignment = NULL;
Packit 6c4009
      scan3 (TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok;;
Packit 6c4009
      if (tok.kind == TOK_EQUAL)
Packit 6c4009
	{
Packit 6c4009
	  scan_num (&tok;;
Packit 6c4009
	  elist->assignment = tok.str;
Packit 6c4009
	  scan2 (TOK_COMMA, TOK_RBRACE, &tok;;
Packit 6c4009
	}
Packit 6c4009
      *tailp = elist;
Packit 6c4009
      tailp = &elist->next;
Packit 6c4009
    }
Packit 6c4009
  while (tok.kind != TOK_RBRACE);
Packit 6c4009
  *tailp = NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_const (definition * defp)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
Packit 6c4009
  defp->def_kind = DEF_CONST;
Packit 6c4009
  scan (TOK_IDENT, &tok;;
Packit 6c4009
  defp->def_name = tok.str;
Packit 6c4009
  scan (TOK_EQUAL, &tok;;
Packit 6c4009
  scan2 (TOK_IDENT, TOK_STRCONST, &tok;;
Packit 6c4009
  defp->def.co = tok.str;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_union (definition *defp)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
  declaration dec;
Packit 6c4009
  case_list *cases;
Packit 6c4009
/*  case_list *tcase; */
Packit 6c4009
  case_list **tailp;
Packit 6c4009
#if 0
Packit 6c4009
  int flag;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  defp->def_kind = DEF_UNION;
Packit 6c4009
  scan (TOK_IDENT, &tok;;
Packit 6c4009
  defp->def_name = tok.str;
Packit 6c4009
  scan (TOK_SWITCH, &tok;;
Packit 6c4009
  scan (TOK_LPAREN, &tok;;
Packit 6c4009
  get_declaration (&dec, DEF_UNION);
Packit 6c4009
  defp->def.un.enum_decl = dec;
Packit 6c4009
  tailp = &defp->def.un.cases;
Packit 6c4009
  scan (TOK_RPAREN, &tok;;
Packit 6c4009
  scan (TOK_LBRACE, &tok;;
Packit 6c4009
  scan (TOK_CASE, &tok;;
Packit 6c4009
  while (tok.kind == TOK_CASE)
Packit 6c4009
    {
Packit 6c4009
      scan2 (TOK_IDENT, TOK_CHARCONST, &tok;;
Packit 6c4009
      cases = ALLOC (case_list);
Packit 6c4009
      cases->case_name = tok.str;
Packit 6c4009
      scan (TOK_COLON, &tok;;
Packit 6c4009
      /* now peek at next token */
Packit 6c4009
#if 0
Packit 6c4009
      flag = 0;
Packit 6c4009
#endif
Packit 6c4009
      if (peekscan (TOK_CASE, &tok))
Packit 6c4009
	{
Packit 6c4009
Packit 6c4009
	  do
Packit 6c4009
	    {
Packit 6c4009
	      scan2 (TOK_IDENT, TOK_CHARCONST, &tok;;
Packit 6c4009
	      cases->contflag = 1;	/* continued case statement */
Packit 6c4009
	      *tailp = cases;
Packit 6c4009
	      tailp = &cases->next;
Packit 6c4009
	      cases = ALLOC (case_list);
Packit 6c4009
	      cases->case_name = tok.str;
Packit 6c4009
	      scan (TOK_COLON, &tok;;
Packit 6c4009
Packit 6c4009
	    }
Packit 6c4009
	  while (peekscan (TOK_CASE, &tok));
Packit 6c4009
	}
Packit 6c4009
#if 0
Packit 6c4009
      else if (flag)
Packit 6c4009
	{
Packit 6c4009
Packit 6c4009
	  *tailp = cases;
Packit 6c4009
	  tailp = &cases->next;
Packit 6c4009
	  cases = ALLOC (case_list);
Packit 6c4009
	};
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
      get_declaration (&dec, DEF_UNION);
Packit 6c4009
      cases->case_decl = dec;
Packit 6c4009
      cases->contflag = 0;	/* no continued case statement */
Packit 6c4009
      *tailp = cases;
Packit 6c4009
      tailp = &cases->next;
Packit 6c4009
      scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
Packit 6c4009
      scan3 (TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok;;
Packit 6c4009
    }
Packit 6c4009
  *tailp = NULL;
Packit 6c4009
  if (tok.kind == TOK_DEFAULT)
Packit 6c4009
    {
Packit 6c4009
      scan (TOK_COLON, &tok;;
Packit 6c4009
      get_declaration (&dec, DEF_UNION);
Packit 6c4009
      defp->def.un.default_decl = ALLOC (declaration);
Packit 6c4009
      *defp->def.un.default_decl = dec;
Packit 6c4009
      scan (TOK_SEMICOLON, &tok;;
Packit 6c4009
      scan (TOK_RBRACE, &tok;;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      defp->def.un.default_decl = NULL;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static const char *reserved_words[] =
Packit 6c4009
{
Packit 6c4009
  "array",
Packit 6c4009
  "bytes",
Packit 6c4009
  "destroy",
Packit 6c4009
  "free",
Packit 6c4009
  "getpos",
Packit 6c4009
  "inline",
Packit 6c4009
  "pointer",
Packit 6c4009
  "reference",
Packit 6c4009
  "setpos",
Packit 6c4009
  "sizeof",
Packit 6c4009
  "union",
Packit 6c4009
  "vector",
Packit 6c4009
  NULL
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static const char *reserved_types[] =
Packit 6c4009
{
Packit 6c4009
  "opaque",
Packit 6c4009
  "string",
Packit 6c4009
  NULL
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * check that the given name is not one that would eventually result in
Packit 6c4009
 * xdr routines that would conflict with internal XDR routines.
Packit 6c4009
 */
Packit 6c4009
static void
Packit 6c4009
check_type_name (const char *name, int new_type)
Packit 6c4009
{
Packit 6c4009
  int i;
Packit 6c4009
  char tmp[100];
Packit 6c4009
Packit 6c4009
  for (i = 0; reserved_words[i] != NULL; i++)
Packit 6c4009
    {
Packit 6c4009
      if (strcmp (name, reserved_words[i]) == 0)
Packit 6c4009
	{
Packit 6c4009
	  sprintf (tmp,
Packit 6c4009
		"illegal (reserved) name :\'%s\' in type definition", name);
Packit 6c4009
	  error (tmp);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  if (new_type)
Packit 6c4009
    {
Packit 6c4009
      for (i = 0; reserved_types[i] != NULL; i++)
Packit 6c4009
	{
Packit 6c4009
	  if (strcmp (name, reserved_types[i]) == 0)
Packit 6c4009
	    {
Packit 6c4009
	      sprintf (tmp,
Packit 6c4009
		"illegal (reserved) name :\'%s\' in type definition", name);
Packit 6c4009
	      error (tmp);
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
def_typedef (definition * defp)
Packit 6c4009
{
Packit 6c4009
  declaration dec;
Packit 6c4009
Packit 6c4009
  defp->def_kind = DEF_TYPEDEF;
Packit 6c4009
  get_declaration (&dec, DEF_TYPEDEF);
Packit 6c4009
  defp->def_name = dec.name;
Packit 6c4009
  check_type_name (dec.name, 1);
Packit 6c4009
  defp->def.ty.old_prefix = dec.prefix;
Packit 6c4009
  defp->def.ty.old_type = dec.type;
Packit 6c4009
  defp->def.ty.rel = dec.rel;
Packit 6c4009
  defp->def.ty.array_max = dec.array_max;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
get_declaration (declaration * dec, defkind dkind)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
Packit 6c4009
  get_type (&dec->prefix, &dec->type, dkind);
Packit 6c4009
  dec->rel = REL_ALIAS;
Packit 6c4009
  if (streq (dec->type, "void"))
Packit 6c4009
    {
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  check_type_name (dec->type, 0);
Packit 6c4009
Packit 6c4009
  scan2 (TOK_STAR, TOK_IDENT, &tok;;
Packit 6c4009
  if (tok.kind == TOK_STAR)
Packit 6c4009
    {
Packit 6c4009
      dec->rel = REL_POINTER;
Packit 6c4009
      scan (TOK_IDENT, &tok;;
Packit 6c4009
    }
Packit 6c4009
  dec->name = tok.str;
Packit 6c4009
  if (peekscan (TOK_LBRACKET, &tok))
Packit 6c4009
    {
Packit 6c4009
      if (dec->rel == REL_POINTER)
Packit 6c4009
	{
Packit 6c4009
	  error ("no array-of-pointer declarations -- use typedef");
Packit 6c4009
	}
Packit 6c4009
      dec->rel = REL_VECTOR;
Packit 6c4009
      scan_num (&tok;;
Packit 6c4009
      dec->array_max = tok.str;
Packit 6c4009
      scan (TOK_RBRACKET, &tok;;
Packit 6c4009
    }
Packit 6c4009
  else if (peekscan (TOK_LANGLE, &tok))
Packit 6c4009
    {
Packit 6c4009
      if (dec->rel == REL_POINTER)
Packit 6c4009
	{
Packit 6c4009
	  error ("no array-of-pointer declarations -- use typedef");
Packit 6c4009
	}
Packit 6c4009
      dec->rel = REL_ARRAY;
Packit 6c4009
      if (peekscan (TOK_RANGLE, &tok))
Packit 6c4009
	{
Packit 6c4009
	  dec->array_max = "~0";	/* unspecified size, use max */
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  scan_num (&tok;;
Packit 6c4009
	  dec->array_max = tok.str;
Packit 6c4009
	  scan (TOK_RANGLE, &tok;;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  if (streq (dec->type, "opaque"))
Packit 6c4009
    {
Packit 6c4009
      if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR)
Packit 6c4009
	{
Packit 6c4009
	  error ("array declaration expected");
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else if (streq (dec->type, "string"))
Packit 6c4009
    {
Packit 6c4009
      if (dec->rel != REL_ARRAY)
Packit 6c4009
	{
Packit 6c4009
	  error ("variable-length array declaration expected");
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
  char name[MAXLINESIZE];		/* argument name */
Packit 6c4009
Packit 6c4009
  if (dkind == DEF_PROGRAM)
Packit 6c4009
    {
Packit 6c4009
      peek (&tok;;
Packit 6c4009
      if (tok.kind == TOK_RPAREN)
Packit 6c4009
	{			/* no arguments */
Packit 6c4009
	  dec->rel = REL_ALIAS;
Packit 6c4009
	  dec->type = "void";
Packit 6c4009
	  dec->prefix = NULL;
Packit 6c4009
	  dec->name = NULL;
Packit 6c4009
	  return;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  get_type (&dec->prefix, &dec->type, dkind);
Packit 6c4009
  dec->rel = REL_ALIAS;
Packit 6c4009
  if (peekscan (TOK_IDENT, &tok))	/* optional name of argument */
Packit 6c4009
    strcpy (name, tok.str);
Packit 6c4009
  else
Packit 6c4009
    sprintf (name, "%s%d", ARGNAME, num);	/* default name of argument */
Packit 6c4009
Packit 6c4009
  dec->name = (char *) strdup (name);
Packit 6c4009
Packit 6c4009
  if (streq (dec->type, "void"))
Packit 6c4009
    {
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (streq (dec->type, "opaque"))
Packit 6c4009
    {
Packit 6c4009
      error ("opaque -- illegal argument type");
Packit 6c4009
    }
Packit 6c4009
  if (peekscan (TOK_STAR, &tok))
Packit 6c4009
    {
Packit 6c4009
      if (streq (dec->type, "string"))
Packit 6c4009
	{
Packit 6c4009
	  error ("pointer to string not allowed in program arguments\n");
Packit 6c4009
	}
Packit 6c4009
      dec->rel = REL_POINTER;
Packit 6c4009
      if (peekscan (TOK_IDENT, &tok))	/* optional name of argument */
Packit 6c4009
	dec->name = strdup (tok.str);
Packit 6c4009
    }
Packit 6c4009
  if (peekscan (TOK_LANGLE, &tok))
Packit 6c4009
    {
Packit 6c4009
      if (!streq (dec->type, "string"))
Packit 6c4009
	{
Packit 6c4009
	  error ("arrays cannot be declared as arguments to procedures -- use typedef");
Packit 6c4009
	}
Packit 6c4009
      dec->rel = REL_ARRAY;
Packit 6c4009
      if (peekscan (TOK_RANGLE, &tok))
Packit 6c4009
	{
Packit 6c4009
	  dec->array_max = "~0";	/* unspecified size, use max */
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  scan_num (&tok;;
Packit 6c4009
	  dec->array_max = tok.str;
Packit 6c4009
	  scan (TOK_RANGLE, &tok;;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  if (streq (dec->type, "string"))
Packit 6c4009
    {
Packit 6c4009
      if (dec->rel != REL_ARRAY)
Packit 6c4009
	{			/* .x specifies just string as
Packit 6c4009
				 * type of argument
Packit 6c4009
				 * - make it string<>
Packit 6c4009
				 */
Packit 6c4009
	  dec->rel = REL_ARRAY;
Packit 6c4009
	  dec->array_max = "~0";	/* unspecified size, use max */
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
get_type (const char **prefixp, const char **typep, defkind dkind)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
Packit 6c4009
  *prefixp = NULL;
Packit 6c4009
  get_token (&tok;;
Packit 6c4009
  switch (tok.kind)
Packit 6c4009
    {
Packit 6c4009
    case TOK_IDENT:
Packit 6c4009
      *typep = tok.str;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_STRUCT:
Packit 6c4009
    case TOK_ENUM:
Packit 6c4009
    case TOK_UNION:
Packit 6c4009
      *prefixp = tok.str;
Packit 6c4009
      scan (TOK_IDENT, &tok;;
Packit 6c4009
      *typep = tok.str;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_UNSIGNED:
Packit 6c4009
      unsigned_dec (typep);
Packit 6c4009
      break;
Packit 6c4009
    case TOK_SHORT:
Packit 6c4009
      *typep = "short";
Packit 6c4009
      (void) peekscan (TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_LONG:
Packit 6c4009
      *typep = "long";
Packit 6c4009
      (void) peekscan (TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_HYPER:
Packit 6c4009
      *typep = "quad_t";
Packit 6c4009
      (void) peekscan(TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_VOID:
Packit 6c4009
      if (dkind != DEF_UNION && dkind != DEF_PROGRAM)
Packit 6c4009
	{
Packit 6c4009
	  error ("voids allowed only inside union and program definitions with one argument");
Packit 6c4009
	}
Packit 6c4009
      *typep = tok.str;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_STRING:
Packit 6c4009
    case TOK_OPAQUE:
Packit 6c4009
    case TOK_CHAR:
Packit 6c4009
    case TOK_INT:
Packit 6c4009
    case TOK_FLOAT:
Packit 6c4009
    case TOK_DOUBLE:
Packit 6c4009
    case TOK_BOOL:
Packit 6c4009
      *typep = tok.str;
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      error ("expected type specifier");
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
unsigned_dec (const char **typep)
Packit 6c4009
{
Packit 6c4009
  token tok;
Packit 6c4009
Packit 6c4009
  peek (&tok;;
Packit 6c4009
  switch (tok.kind)
Packit 6c4009
    {
Packit 6c4009
    case TOK_CHAR:
Packit 6c4009
      get_token (&tok;;
Packit 6c4009
      *typep = "u_char";
Packit 6c4009
      break;
Packit 6c4009
    case TOK_SHORT:
Packit 6c4009
      get_token (&tok;;
Packit 6c4009
      *typep = "u_short";
Packit 6c4009
      (void) peekscan (TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_LONG:
Packit 6c4009
      get_token (&tok;;
Packit 6c4009
      *typep = "u_long";
Packit 6c4009
      (void) peekscan (TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_HYPER:
Packit 6c4009
      get_token (&tok;;
Packit 6c4009
      *typep = "u_quad_t";
Packit 6c4009
      (void) peekscan(TOK_INT, &tok;;
Packit 6c4009
      break;
Packit 6c4009
    case TOK_INT:
Packit 6c4009
      get_token (&tok;;
Packit 6c4009
      *typep = "u_int";
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      *typep = "u_int";
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
}