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