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