Home | History | Annotate | Line # | Download | only in rpcgen
rpc_parse.c revision 1.6
      1  1.6  christos /*	$NetBSD: rpc_parse.c,v 1.6 1997/10/11 21:01:40 christos Exp $	*/
      2  1.1     glass /*
      3  1.1     glass  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
      4  1.1     glass  * unrestricted use provided that this legend is included on all tape
      5  1.1     glass  * media and as a part of the software program in whole or part.  Users
      6  1.1     glass  * may copy or modify Sun RPC without charge, but are not authorized
      7  1.1     glass  * to license or distribute it to anyone else except as part of a product or
      8  1.4        pk  * program developed by the user or with the express written consent of
      9  1.4        pk  * Sun Microsystems, Inc.
     10  1.4        pk  *
     11  1.1     glass  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     12  1.1     glass  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     13  1.1     glass  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     14  1.4        pk  *
     15  1.1     glass  * Sun RPC is provided with no support and without any obligation on the
     16  1.1     glass  * part of Sun Microsystems, Inc. to assist in its use, correction,
     17  1.1     glass  * modification or enhancement.
     18  1.4        pk  *
     19  1.1     glass  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     20  1.1     glass  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     21  1.1     glass  * OR ANY PART THEREOF.
     22  1.4        pk  *
     23  1.1     glass  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     24  1.1     glass  * or profits or other special, indirect and consequential damages, even if
     25  1.1     glass  * Sun has been advised of the possibility of such damages.
     26  1.4        pk  *
     27  1.1     glass  * Sun Microsystems, Inc.
     28  1.1     glass  * 2550 Garcia Avenue
     29  1.1     glass  * Mountain View, California  94043
     30  1.1     glass  */
     31  1.4        pk 
     32  1.6  christos #include <sys/cdefs.h>
     33  1.1     glass #ifndef lint
     34  1.6  christos #if 0
     35  1.4        pk static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
     36  1.6  christos #else
     37  1.6  christos __RCSID("$NetBSD: rpc_parse.c,v 1.6 1997/10/11 21:01:40 christos Exp $");
     38  1.6  christos #endif
     39  1.1     glass #endif
     40  1.1     glass 
     41  1.1     glass /*
     42  1.1     glass  * rpc_parse.c, Parser for the RPC protocol compiler
     43  1.1     glass  * Copyright (C) 1987 Sun Microsystems, Inc.
     44  1.1     glass  */
     45  1.1     glass #include <stdio.h>
     46  1.5       cgd #include <stdlib.h>
     47  1.5       cgd #include <string.h>
     48  1.4        pk #include "rpc/types.h"
     49  1.1     glass #include "rpc_scan.h"
     50  1.1     glass #include "rpc_parse.h"
     51  1.4        pk #include "rpc_util.h"
     52  1.4        pk 
     53  1.4        pk #define ARGNAME "arg"
     54  1.4        pk 
     55  1.6  christos static void isdefined __P((definition *));
     56  1.6  christos static void def_struct __P((definition *));
     57  1.6  christos static void def_program __P((definition *));
     58  1.6  christos static void def_enum __P((definition *));
     59  1.6  christos static void def_const __P((definition *));
     60  1.6  christos static void def_union __P((definition *));
     61  1.6  christos static void check_type_name __P((char *, int));
     62  1.6  christos static void def_typedef __P((definition *));
     63  1.6  christos static void get_declaration __P((declaration *, defkind));
     64  1.6  christos static void get_prog_declaration __P((declaration *, defkind, int));
     65  1.6  christos static void get_type __P((char **, char **, defkind));
     66  1.6  christos static void unsigned_dec __P((char **));
     67  1.1     glass 
     68  1.1     glass /*
     69  1.1     glass  * return the next definition you see
     70  1.1     glass  */
     71  1.1     glass definition *
     72  1.1     glass get_definition()
     73  1.1     glass {
     74  1.1     glass 	definition *defp;
     75  1.1     glass 	token tok;
     76  1.1     glass 
     77  1.1     glass 	defp = ALLOC(definition);
     78  1.1     glass 	get_token(&tok);
     79  1.1     glass 	switch (tok.kind) {
     80  1.1     glass 	case TOK_STRUCT:
     81  1.1     glass 		def_struct(defp);
     82  1.1     glass 		break;
     83  1.1     glass 	case TOK_UNION:
     84  1.1     glass 		def_union(defp);
     85  1.1     glass 		break;
     86  1.1     glass 	case TOK_TYPEDEF:
     87  1.1     glass 		def_typedef(defp);
     88  1.1     glass 		break;
     89  1.1     glass 	case TOK_ENUM:
     90  1.1     glass 		def_enum(defp);
     91  1.1     glass 		break;
     92  1.1     glass 	case TOK_PROGRAM:
     93  1.1     glass 		def_program(defp);
     94  1.1     glass 		break;
     95  1.1     glass 	case TOK_CONST:
     96  1.1     glass 		def_const(defp);
     97  1.1     glass 		break;
     98  1.1     glass 	case TOK_EOF:
     99  1.1     glass 		return (NULL);
    100  1.1     glass 	default:
    101  1.1     glass 		error("definition keyword expected");
    102  1.1     glass 	}
    103  1.1     glass 	scan(TOK_SEMICOLON, &tok);
    104  1.1     glass 	isdefined(defp);
    105  1.1     glass 	return (defp);
    106  1.1     glass }
    107  1.1     glass 
    108  1.6  christos static void
    109  1.1     glass isdefined(defp)
    110  1.1     glass 	definition *defp;
    111  1.1     glass {
    112  1.1     glass 	STOREVAL(&defined, defp);
    113  1.1     glass }
    114  1.1     glass 
    115  1.6  christos static void
    116  1.1     glass def_struct(defp)
    117  1.1     glass 	definition *defp;
    118  1.1     glass {
    119  1.1     glass 	token tok;
    120  1.1     glass 	declaration dec;
    121  1.1     glass 	decl_list *decls;
    122  1.1     glass 	decl_list **tailp;
    123  1.1     glass 
    124  1.1     glass 	defp->def_kind = DEF_STRUCT;
    125  1.1     glass 
    126  1.1     glass 	scan(TOK_IDENT, &tok);
    127  1.1     glass 	defp->def_name = tok.str;
    128  1.1     glass 	scan(TOK_LBRACE, &tok);
    129  1.1     glass 	tailp = &defp->def.st.decls;
    130  1.1     glass 	do {
    131  1.1     glass 		get_declaration(&dec, DEF_STRUCT);
    132  1.1     glass 		decls = ALLOC(decl_list);
    133  1.1     glass 		decls->decl = dec;
    134  1.1     glass 		*tailp = decls;
    135  1.1     glass 		tailp = &decls->next;
    136  1.1     glass 		scan(TOK_SEMICOLON, &tok);
    137  1.1     glass 		peek(&tok);
    138  1.1     glass 	} while (tok.kind != TOK_RBRACE);
    139  1.1     glass 	get_token(&tok);
    140  1.1     glass 	*tailp = NULL;
    141  1.1     glass }
    142  1.1     glass 
    143  1.6  christos static void
    144  1.1     glass def_program(defp)
    145  1.1     glass 	definition *defp;
    146  1.1     glass {
    147  1.1     glass 	token tok;
    148  1.4        pk 	declaration dec;
    149  1.4        pk 	decl_list *decls;
    150  1.4        pk 	decl_list **tailp;
    151  1.1     glass 	version_list *vlist;
    152  1.1     glass 	version_list **vtailp;
    153  1.1     glass 	proc_list *plist;
    154  1.1     glass 	proc_list **ptailp;
    155  1.4        pk 	int num_args;
    156  1.4        pk 	bool_t isvoid = FALSE; /* whether first argument is void */
    157  1.1     glass 	defp->def_kind = DEF_PROGRAM;
    158  1.1     glass 	scan(TOK_IDENT, &tok);
    159  1.1     glass 	defp->def_name = tok.str;
    160  1.1     glass 	scan(TOK_LBRACE, &tok);
    161  1.1     glass 	vtailp = &defp->def.pr.versions;
    162  1.4        pk 	tailp = &defp->def.st.decls;
    163  1.1     glass 	scan(TOK_VERSION, &tok);
    164  1.1     glass 	do {
    165  1.1     glass 		scan(TOK_IDENT, &tok);
    166  1.1     glass 		vlist = ALLOC(version_list);
    167  1.1     glass 		vlist->vers_name = tok.str;
    168  1.1     glass 		scan(TOK_LBRACE, &tok);
    169  1.1     glass 		ptailp = &vlist->procs;
    170  1.1     glass 		do {
    171  1.4        pk 			/* get result type */
    172  1.1     glass 			plist = ALLOC(proc_list);
    173  1.4        pk 			get_type(&plist->res_prefix, &plist->res_type,
    174  1.4        pk 				 DEF_PROGRAM);
    175  1.1     glass 			if (streq(plist->res_type, "opaque")) {
    176  1.1     glass 				error("illegal result type");
    177  1.1     glass 			}
    178  1.1     glass 			scan(TOK_IDENT, &tok);
    179  1.1     glass 			plist->proc_name = tok.str;
    180  1.1     glass 			scan(TOK_LPAREN, &tok);
    181  1.4        pk 			/* get args - first one*/
    182  1.4        pk 			num_args = 1;
    183  1.4        pk 			isvoid = FALSE;
    184  1.4        pk 			/* type of DEF_PROGRAM in the first
    185  1.4        pk 			 * get_prog_declaration and DEF_STURCT in the next
    186  1.4        pk 			 * allows void as argument if it is the only argument
    187  1.4        pk 			 */
    188  1.4        pk 			get_prog_declaration(&dec, DEF_PROGRAM, num_args);
    189  1.4        pk 			if (streq(dec.type, "void"))
    190  1.4        pk 			  isvoid = TRUE;
    191  1.4        pk 			decls = ALLOC(decl_list);
    192  1.4        pk 			plist->args.decls = decls;
    193  1.4        pk 			decls->decl = dec;
    194  1.4        pk 			tailp = &decls->next;
    195  1.4        pk 			/* get args */
    196  1.4        pk 			while(peekscan(TOK_COMMA, &tok)) {
    197  1.4        pk 			  num_args++;
    198  1.4        pk 			  get_prog_declaration(&dec, DEF_STRUCT,
    199  1.4        pk 					       num_args);
    200  1.4        pk 			  decls = ALLOC(decl_list);
    201  1.4        pk 			  decls->decl = dec;
    202  1.4        pk 			  *tailp = decls;
    203  1.4        pk 			  if (streq(dec.type, "void"))
    204  1.4        pk 			    isvoid = TRUE;
    205  1.4        pk 			  tailp = &decls->next;
    206  1.1     glass 			}
    207  1.4        pk 			/* multiple arguments are only allowed in newstyle */
    208  1.4        pk 			if( !newstyle && num_args > 1 ) {
    209  1.4        pk 			  error("only one argument is allowed" );
    210  1.4        pk 			}
    211  1.4        pk 			if (isvoid && num_args > 1) {
    212  1.4        pk 			  error("illegal use of void in program definition");
    213  1.4        pk 			}
    214  1.4        pk 			*tailp = NULL;
    215  1.1     glass 			scan(TOK_RPAREN, &tok);
    216  1.1     glass 			scan(TOK_EQUAL, &tok);
    217  1.1     glass 			scan_num(&tok);
    218  1.1     glass 			scan(TOK_SEMICOLON, &tok);
    219  1.1     glass 			plist->proc_num = tok.str;
    220  1.4        pk 			plist->arg_num = num_args;
    221  1.1     glass 			*ptailp = plist;
    222  1.1     glass 			ptailp = &plist->next;
    223  1.1     glass 			peek(&tok);
    224  1.1     glass 		} while (tok.kind != TOK_RBRACE);
    225  1.4        pk 		*ptailp = NULL;
    226  1.1     glass 		*vtailp = vlist;
    227  1.1     glass 		vtailp = &vlist->next;
    228  1.1     glass 		scan(TOK_RBRACE, &tok);
    229  1.1     glass 		scan(TOK_EQUAL, &tok);
    230  1.1     glass 		scan_num(&tok);
    231  1.1     glass 		vlist->vers_num = tok.str;
    232  1.4        pk 		/* make the argument structure name for each arg*/
    233  1.4        pk 		for(plist = vlist->procs; plist != NULL;
    234  1.4        pk 		    plist = plist->next) {
    235  1.4        pk 			plist->args.argname = make_argname(plist->proc_name,
    236  1.4        pk 							   vlist->vers_num);
    237  1.4        pk 			/* free the memory ??*/
    238  1.4        pk 		}
    239  1.1     glass 		scan(TOK_SEMICOLON, &tok);
    240  1.1     glass 		scan2(TOK_VERSION, TOK_RBRACE, &tok);
    241  1.1     glass 	} while (tok.kind == TOK_VERSION);
    242  1.1     glass 	scan(TOK_EQUAL, &tok);
    243  1.1     glass 	scan_num(&tok);
    244  1.1     glass 	defp->def.pr.prog_num = tok.str;
    245  1.1     glass 	*vtailp = NULL;
    246  1.1     glass }
    247  1.1     glass 
    248  1.4        pk 
    249  1.6  christos static void
    250  1.1     glass def_enum(defp)
    251  1.1     glass 	definition *defp;
    252  1.1     glass {
    253  1.1     glass 	token tok;
    254  1.1     glass 	enumval_list *elist;
    255  1.1     glass 	enumval_list **tailp;
    256  1.1     glass 
    257  1.1     glass 	defp->def_kind = DEF_ENUM;
    258  1.1     glass 	scan(TOK_IDENT, &tok);
    259  1.1     glass 	defp->def_name = tok.str;
    260  1.1     glass 	scan(TOK_LBRACE, &tok);
    261  1.1     glass 	tailp = &defp->def.en.vals;
    262  1.1     glass 	do {
    263  1.1     glass 		scan(TOK_IDENT, &tok);
    264  1.1     glass 		elist = ALLOC(enumval_list);
    265  1.1     glass 		elist->name = tok.str;
    266  1.1     glass 		elist->assignment = NULL;
    267  1.1     glass 		scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
    268  1.1     glass 		if (tok.kind == TOK_EQUAL) {
    269  1.1     glass 			scan_num(&tok);
    270  1.1     glass 			elist->assignment = tok.str;
    271  1.1     glass 			scan2(TOK_COMMA, TOK_RBRACE, &tok);
    272  1.1     glass 		}
    273  1.1     glass 		*tailp = elist;
    274  1.1     glass 		tailp = &elist->next;
    275  1.1     glass 	} while (tok.kind != TOK_RBRACE);
    276  1.1     glass 	*tailp = NULL;
    277  1.1     glass }
    278  1.1     glass 
    279  1.6  christos static void
    280  1.1     glass def_const(defp)
    281  1.1     glass 	definition *defp;
    282  1.1     glass {
    283  1.1     glass 	token tok;
    284  1.1     glass 
    285  1.1     glass 	defp->def_kind = DEF_CONST;
    286  1.1     glass 	scan(TOK_IDENT, &tok);
    287  1.1     glass 	defp->def_name = tok.str;
    288  1.1     glass 	scan(TOK_EQUAL, &tok);
    289  1.1     glass 	scan2(TOK_IDENT, TOK_STRCONST, &tok);
    290  1.1     glass 	defp->def.co = tok.str;
    291  1.1     glass }
    292  1.1     glass 
    293  1.6  christos static void
    294  1.1     glass def_union(defp)
    295  1.1     glass 	definition *defp;
    296  1.1     glass {
    297  1.4        pk   token tok;
    298  1.4        pk   declaration dec;
    299  1.6  christos   case_list *cases;
    300  1.4        pk   case_list **tailp;
    301  1.4        pk   int flag;
    302  1.4        pk 
    303  1.4        pk   defp->def_kind = DEF_UNION;
    304  1.4        pk   scan(TOK_IDENT, &tok);
    305  1.4        pk   defp->def_name = tok.str;
    306  1.4        pk   scan(TOK_SWITCH, &tok);
    307  1.4        pk   scan(TOK_LPAREN, &tok);
    308  1.4        pk   get_declaration(&dec, DEF_UNION);
    309  1.4        pk   defp->def.un.enum_decl = dec;
    310  1.4        pk   tailp = &defp->def.un.cases;
    311  1.4        pk   scan(TOK_RPAREN, &tok);
    312  1.4        pk   scan(TOK_LBRACE, &tok);
    313  1.4        pk   scan(TOK_CASE, &tok);
    314  1.4        pk   while (tok.kind == TOK_CASE) {
    315  1.4        pk     scan2(TOK_IDENT, TOK_CHARCONST, &tok);
    316  1.4        pk     cases = ALLOC(case_list);
    317  1.4        pk     cases->case_name = tok.str;
    318  1.4        pk     scan(TOK_COLON, &tok);
    319  1.4        pk     /* now peek at next token */
    320  1.4        pk     flag=0;
    321  1.4        pk     if(peekscan(TOK_CASE,&tok))
    322  1.4        pk       {
    323  1.4        pk 
    324  1.4        pk 	do
    325  1.4        pk 	  {
    326  1.4        pk 	    scan2(TOK_IDENT, TOK_CHARCONST, &tok);
    327  1.4        pk 	    cases->contflag=1;	/* continued case statement */
    328  1.4        pk 	    *tailp = cases;
    329  1.4        pk 	    tailp = &cases->next;
    330  1.4        pk 	    cases = ALLOC(case_list);
    331  1.4        pk 	    cases->case_name = tok.str;
    332  1.4        pk 	    scan(TOK_COLON, &tok);
    333  1.4        pk 
    334  1.4        pk 	  }while(peekscan(TOK_CASE,&tok));
    335  1.4        pk       }
    336  1.4        pk     else
    337  1.4        pk       if(flag)
    338  1.4        pk 	{
    339  1.4        pk 
    340  1.4        pk 	  *tailp = cases;
    341  1.4        pk 	  tailp = &cases->next;
    342  1.4        pk 	  cases = ALLOC(case_list);
    343  1.4        pk 	};
    344  1.4        pk 
    345  1.4        pk     get_declaration(&dec, DEF_UNION);
    346  1.4        pk     cases->case_decl = dec;
    347  1.4        pk     cases->contflag=0;		/* no continued case statement */
    348  1.4        pk     *tailp = cases;
    349  1.4        pk     tailp = &cases->next;
    350  1.4        pk     scan(TOK_SEMICOLON, &tok);
    351  1.4        pk 
    352  1.4        pk     scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
    353  1.4        pk   }
    354  1.4        pk   *tailp = NULL;
    355  1.4        pk   if (tok.kind == TOK_DEFAULT) {
    356  1.4        pk     scan(TOK_COLON, &tok);
    357  1.4        pk     get_declaration(&dec, DEF_UNION);
    358  1.4        pk     defp->def.un.default_decl = ALLOC(declaration);
    359  1.4        pk     *defp->def.un.default_decl = dec;
    360  1.4        pk     scan(TOK_SEMICOLON, &tok);
    361  1.4        pk     scan(TOK_RBRACE, &tok);
    362  1.4        pk   } else {
    363  1.4        pk     defp->def.un.default_decl = NULL;
    364  1.4        pk   }
    365  1.4        pk }
    366  1.4        pk 
    367  1.4        pk static char* reserved_words[] = {
    368  1.4        pk 	"array",
    369  1.4        pk 	"bytes",
    370  1.4        pk 	"destroy",
    371  1.4        pk 	"free",
    372  1.4        pk 	"getpos",
    373  1.4        pk 	"inline",
    374  1.4        pk 	"pointer",
    375  1.4        pk 	"reference",
    376  1.4        pk 	"setpos",
    377  1.4        pk 	"sizeof",
    378  1.4        pk 	"union",
    379  1.4        pk 	"vector",
    380  1.4        pk 	NULL
    381  1.4        pk };
    382  1.4        pk 
    383  1.4        pk static char* reserved_types[] = {
    384  1.4        pk 	"opaque",
    385  1.4        pk 	"string",
    386  1.4        pk 	NULL
    387  1.4        pk };
    388  1.4        pk 
    389  1.4        pk /* check that the given name is not one that would eventually result in
    390  1.4        pk    xdr routines that would conflict with internal XDR routines. */
    391  1.6  christos static void
    392  1.6  christos check_type_name( name, new_type )
    393  1.4        pk int new_type;
    394  1.4        pk char* name;
    395  1.4        pk {
    396  1.4        pk   int i;
    397  1.4        pk   char tmp[100];
    398  1.1     glass 
    399  1.4        pk   for( i = 0; reserved_words[i] != NULL; i++ ) {
    400  1.4        pk     if( strcmp( name, reserved_words[i] ) == 0 ) {
    401  1.4        pk       sprintf(tmp,
    402  1.4        pk 	      "illegal (reserved) name :\'%s\' in type definition", name );
    403  1.4        pk       error(tmp);
    404  1.4        pk     }
    405  1.4        pk   }
    406  1.4        pk   if( new_type ) {
    407  1.4        pk     for( i = 0; reserved_types[i] != NULL; i++ ) {
    408  1.4        pk       if( strcmp( name, reserved_types[i] ) == 0 ) {
    409  1.4        pk 	sprintf(tmp,
    410  1.4        pk 		"illegal (reserved) name :\'%s\' in type definition", name );
    411  1.4        pk 	error(tmp);
    412  1.4        pk       }
    413  1.4        pk     }
    414  1.4        pk   }
    415  1.1     glass }
    416  1.1     glass 
    417  1.6  christos static void
    418  1.1     glass def_typedef(defp)
    419  1.1     glass 	definition *defp;
    420  1.1     glass {
    421  1.1     glass 	declaration dec;
    422  1.1     glass 
    423  1.1     glass 	defp->def_kind = DEF_TYPEDEF;
    424  1.1     glass 	get_declaration(&dec, DEF_TYPEDEF);
    425  1.1     glass 	defp->def_name = dec.name;
    426  1.4        pk 	check_type_name( dec.name, 1 );
    427  1.1     glass 	defp->def.ty.old_prefix = dec.prefix;
    428  1.1     glass 	defp->def.ty.old_type = dec.type;
    429  1.1     glass 	defp->def.ty.rel = dec.rel;
    430  1.1     glass 	defp->def.ty.array_max = dec.array_max;
    431  1.1     glass }
    432  1.1     glass 
    433  1.6  christos static void
    434  1.1     glass get_declaration(dec, dkind)
    435  1.1     glass 	declaration *dec;
    436  1.1     glass 	defkind dkind;
    437  1.1     glass {
    438  1.1     glass 	token tok;
    439  1.1     glass 
    440  1.1     glass 	get_type(&dec->prefix, &dec->type, dkind);
    441  1.1     glass 	dec->rel = REL_ALIAS;
    442  1.1     glass 	if (streq(dec->type, "void")) {
    443  1.1     glass 		return;
    444  1.1     glass 	}
    445  1.4        pk 
    446  1.4        pk 	check_type_name( dec->type, 0 );
    447  1.4        pk 
    448  1.1     glass 	scan2(TOK_STAR, TOK_IDENT, &tok);
    449  1.1     glass 	if (tok.kind == TOK_STAR) {
    450  1.1     glass 		dec->rel = REL_POINTER;
    451  1.1     glass 		scan(TOK_IDENT, &tok);
    452  1.1     glass 	}
    453  1.1     glass 	dec->name = tok.str;
    454  1.1     glass 	if (peekscan(TOK_LBRACKET, &tok)) {
    455  1.1     glass 		if (dec->rel == REL_POINTER) {
    456  1.1     glass 			error("no array-of-pointer declarations -- use typedef");
    457  1.1     glass 		}
    458  1.1     glass 		dec->rel = REL_VECTOR;
    459  1.1     glass 		scan_num(&tok);
    460  1.1     glass 		dec->array_max = tok.str;
    461  1.1     glass 		scan(TOK_RBRACKET, &tok);
    462  1.1     glass 	} else if (peekscan(TOK_LANGLE, &tok)) {
    463  1.1     glass 		if (dec->rel == REL_POINTER) {
    464  1.1     glass 			error("no array-of-pointer declarations -- use typedef");
    465  1.1     glass 		}
    466  1.1     glass 		dec->rel = REL_ARRAY;
    467  1.1     glass 		if (peekscan(TOK_RANGLE, &tok)) {
    468  1.1     glass 			dec->array_max = "~0";	/* unspecified size, use max */
    469  1.1     glass 		} else {
    470  1.1     glass 			scan_num(&tok);
    471  1.1     glass 			dec->array_max = tok.str;
    472  1.1     glass 			scan(TOK_RANGLE, &tok);
    473  1.1     glass 		}
    474  1.1     glass 	}
    475  1.1     glass 	if (streq(dec->type, "opaque")) {
    476  1.1     glass 		if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
    477  1.1     glass 			error("array declaration expected");
    478  1.1     glass 		}
    479  1.1     glass 	} else if (streq(dec->type, "string")) {
    480  1.1     glass 		if (dec->rel != REL_ARRAY) {
    481  1.1     glass 			error("variable-length array declaration expected");
    482  1.1     glass 		}
    483  1.1     glass 	}
    484  1.1     glass }
    485  1.1     glass 
    486  1.6  christos static void
    487  1.4        pk get_prog_declaration(dec, dkind, num)
    488  1.4        pk 	declaration *dec;
    489  1.4        pk 	defkind dkind;
    490  1.4        pk         int num;  /* arg number */
    491  1.4        pk {
    492  1.4        pk 	token tok;
    493  1.4        pk 	char name[10]; /* argument name */
    494  1.4        pk 
    495  1.4        pk 	if (dkind == DEF_PROGRAM) {
    496  1.4        pk 	  peek(&tok);
    497  1.4        pk 	  if (tok.kind == TOK_RPAREN) { /* no arguments */
    498  1.4        pk 	    	dec->rel = REL_ALIAS;
    499  1.4        pk 		dec->type = "void";
    500  1.4        pk 		dec->prefix = NULL;
    501  1.4        pk 		dec->name = NULL;
    502  1.4        pk 		return;
    503  1.4        pk 	      }
    504  1.4        pk 	}
    505  1.4        pk 	get_type(&dec->prefix, &dec->type, dkind);
    506  1.4        pk 	dec->rel = REL_ALIAS;
    507  1.4        pk 	if (peekscan(TOK_IDENT, &tok))  /* optional name of argument */
    508  1.4        pk 		strcpy(name, tok.str);
    509  1.4        pk 	else
    510  1.4        pk 		sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */
    511  1.4        pk 
    512  1.4        pk 	dec->name = (char *)strdup(name);
    513  1.4        pk 
    514  1.4        pk 	if (streq(dec->type, "void")) {
    515  1.4        pk 		return;
    516  1.4        pk 	}
    517  1.4        pk 
    518  1.4        pk 	if (streq(dec->type, "opaque")) {
    519  1.4        pk 		error("opaque -- illegal argument type");
    520  1.4        pk 	}
    521  1.4        pk 	if (peekscan(TOK_STAR, &tok)) {
    522  1.4        pk 	  if (streq(dec->type, "string")) {
    523  1.4        pk 	    error("pointer to string not allowed in program arguments\n");
    524  1.4        pk 	  }
    525  1.4        pk 		dec->rel = REL_POINTER;
    526  1.4        pk 		if (peekscan(TOK_IDENT, &tok))  /* optional name of argument */
    527  1.4        pk 		  dec->name = (char *)strdup(tok.str);
    528  1.4        pk       }
    529  1.4        pk 	  if (peekscan(TOK_LANGLE, &tok)) {
    530  1.4        pk 	    if (!streq(dec->type, "string")) {
    531  1.4        pk 	      error("arrays cannot be declared as arguments to procedures -- use typedef");
    532  1.4        pk 	    }
    533  1.4        pk 		dec->rel = REL_ARRAY;
    534  1.4        pk 		if (peekscan(TOK_RANGLE, &tok)) {
    535  1.4        pk 			dec->array_max = "~0";/* unspecified size, use max */
    536  1.4        pk 		} else {
    537  1.4        pk 			scan_num(&tok);
    538  1.4        pk 			dec->array_max = tok.str;
    539  1.4        pk 			scan(TOK_RANGLE, &tok);
    540  1.4        pk 		}
    541  1.4        pk 	}
    542  1.4        pk 	if (streq(dec->type, "string")) {
    543  1.4        pk 		if (dec->rel != REL_ARRAY) {  /* .x specifies just string as
    544  1.4        pk 					       * type of argument
    545  1.4        pk 					       * - make it string<>
    546  1.4        pk 					       */
    547  1.4        pk 			dec->rel = REL_ARRAY;
    548  1.4        pk 			dec->array_max = "~0";/* unspecified size, use max */
    549  1.4        pk 		}
    550  1.4        pk 	}
    551  1.4        pk }
    552  1.4        pk 
    553  1.4        pk 
    554  1.1     glass 
    555  1.6  christos static void
    556  1.1     glass get_type(prefixp, typep, dkind)
    557  1.1     glass 	char **prefixp;
    558  1.1     glass 	char **typep;
    559  1.1     glass 	defkind dkind;
    560  1.1     glass {
    561  1.1     glass 	token tok;
    562  1.1     glass 
    563  1.1     glass 	*prefixp = NULL;
    564  1.1     glass 	get_token(&tok);
    565  1.1     glass 	switch (tok.kind) {
    566  1.1     glass 	case TOK_IDENT:
    567  1.1     glass 		*typep = tok.str;
    568  1.1     glass 		break;
    569  1.1     glass 	case TOK_STRUCT:
    570  1.1     glass 	case TOK_ENUM:
    571  1.1     glass 	case TOK_UNION:
    572  1.1     glass 		*prefixp = tok.str;
    573  1.1     glass 		scan(TOK_IDENT, &tok);
    574  1.1     glass 		*typep = tok.str;
    575  1.1     glass 		break;
    576  1.1     glass 	case TOK_UNSIGNED:
    577  1.1     glass 		unsigned_dec(typep);
    578  1.1     glass 		break;
    579  1.1     glass 	case TOK_SHORT:
    580  1.1     glass 		*typep = "short";
    581  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    582  1.1     glass 		break;
    583  1.1     glass 	case TOK_LONG:
    584  1.1     glass 		*typep = "long";
    585  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    586  1.1     glass 		break;
    587  1.1     glass 	case TOK_VOID:
    588  1.1     glass 		if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
    589  1.4        pk 			error("voids allowed only inside union and program definitions with one argument");
    590  1.1     glass 		}
    591  1.1     glass 		*typep = tok.str;
    592  1.1     glass 		break;
    593  1.1     glass 	case TOK_STRING:
    594  1.1     glass 	case TOK_OPAQUE:
    595  1.1     glass 	case TOK_CHAR:
    596  1.1     glass 	case TOK_INT:
    597  1.1     glass 	case TOK_FLOAT:
    598  1.1     glass 	case TOK_DOUBLE:
    599  1.1     glass 	case TOK_BOOL:
    600  1.1     glass 		*typep = tok.str;
    601  1.1     glass 		break;
    602  1.1     glass 	default:
    603  1.1     glass 		error("expected type specifier");
    604  1.1     glass 	}
    605  1.1     glass }
    606  1.1     glass 
    607  1.6  christos static void
    608  1.1     glass unsigned_dec(typep)
    609  1.1     glass 	char **typep;
    610  1.1     glass {
    611  1.1     glass 	token tok;
    612  1.1     glass 
    613  1.1     glass 	peek(&tok);
    614  1.1     glass 	switch (tok.kind) {
    615  1.1     glass 	case TOK_CHAR:
    616  1.1     glass 		get_token(&tok);
    617  1.1     glass 		*typep = "u_char";
    618  1.1     glass 		break;
    619  1.1     glass 	case TOK_SHORT:
    620  1.1     glass 		get_token(&tok);
    621  1.1     glass 		*typep = "u_short";
    622  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    623  1.1     glass 		break;
    624  1.1     glass 	case TOK_LONG:
    625  1.1     glass 		get_token(&tok);
    626  1.1     glass 		*typep = "u_long";
    627  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    628  1.1     glass 		break;
    629  1.1     glass 	case TOK_INT:
    630  1.1     glass 		get_token(&tok);
    631  1.1     glass 		*typep = "u_int";
    632  1.1     glass 		break;
    633  1.1     glass 	default:
    634  1.1     glass 		*typep = "u_int";
    635  1.1     glass 		break;
    636  1.1     glass 	}
    637  1.1     glass }
    638