Home | History | Annotate | Line # | Download | only in rpcgen
rpc_parse.c revision 1.9
      1  1.8     lukem /*	$NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem 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.8     lukem __RCSID("$NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $");
     38  1.6  christos #endif
     39  1.1     glass #endif
     40  1.1     glass 
     41  1.1     glass /*
     42  1.7     lukem  * 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.7     lukem 	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.7     lukem 	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.7     lukem 	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.7     lukem 	int     num_args;
    156  1.7     lukem 	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.7     lukem 			get_type(&plist->res_prefix, &plist->res_type,
    174  1.7     lukem 			    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.7     lukem 			/* get args - first one */
    182  1.4        pk 			num_args = 1;
    183  1.4        pk 			isvoid = FALSE;
    184  1.7     lukem 			/* type of DEF_PROGRAM in the first
    185  1.4        pk 			 * get_prog_declaration and DEF_STURCT in the next
    186  1.7     lukem 			 * allows void as argument if it is the only argument */
    187  1.4        pk 			get_prog_declaration(&dec, DEF_PROGRAM, num_args);
    188  1.4        pk 			if (streq(dec.type, "void"))
    189  1.7     lukem 				isvoid = TRUE;
    190  1.4        pk 			decls = ALLOC(decl_list);
    191  1.4        pk 			plist->args.decls = decls;
    192  1.4        pk 			decls->decl = dec;
    193  1.4        pk 			tailp = &decls->next;
    194  1.4        pk 			/* get args */
    195  1.7     lukem 			while (peekscan(TOK_COMMA, &tok)) {
    196  1.7     lukem 				num_args++;
    197  1.7     lukem 				get_prog_declaration(&dec, DEF_STRUCT,
    198  1.7     lukem 				    num_args);
    199  1.7     lukem 				decls = ALLOC(decl_list);
    200  1.7     lukem 				decls->decl = dec;
    201  1.7     lukem 				*tailp = decls;
    202  1.7     lukem 				if (streq(dec.type, "void"))
    203  1.7     lukem 					isvoid = TRUE;
    204  1.7     lukem 				tailp = &decls->next;
    205  1.1     glass 			}
    206  1.4        pk 			/* multiple arguments are only allowed in newstyle */
    207  1.7     lukem 			if (!newstyle && num_args > 1) {
    208  1.7     lukem 				error("only one argument is allowed");
    209  1.4        pk 			}
    210  1.7     lukem 			if (isvoid && num_args > 1) {
    211  1.7     lukem 				error("illegal use of void in program definition");
    212  1.4        pk 			}
    213  1.4        pk 			*tailp = NULL;
    214  1.1     glass 			scan(TOK_RPAREN, &tok);
    215  1.1     glass 			scan(TOK_EQUAL, &tok);
    216  1.1     glass 			scan_num(&tok);
    217  1.1     glass 			scan(TOK_SEMICOLON, &tok);
    218  1.1     glass 			plist->proc_num = tok.str;
    219  1.4        pk 			plist->arg_num = num_args;
    220  1.1     glass 			*ptailp = plist;
    221  1.1     glass 			ptailp = &plist->next;
    222  1.1     glass 			peek(&tok);
    223  1.1     glass 		} while (tok.kind != TOK_RBRACE);
    224  1.4        pk 		*ptailp = NULL;
    225  1.1     glass 		*vtailp = vlist;
    226  1.1     glass 		vtailp = &vlist->next;
    227  1.1     glass 		scan(TOK_RBRACE, &tok);
    228  1.1     glass 		scan(TOK_EQUAL, &tok);
    229  1.1     glass 		scan_num(&tok);
    230  1.1     glass 		vlist->vers_num = tok.str;
    231  1.7     lukem 		/* make the argument structure name for each arg */
    232  1.7     lukem 		for (plist = vlist->procs; plist != NULL;
    233  1.4        pk 		    plist = plist->next) {
    234  1.4        pk 			plist->args.argname = make_argname(plist->proc_name,
    235  1.7     lukem 			    vlist->vers_num);
    236  1.7     lukem 			/* free the memory ?? */
    237  1.4        pk 		}
    238  1.1     glass 		scan(TOK_SEMICOLON, &tok);
    239  1.1     glass 		scan2(TOK_VERSION, TOK_RBRACE, &tok);
    240  1.1     glass 	} while (tok.kind == TOK_VERSION);
    241  1.1     glass 	scan(TOK_EQUAL, &tok);
    242  1.1     glass 	scan_num(&tok);
    243  1.1     glass 	defp->def.pr.prog_num = tok.str;
    244  1.1     glass 	*vtailp = NULL;
    245  1.1     glass }
    246  1.1     glass 
    247  1.4        pk 
    248  1.6  christos static void
    249  1.1     glass def_enum(defp)
    250  1.1     glass 	definition *defp;
    251  1.1     glass {
    252  1.7     lukem 	token   tok;
    253  1.1     glass 	enumval_list *elist;
    254  1.1     glass 	enumval_list **tailp;
    255  1.1     glass 
    256  1.1     glass 	defp->def_kind = DEF_ENUM;
    257  1.1     glass 	scan(TOK_IDENT, &tok);
    258  1.1     glass 	defp->def_name = tok.str;
    259  1.1     glass 	scan(TOK_LBRACE, &tok);
    260  1.1     glass 	tailp = &defp->def.en.vals;
    261  1.1     glass 	do {
    262  1.1     glass 		scan(TOK_IDENT, &tok);
    263  1.1     glass 		elist = ALLOC(enumval_list);
    264  1.1     glass 		elist->name = tok.str;
    265  1.1     glass 		elist->assignment = NULL;
    266  1.1     glass 		scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
    267  1.1     glass 		if (tok.kind == TOK_EQUAL) {
    268  1.1     glass 			scan_num(&tok);
    269  1.1     glass 			elist->assignment = tok.str;
    270  1.1     glass 			scan2(TOK_COMMA, TOK_RBRACE, &tok);
    271  1.1     glass 		}
    272  1.1     glass 		*tailp = elist;
    273  1.1     glass 		tailp = &elist->next;
    274  1.1     glass 	} while (tok.kind != TOK_RBRACE);
    275  1.1     glass 	*tailp = NULL;
    276  1.1     glass }
    277  1.1     glass 
    278  1.6  christos static void
    279  1.1     glass def_const(defp)
    280  1.1     glass 	definition *defp;
    281  1.1     glass {
    282  1.7     lukem 	token   tok;
    283  1.1     glass 
    284  1.1     glass 	defp->def_kind = DEF_CONST;
    285  1.1     glass 	scan(TOK_IDENT, &tok);
    286  1.1     glass 	defp->def_name = tok.str;
    287  1.1     glass 	scan(TOK_EQUAL, &tok);
    288  1.1     glass 	scan2(TOK_IDENT, TOK_STRCONST, &tok);
    289  1.1     glass 	defp->def.co = tok.str;
    290  1.1     glass }
    291  1.1     glass 
    292  1.6  christos static void
    293  1.1     glass def_union(defp)
    294  1.1     glass 	definition *defp;
    295  1.1     glass {
    296  1.7     lukem 	token   tok;
    297  1.7     lukem 	declaration dec;
    298  1.7     lukem 	case_list *cases;
    299  1.7     lukem 	case_list **tailp;
    300  1.7     lukem 	int     flag;
    301  1.7     lukem 
    302  1.7     lukem 	defp->def_kind = DEF_UNION;
    303  1.7     lukem 	scan(TOK_IDENT, &tok);
    304  1.7     lukem 	defp->def_name = tok.str;
    305  1.7     lukem 	scan(TOK_SWITCH, &tok);
    306  1.7     lukem 	scan(TOK_LPAREN, &tok);
    307  1.7     lukem 	get_declaration(&dec, DEF_UNION);
    308  1.7     lukem 	defp->def.un.enum_decl = dec;
    309  1.7     lukem 	tailp = &defp->def.un.cases;
    310  1.7     lukem 	scan(TOK_RPAREN, &tok);
    311  1.7     lukem 	scan(TOK_LBRACE, &tok);
    312  1.7     lukem 	scan(TOK_CASE, &tok);
    313  1.7     lukem 	while (tok.kind == TOK_CASE) {
    314  1.7     lukem 		scan2(TOK_IDENT, TOK_CHARCONST, &tok);
    315  1.7     lukem 		cases = ALLOC(case_list);
    316  1.7     lukem 		cases->case_name = tok.str;
    317  1.7     lukem 		scan(TOK_COLON, &tok);
    318  1.7     lukem 		/* now peek at next token */
    319  1.7     lukem 		flag = 0;
    320  1.7     lukem 		if (peekscan(TOK_CASE, &tok)) {
    321  1.7     lukem 
    322  1.7     lukem 			do {
    323  1.7     lukem 				scan2(TOK_IDENT, TOK_CHARCONST, &tok);
    324  1.7     lukem 				cases->contflag = 1;	/* continued case
    325  1.7     lukem 							 * statement */
    326  1.7     lukem 				*tailp = cases;
    327  1.7     lukem 				tailp = &cases->next;
    328  1.7     lukem 				cases = ALLOC(case_list);
    329  1.7     lukem 				cases->case_name = tok.str;
    330  1.7     lukem 				scan(TOK_COLON, &tok);
    331  1.7     lukem 
    332  1.7     lukem 			} while (peekscan(TOK_CASE, &tok));
    333  1.7     lukem 		} else
    334  1.7     lukem 			if (flag) {
    335  1.7     lukem 
    336  1.7     lukem 				*tailp = cases;
    337  1.7     lukem 				tailp = &cases->next;
    338  1.7     lukem 				cases = ALLOC(case_list);
    339  1.7     lukem 			};
    340  1.7     lukem 
    341  1.7     lukem 		get_declaration(&dec, DEF_UNION);
    342  1.7     lukem 		cases->case_decl = dec;
    343  1.7     lukem 		cases->contflag = 0;	/* no continued case statement */
    344  1.7     lukem 		*tailp = cases;
    345  1.7     lukem 		tailp = &cases->next;
    346  1.7     lukem 		scan(TOK_SEMICOLON, &tok);
    347  1.7     lukem 
    348  1.7     lukem 		scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
    349  1.7     lukem 	}
    350  1.7     lukem 	*tailp = NULL;
    351  1.7     lukem 	if (tok.kind == TOK_DEFAULT) {
    352  1.7     lukem 		scan(TOK_COLON, &tok);
    353  1.7     lukem 		get_declaration(&dec, DEF_UNION);
    354  1.7     lukem 		defp->def.un.default_decl = ALLOC(declaration);
    355  1.7     lukem 		*defp->def.un.default_decl = dec;
    356  1.7     lukem 		scan(TOK_SEMICOLON, &tok);
    357  1.7     lukem 		scan(TOK_RBRACE, &tok);
    358  1.7     lukem 	} else {
    359  1.7     lukem 		defp->def.un.default_decl = NULL;
    360  1.7     lukem 	}
    361  1.4        pk }
    362  1.4        pk 
    363  1.7     lukem static char *reserved_words[] = {
    364  1.4        pk 	"array",
    365  1.4        pk 	"bytes",
    366  1.4        pk 	"destroy",
    367  1.4        pk 	"free",
    368  1.4        pk 	"getpos",
    369  1.4        pk 	"inline",
    370  1.4        pk 	"pointer",
    371  1.4        pk 	"reference",
    372  1.4        pk 	"setpos",
    373  1.4        pk 	"sizeof",
    374  1.4        pk 	"union",
    375  1.4        pk 	"vector",
    376  1.4        pk 	NULL
    377  1.4        pk };
    378  1.4        pk 
    379  1.7     lukem static char *reserved_types[] = {
    380  1.4        pk 	"opaque",
    381  1.4        pk 	"string",
    382  1.4        pk 	NULL
    383  1.4        pk };
    384  1.4        pk /* check that the given name is not one that would eventually result in
    385  1.4        pk    xdr routines that would conflict with internal XDR routines. */
    386  1.6  christos static void
    387  1.7     lukem check_type_name(name, new_type)
    388  1.7     lukem 	int     new_type;
    389  1.7     lukem 	char   *name;
    390  1.7     lukem {
    391  1.7     lukem 	int     i;
    392  1.7     lukem 	char    tmp[100];
    393  1.7     lukem 
    394  1.7     lukem 	for (i = 0; reserved_words[i] != NULL; i++) {
    395  1.7     lukem 		if (strcmp(name, reserved_words[i]) == 0) {
    396  1.7     lukem 			sprintf(tmp,
    397  1.7     lukem 			    "illegal (reserved) name :\'%s\' in type definition", name);
    398  1.7     lukem 			error(tmp);
    399  1.7     lukem 		}
    400  1.7     lukem 	}
    401  1.7     lukem 	if (new_type) {
    402  1.7     lukem 		for (i = 0; reserved_types[i] != NULL; i++) {
    403  1.7     lukem 			if (strcmp(name, reserved_types[i]) == 0) {
    404  1.7     lukem 				sprintf(tmp,
    405  1.7     lukem 				    "illegal (reserved) name :\'%s\' in type definition", name);
    406  1.7     lukem 				error(tmp);
    407  1.7     lukem 			}
    408  1.7     lukem 		}
    409  1.7     lukem 	}
    410  1.1     glass }
    411  1.1     glass 
    412  1.6  christos static void
    413  1.1     glass def_typedef(defp)
    414  1.1     glass 	definition *defp;
    415  1.1     glass {
    416  1.1     glass 	declaration dec;
    417  1.1     glass 
    418  1.1     glass 	defp->def_kind = DEF_TYPEDEF;
    419  1.1     glass 	get_declaration(&dec, DEF_TYPEDEF);
    420  1.1     glass 	defp->def_name = dec.name;
    421  1.7     lukem 	check_type_name(dec.name, 1);
    422  1.1     glass 	defp->def.ty.old_prefix = dec.prefix;
    423  1.1     glass 	defp->def.ty.old_type = dec.type;
    424  1.1     glass 	defp->def.ty.rel = dec.rel;
    425  1.1     glass 	defp->def.ty.array_max = dec.array_max;
    426  1.1     glass }
    427  1.1     glass 
    428  1.6  christos static void
    429  1.1     glass get_declaration(dec, dkind)
    430  1.1     glass 	declaration *dec;
    431  1.1     glass 	defkind dkind;
    432  1.1     glass {
    433  1.7     lukem 	token   tok;
    434  1.1     glass 
    435  1.1     glass 	get_type(&dec->prefix, &dec->type, dkind);
    436  1.1     glass 	dec->rel = REL_ALIAS;
    437  1.1     glass 	if (streq(dec->type, "void")) {
    438  1.1     glass 		return;
    439  1.1     glass 	}
    440  1.7     lukem 	check_type_name(dec->type, 0);
    441  1.4        pk 
    442  1.1     glass 	scan2(TOK_STAR, TOK_IDENT, &tok);
    443  1.1     glass 	if (tok.kind == TOK_STAR) {
    444  1.1     glass 		dec->rel = REL_POINTER;
    445  1.1     glass 		scan(TOK_IDENT, &tok);
    446  1.1     glass 	}
    447  1.1     glass 	dec->name = tok.str;
    448  1.1     glass 	if (peekscan(TOK_LBRACKET, &tok)) {
    449  1.1     glass 		if (dec->rel == REL_POINTER) {
    450  1.1     glass 			error("no array-of-pointer declarations -- use typedef");
    451  1.1     glass 		}
    452  1.1     glass 		dec->rel = REL_VECTOR;
    453  1.1     glass 		scan_num(&tok);
    454  1.1     glass 		dec->array_max = tok.str;
    455  1.1     glass 		scan(TOK_RBRACKET, &tok);
    456  1.7     lukem 	} else
    457  1.7     lukem 		if (peekscan(TOK_LANGLE, &tok)) {
    458  1.7     lukem 			if (dec->rel == REL_POINTER) {
    459  1.7     lukem 				error("no array-of-pointer declarations -- use typedef");
    460  1.7     lukem 			}
    461  1.7     lukem 			dec->rel = REL_ARRAY;
    462  1.7     lukem 			if (peekscan(TOK_RANGLE, &tok)) {
    463  1.7     lukem 				dec->array_max = "~0";	/* unspecified size, use
    464  1.7     lukem 							 * max */
    465  1.7     lukem 			} else {
    466  1.7     lukem 				scan_num(&tok);
    467  1.7     lukem 				dec->array_max = tok.str;
    468  1.7     lukem 				scan(TOK_RANGLE, &tok);
    469  1.7     lukem 			}
    470  1.1     glass 		}
    471  1.1     glass 	if (streq(dec->type, "opaque")) {
    472  1.1     glass 		if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
    473  1.1     glass 			error("array declaration expected");
    474  1.1     glass 		}
    475  1.7     lukem 	} else
    476  1.7     lukem 		if (streq(dec->type, "string")) {
    477  1.7     lukem 			if (dec->rel != REL_ARRAY) {
    478  1.7     lukem 				error("variable-length array declaration expected");
    479  1.7     lukem 			}
    480  1.1     glass 		}
    481  1.1     glass }
    482  1.1     glass 
    483  1.6  christos static void
    484  1.4        pk get_prog_declaration(dec, dkind, num)
    485  1.4        pk 	declaration *dec;
    486  1.4        pk 	defkind dkind;
    487  1.7     lukem 	int     num;		/* arg number */
    488  1.4        pk {
    489  1.7     lukem 	token   tok;
    490  1.7     lukem 	char    name[10];	/* argument name */
    491  1.4        pk 
    492  1.7     lukem 	if (dkind == DEF_PROGRAM) {
    493  1.7     lukem 		peek(&tok);
    494  1.7     lukem 		if (tok.kind == TOK_RPAREN) {	/* no arguments */
    495  1.7     lukem 			dec->rel = REL_ALIAS;
    496  1.7     lukem 			dec->type = "void";
    497  1.7     lukem 			dec->prefix = NULL;
    498  1.7     lukem 			dec->name = NULL;
    499  1.7     lukem 			return;
    500  1.7     lukem 		}
    501  1.4        pk 	}
    502  1.4        pk 	get_type(&dec->prefix, &dec->type, dkind);
    503  1.4        pk 	dec->rel = REL_ALIAS;
    504  1.7     lukem 	if (peekscan(TOK_IDENT, &tok))	/* optional name of argument */
    505  1.4        pk 		strcpy(name, tok.str);
    506  1.7     lukem 	else
    507  1.7     lukem 		sprintf(name, "%s%d", ARGNAME, num);	/* default name of
    508  1.7     lukem 							 * argument */
    509  1.7     lukem 
    510  1.7     lukem 	dec->name = (char *) strdup(name);
    511  1.4        pk 
    512  1.4        pk 	if (streq(dec->type, "void")) {
    513  1.4        pk 		return;
    514  1.4        pk 	}
    515  1.4        pk 	if (streq(dec->type, "opaque")) {
    516  1.4        pk 		error("opaque -- illegal argument type");
    517  1.4        pk 	}
    518  1.7     lukem 	if (peekscan(TOK_STAR, &tok)) {
    519  1.7     lukem 		if (streq(dec->type, "string")) {
    520  1.7     lukem 			error("pointer to string not allowed in program arguments\n");
    521  1.7     lukem 		}
    522  1.4        pk 		dec->rel = REL_POINTER;
    523  1.7     lukem 		if (peekscan(TOK_IDENT, &tok))	/* optional name of argument */
    524  1.7     lukem 			dec->name = (char *) strdup(tok.str);
    525  1.7     lukem 	}
    526  1.7     lukem 	if (peekscan(TOK_LANGLE, &tok)) {
    527  1.7     lukem 		if (!streq(dec->type, "string")) {
    528  1.7     lukem 			error("arrays cannot be declared as arguments to procedures -- use typedef");
    529  1.7     lukem 		}
    530  1.4        pk 		dec->rel = REL_ARRAY;
    531  1.4        pk 		if (peekscan(TOK_RANGLE, &tok)) {
    532  1.7     lukem 			dec->array_max = "~0";	/* unspecified size, use max */
    533  1.4        pk 		} else {
    534  1.4        pk 			scan_num(&tok);
    535  1.4        pk 			dec->array_max = tok.str;
    536  1.4        pk 			scan(TOK_RANGLE, &tok);
    537  1.4        pk 		}
    538  1.4        pk 	}
    539  1.4        pk 	if (streq(dec->type, "string")) {
    540  1.7     lukem 		if (dec->rel != REL_ARRAY) {	/* .x specifies just string as
    541  1.7     lukem 						 * type of argument - make it
    542  1.7     lukem 						 * string<> */
    543  1.4        pk 			dec->rel = REL_ARRAY;
    544  1.7     lukem 			dec->array_max = "~0";	/* unspecified size, use max */
    545  1.4        pk 		}
    546  1.4        pk 	}
    547  1.4        pk }
    548  1.4        pk 
    549  1.4        pk 
    550  1.1     glass 
    551  1.6  christos static void
    552  1.1     glass get_type(prefixp, typep, dkind)
    553  1.7     lukem 	char  **prefixp;
    554  1.7     lukem 	char  **typep;
    555  1.1     glass 	defkind dkind;
    556  1.1     glass {
    557  1.7     lukem 	token   tok;
    558  1.1     glass 
    559  1.1     glass 	*prefixp = NULL;
    560  1.1     glass 	get_token(&tok);
    561  1.1     glass 	switch (tok.kind) {
    562  1.1     glass 	case TOK_IDENT:
    563  1.1     glass 		*typep = tok.str;
    564  1.1     glass 		break;
    565  1.1     glass 	case TOK_STRUCT:
    566  1.1     glass 	case TOK_ENUM:
    567  1.1     glass 	case TOK_UNION:
    568  1.1     glass 		*prefixp = tok.str;
    569  1.1     glass 		scan(TOK_IDENT, &tok);
    570  1.1     glass 		*typep = tok.str;
    571  1.1     glass 		break;
    572  1.1     glass 	case TOK_UNSIGNED:
    573  1.1     glass 		unsigned_dec(typep);
    574  1.1     glass 		break;
    575  1.1     glass 	case TOK_SHORT:
    576  1.9     lukem 		*typep = "short";
    577  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    578  1.1     glass 		break;
    579  1.1     glass 	case TOK_LONG:
    580  1.9     lukem 		*typep = "long";
    581  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    582  1.1     glass 		break;
    583  1.1     glass 	case TOK_VOID:
    584  1.1     glass 		if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
    585  1.4        pk 			error("voids allowed only inside union and program definitions with one argument");
    586  1.1     glass 		}
    587  1.1     glass 		*typep = tok.str;
    588  1.1     glass 		break;
    589  1.1     glass 	case TOK_STRING:
    590  1.1     glass 	case TOK_OPAQUE:
    591  1.1     glass 	case TOK_CHAR:
    592  1.9     lukem 	case TOK_INT:
    593  1.1     glass 	case TOK_FLOAT:
    594  1.1     glass 	case TOK_DOUBLE:
    595  1.1     glass 	case TOK_BOOL:
    596  1.1     glass 		*typep = tok.str;
    597  1.1     glass 		break;
    598  1.1     glass 	default:
    599  1.1     glass 		error("expected type specifier");
    600  1.1     glass 	}
    601  1.1     glass }
    602  1.1     glass 
    603  1.6  christos static void
    604  1.1     glass unsigned_dec(typep)
    605  1.7     lukem 	char  **typep;
    606  1.1     glass {
    607  1.7     lukem 	token   tok;
    608  1.1     glass 
    609  1.1     glass 	peek(&tok);
    610  1.1     glass 	switch (tok.kind) {
    611  1.1     glass 	case TOK_CHAR:
    612  1.1     glass 		get_token(&tok);
    613  1.1     glass 		*typep = "u_char";
    614  1.1     glass 		break;
    615  1.1     glass 	case TOK_SHORT:
    616  1.1     glass 		get_token(&tok);
    617  1.9     lukem 		*typep = "u_short";
    618  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    619  1.1     glass 		break;
    620  1.1     glass 	case TOK_LONG:
    621  1.1     glass 		get_token(&tok);
    622  1.9     lukem 		*typep = "u_long";
    623  1.1     glass 		(void) peekscan(TOK_INT, &tok);
    624  1.1     glass 		break;
    625  1.1     glass 	case TOK_INT:
    626  1.1     glass 		get_token(&tok);
    627  1.9     lukem 		*typep = "u_int";
    628  1.1     glass 		break;
    629  1.1     glass 	default:
    630  1.9     lukem 		*typep = "u_int";
    631  1.1     glass 		break;
    632  1.1     glass 	}
    633  1.1     glass }
    634