xref: /titanic_44/usr/src/cmd/rpcgen/rpc_parse.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29  * University Copyright- Copyright (c) 1982, 1986, 1988
30  * The Regents of the University of California
31  * All Rights Reserved
32  *
33  * University Acknowledgment- Portions of this document are derived from
34  * software developed by the University of California, Berkeley, and its
35  * contributors.
36  */
37 
38 #pragma ident	"%Z%%M%	%I%	%E% SMI"
39 
40 /*
41  * rpc_parse.c, Parser for the RPC protocol compiler
42  */
43 #include <stdio.h>
44 #include <string.h>
45 #include "rpc/types.h"
46 #include "rpc_scan.h"
47 #include "rpc_parse.h"
48 #include "rpc_util.h"
49 
50 #define	ARGNAME "arg"
51 
52 extern char *make_argname();
53 extern char *strdup();
54 
55 /*
56  * return the next definition you see
57  */
58 definition *
59 get_definition()
60 {
61 	definition *defp;
62 	token tok;
63 
64 	defp = ALLOC(definition);
65 	get_token(&tok);
66 	switch (tok.kind) {
67 	case TOK_STRUCT:
68 		def_struct(defp);
69 		break;
70 	case TOK_UNION:
71 		def_union(defp);
72 		break;
73 	case TOK_TYPEDEF:
74 		def_typedef(defp);
75 		break;
76 	case TOK_ENUM:
77 		def_enum(defp);
78 		break;
79 	case TOK_PROGRAM:
80 		def_program(defp);
81 		break;
82 	case TOK_CONST:
83 		def_const(defp);
84 		break;
85 	case TOK_EOF:
86 		return (NULL);
87 	default:
88 		error("definition keyword expected");
89 	}
90 	scan(TOK_SEMICOLON, &tok);
91 	isdefined(defp);
92 	return (defp);
93 }
94 
95 static
96 isdefined(defp)
97 	definition *defp;
98 {
99 	STOREVAL(&defined, defp);
100 }
101 
102 /*
103  * We treat s == NULL the same as *s == '\0'
104  */
105 streqn(const char *s1, const char *s2)
106 {
107 	if (s1 == NULL)
108 		s1 = "";
109 	if (s2 == NULL)
110 		s2 = "";
111 	if (s1 == s2)
112 		return (1);
113 
114 	return (strcmp(s1, s2) == 0);
115 }
116 
117 static int
118 cmptype(definition *defp, char *type)
119 {
120 	/* We only want typedef definitions */
121 	if (streq(defp->def_name, type) && defp->def_kind == DEF_TYPEDEF)
122 		return (1);
123 
124 	return (0);
125 }
126 
127 static int
128 check_self_reference(const char *name, const declaration *decp, int first)
129 {
130 	/*
131 	 * Now check for the following special case if first is true:
132 	 *
133 	 * struct foo {
134 	 *	...
135 	 *	foo *next;
136 	 * };
137 	 *
138 	 *
139 	 * In the above cases foo has not yet been entered in the type list,
140 	 * defined. So there is no typedef entry. The prefix in that case
141 	 * could be empty.
142 	 */
143 	if (decp->rel == REL_POINTER &&
144 	    (streqn(decp->prefix, "struct") ||
145 	    (first && streqn(decp->prefix, ""))) &&
146 	    streqn(name, decp->type))
147 		return (1);
148 	return (0);
149 }
150 
151 static int
152 is_self_reference(definition *defp, declaration *decp)
153 {
154 	declaration current;
155 	definition *dp;
156 
157 	if (check_self_reference(defp->def_name, decp, 1))
158 		return (1);
159 
160 	/*
161 	 * Check for valid declaration:
162 	 * Only prefixes allowed are none and struct.
163 	 * Only relations allowed are pointer or alias.
164 	 */
165 	if (!streqn(decp->prefix, "struct") && !streqn(decp->prefix, ""))
166 		return (0);
167 	if (decp->rel != REL_POINTER && decp->rel != REL_ALIAS)
168 		return (0);
169 
170 	current.rel = decp->rel;
171 	current.prefix = decp->prefix;
172 	current.type = decp->type;
173 	current.name = decp->name;
174 	decp = &current;
175 	while (!check_self_reference(defp->def_name, decp, 0)) {
176 		dp = FINDVAL(defined, decp->type, cmptype);
177 
178 		/*
179 		 * Check if we found a definition.
180 		 */
181 		if (dp == NULL)
182 			return (0);
183 
184 		/*
185 		 * Check for valid prefix. We eventually need to see one
186 		 * and only one struct.
187 		 */
188 		if (streqn(decp->prefix, "")) {
189 			/*
190 			 * If the current declaration prefix in empty
191 			 * then the definition found must have an empty
192 			 * prefix or a struct prefix
193 			 */
194 			if (!streqn(dp->def.ty.old_prefix, "") &&
195 			    !streqn(dp->def.ty.old_prefix, "struct"))
196 				return (0);
197 		} else if (streqn(decp->prefix, "struct") &&
198 			!streqn(dp->def.ty.old_prefix, ""))
199 			/*
200 			 * if the current prefix is struct tne new prefix
201 			 * must be empty
202 			 */
203 			return (0);
204 		else if (!streqn(decp->prefix, "struct"))
205 			/* Should never get here */
206 			return (0);
207 
208 		/*
209 		 * Check for valid relation. We need to see one and
210 		 * only one REL_POINTER. The only valid relation types
211 		 * are REL_POINTER and REL_ALIAS.
212 		 */
213 		if (decp->rel == REL_POINTER && dp->def.ty.rel != REL_ALIAS)
214 			return (0);
215 		else if (decp->rel == REL_ALIAS &&
216 			(dp->def.ty.rel != REL_ALIAS &&
217 			dp->def.ty.rel != REL_POINTER))
218 			return (0);
219 		else if (decp->rel != REL_ALIAS && decp->rel != REL_POINTER)
220 			/* Should never get here */
221 			return (0);
222 
223 		/* Set up the current declaration */
224 		if (streqn(decp->prefix, ""))
225 			decp->prefix = dp->def.ty.old_prefix;
226 		decp->type = dp->def.ty.old_type;
227 		if (decp->rel == REL_ALIAS)
228 			decp->rel = dp->def.ty.rel;
229 	}
230 
231 	/* We have a self reference type */
232 	return (1);
233 }
234 
235 static
236 def_struct(defp)
237 	definition *defp;
238 {
239 	token tok;
240 	declaration dec;
241 	decl_list *decls;
242 	decl_list **tailp, *endp;
243 
244 	defp->def_kind = DEF_STRUCT;
245 
246 	scan(TOK_IDENT, &tok);
247 	defp->def_name = tok.str;
248 	scan(TOK_LBRACE, &tok);
249 	tailp = &defp->def.st.decls;
250 	defp->def.st.tail = NULL;
251 	do {
252 		get_declaration(&dec, DEF_STRUCT);
253 		decls = ALLOC(decl_list);
254 		decls->decl = dec;
255 		/*
256 		 * Keep a referenct to the last declaration to check for
257 		 * tail recurrsion.
258 		 */
259 		endp = *tailp = decls;
260 		tailp = &decls->next;
261 		scan(TOK_SEMICOLON, &tok);
262 		peek(&tok);
263 	} while (tok.kind != TOK_RBRACE);
264 	*tailp = NULL;
265 	/*
266 	 * Check for tail recurse. If the last declaration refers to this
267 	 * structure then mark this stucture to convert the tail recursion
268 	 * to itteration.
269 	 */
270 	defp->def.st.self_pointer = is_self_reference(defp, &endp->decl);
271 	get_token(&tok);
272 	defp->def.st.tail = endp;
273 }
274 
275 static
276 def_program(defp)
277 	definition *defp;
278 {
279 	token tok;
280 	declaration dec;
281 	decl_list *decls;
282 	decl_list **tailp;
283 	version_list *vlist;
284 	version_list **vtailp;
285 	proc_list *plist;
286 	proc_list **ptailp;
287 	int num_args;
288 	bool_t isvoid = FALSE;	/* whether first argument is void */
289 	defp->def_kind = DEF_PROGRAM;
290 	scan(TOK_IDENT, &tok);
291 	defp->def_name = tok.str;
292 	scan(TOK_LBRACE, &tok);
293 	vtailp = &defp->def.pr.versions;
294 	tailp = &defp->def.st.decls;
295 	scan(TOK_VERSION, &tok);
296 	do {
297 		scan(TOK_IDENT, &tok);
298 		vlist = ALLOC(version_list);
299 		vlist->vers_name = tok.str;
300 		scan(TOK_LBRACE, &tok);
301 		ptailp = &vlist->procs;
302 		do {
303 			/* get result type */
304 			plist = ALLOC(proc_list);
305 			get_type(&plist->res_prefix, &plist->res_type,
306 			    DEF_RESULT);
307 			if (streq(plist->res_type, "opaque")) {
308 				error("illegal result type");
309 			}
310 			scan(TOK_IDENT, &tok);
311 			plist->proc_name = tok.str;
312 			scan(TOK_LPAREN, &tok);
313 			/* get args - first one */
314 			num_args = 1;
315 			isvoid = FALSE;
316 			/*
317 			 * type of DEF_PROGRAM in the first
318 			 * get_prog_declaration and DEF_STURCT in the next
319 			 * allows void as argument if it is the only argument
320 			 */
321 			get_prog_declaration(&dec, DEF_PROGRAM, num_args);
322 			if (streq(dec.type, "void"))
323 				isvoid = TRUE;
324 			decls = ALLOC(decl_list);
325 			plist->args.decls = decls;
326 			decls->decl = dec;
327 			tailp = &decls->next;
328 			/* get args */
329 			while (peekscan(TOK_COMMA, &tok)) {
330 				num_args++;
331 				get_prog_declaration(&dec, DEF_STRUCT,
332 						    num_args);
333 				decls = ALLOC(decl_list);
334 				decls->decl = dec;
335 				*tailp = decls;
336 				if (streq(dec.type, "void"))
337 					isvoid = TRUE;
338 				tailp = &decls->next;
339 			}
340 			/* multiple arguments are only allowed in newstyle */
341 			if (!newstyle && num_args > 1) {
342 				error("only one argument is allowed");
343 			}
344 			if (isvoid && num_args > 1) {
345 				error("illegal use of void "
346 				    "in program definition");
347 			}
348 			*tailp = NULL;
349 			scan(TOK_RPAREN, &tok);
350 			scan(TOK_EQUAL, &tok);
351 			scan_num(&tok);
352 			scan(TOK_SEMICOLON, &tok);
353 			plist->proc_num = tok.str;
354 			plist->arg_num = num_args;
355 			*ptailp = plist;
356 			ptailp = &plist->next;
357 			peek(&tok);
358 		} while (tok.kind != TOK_RBRACE);
359 		*ptailp = NULL;
360 		*vtailp = vlist;
361 		vtailp = &vlist->next;
362 		scan(TOK_RBRACE, &tok);
363 		scan(TOK_EQUAL, &tok);
364 		scan_num(&tok);
365 		vlist->vers_num = tok.str;
366 		/* make the argument structure name for each arg */
367 		for (plist = vlist->procs; plist != NULL;
368 		    plist = plist->next) {
369 			plist->args.argname = make_argname(plist->proc_name,
370 							vlist->vers_num);
371 			/* free the memory ?? */
372 		}
373 		scan(TOK_SEMICOLON, &tok);
374 		scan2(TOK_VERSION, TOK_RBRACE, &tok);
375 	} while (tok.kind == TOK_VERSION);
376 	scan(TOK_EQUAL, &tok);
377 	scan_num(&tok);
378 	defp->def.pr.prog_num = tok.str;
379 	*vtailp = NULL;
380 }
381 
382 
383 static
384 def_enum(defp)
385 	definition *defp;
386 {
387 	token tok;
388 	enumval_list *elist;
389 	enumval_list **tailp;
390 
391 	defp->def_kind = DEF_ENUM;
392 	scan(TOK_IDENT, &tok);
393 	defp->def_name = tok.str;
394 	scan(TOK_LBRACE, &tok);
395 	tailp = &defp->def.en.vals;
396 	do {
397 		scan(TOK_IDENT, &tok);
398 		elist = ALLOC(enumval_list);
399 		elist->name = tok.str;
400 		elist->assignment = NULL;
401 		scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
402 		if (tok.kind == TOK_EQUAL) {
403 			scan_num(&tok);
404 			elist->assignment = tok.str;
405 			scan2(TOK_COMMA, TOK_RBRACE, &tok);
406 		}
407 		*tailp = elist;
408 		tailp = &elist->next;
409 	} while (tok.kind != TOK_RBRACE);
410 	*tailp = NULL;
411 }
412 
413 static
414 def_const(defp)
415 	definition *defp;
416 {
417 	token tok;
418 
419 	defp->def_kind = DEF_CONST;
420 	scan(TOK_IDENT, &tok);
421 	defp->def_name = tok.str;
422 	scan(TOK_EQUAL, &tok);
423 	scan2(TOK_IDENT, TOK_STRCONST, &tok);
424 	defp->def.co = tok.str;
425 }
426 
427 static
428 def_union(defp)
429 	definition *defp;
430 {
431 	token tok;
432 	declaration dec;
433 	case_list *cases, *tcase;
434 	case_list **tailp;
435 	int flag;
436 
437 	defp->def_kind = DEF_UNION;
438 	scan(TOK_IDENT, &tok);
439 	defp->def_name = tok.str;
440 	scan(TOK_SWITCH, &tok);
441 	scan(TOK_LPAREN, &tok);
442 	get_declaration(&dec, DEF_UNION);
443 	defp->def.un.enum_decl = dec;
444 	tailp = &defp->def.un.cases;
445 	scan(TOK_RPAREN, &tok);
446 	scan(TOK_LBRACE, &tok);
447 	scan(TOK_CASE, &tok);
448 	while (tok.kind == TOK_CASE) {
449 		scan2(TOK_IDENT, TOK_CHARCONST, &tok);
450 		cases = ALLOC(case_list);
451 		cases->case_name = tok.str;
452 		scan(TOK_COLON, &tok);
453 		/* now peek at next token */
454 		flag = 0;
455 		if (peekscan(TOK_CASE, &tok)) {
456 			do {
457 				scan2(TOK_IDENT, TOK_CHARCONST, &tok);
458 				cases->contflag = 1;
459 				/* continued case statement */
460 				*tailp = cases;
461 				tailp = &cases->next;
462 				cases = ALLOC(case_list);
463 				cases->case_name = tok.str;
464 				scan(TOK_COLON, &tok);
465 			} while (peekscan(TOK_CASE, &tok));
466 		}
467 		else
468 			if (flag)
469 			{
470 
471 				*tailp = cases;
472 				tailp = &cases->next;
473 				cases = ALLOC(case_list);
474 			};
475 
476 		get_declaration(&dec, DEF_UNION);
477 		cases->case_decl = dec;
478 		cases->contflag = 0; /* no continued case statement */
479 		*tailp = cases;
480 		tailp = &cases->next;
481 		scan(TOK_SEMICOLON, &tok);
482 
483 		scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
484 	}
485 	*tailp = NULL;
486 	if (tok.kind == TOK_DEFAULT) {
487 		scan(TOK_COLON, &tok);
488 		get_declaration(&dec, DEF_UNION);
489 		defp->def.un.default_decl = ALLOC(declaration);
490 		*defp->def.un.default_decl = dec;
491 		scan(TOK_SEMICOLON, &tok);
492 		scan(TOK_RBRACE, &tok);
493 	} else {
494 		defp->def.un.default_decl = NULL;
495 	}
496 }
497 
498 static char *reserved_words[] =
499 {
500 	"array",
501 	"bytes",
502 	"destroy",
503 	"free",
504 	"getpos",
505 	"inline",
506 	"pointer",
507 	"reference",
508 	"setpos",
509 	"sizeof",
510 	"union",
511 	"vector",
512 	NULL
513 	};
514 
515 static char *reserved_types[] =
516 {
517 	"opaque",
518 	"string",
519 	NULL
520 	};
521 
522 /*
523  * check that the given name is not one that would eventually result in
524  * xdr routines that would conflict with internal XDR routines.
525  */
526 static check_type_name(name, new_type)
527 int new_type;
528 char *name;
529 {
530 	int i;
531 	char tmp[100];
532 
533 	for (i = 0; reserved_words[i] != NULL; i++) {
534 		if (strcmp(name, reserved_words[i]) == 0) {
535 			snprintf(tmp, sizeof (tmp),
536 				"illegal (reserved) name :\'%s\' "
537 				"in type definition",
538 				name);
539 			error(tmp);
540 		}
541 	}
542 	if (new_type) {
543 		for (i = 0; reserved_types[i] != NULL; i++) {
544 			if (strcmp(name, reserved_types[i]) == 0) {
545 				snprintf(tmp, sizeof (tmp),
546 					"illegal (reserved) name :\'%s\' "
547 					"in type definition",
548 					name);
549 				error(tmp);
550 			}
551 		}
552 	}
553 }
554 
555 
556 
557 static
558 def_typedef(defp)
559 	definition *defp;
560 {
561 	declaration dec;
562 
563 	defp->def_kind = DEF_TYPEDEF;
564 	get_declaration(&dec, DEF_TYPEDEF);
565 	defp->def_name = dec.name;
566 	check_type_name(dec.name, 1);
567 	defp->def.ty.old_prefix = dec.prefix;
568 	defp->def.ty.old_type = dec.type;
569 	defp->def.ty.rel = dec.rel;
570 	defp->def.ty.array_max = dec.array_max;
571 }
572 
573 static
574 get_declaration(dec, dkind)
575 	declaration *dec;
576 	defkind dkind;
577 {
578 	token tok;
579 
580 	get_type(&dec->prefix, &dec->type, dkind);
581 	dec->rel = REL_ALIAS;
582 	if (streq(dec->type, "void")) {
583 		return;
584 	}
585 
586 	check_type_name(dec->type, 0);
587 	scan2(TOK_STAR, TOK_IDENT, &tok);
588 	if (tok.kind == TOK_STAR) {
589 		dec->rel = REL_POINTER;
590 		scan(TOK_IDENT, &tok);
591 	}
592 	dec->name = tok.str;
593 	if (peekscan(TOK_LBRACKET, &tok)) {
594 		if (dec->rel == REL_POINTER) {
595 			error("no array-of-pointer declarations "
596 			    "-- use typedef");
597 		}
598 		dec->rel = REL_VECTOR;
599 		scan_num(&tok);
600 		dec->array_max = tok.str;
601 		scan(TOK_RBRACKET, &tok);
602 	} else if (peekscan(TOK_LANGLE, &tok)) {
603 		if (dec->rel == REL_POINTER) {
604 			error("no array-of-pointer declarations "
605 			    "-- use typedef");
606 		}
607 		dec->rel = REL_ARRAY;
608 		if (peekscan(TOK_RANGLE, &tok)) {
609 			dec->array_max = "~0";	/* unspecified size, use max */
610 		} else {
611 			scan_num(&tok);
612 			dec->array_max = tok.str;
613 			scan(TOK_RANGLE, &tok);
614 		}
615 	}
616 	if (streq(dec->type, "opaque")) {
617 		if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
618 			error("array declaration expected");
619 		}
620 	} else if (streq(dec->type, "string")) {
621 		if (dec->rel != REL_ARRAY) {
622 			error("variable-length array declaration expected");
623 		}
624 	}
625 }
626 
627 
628 static
629 get_prog_declaration(dec, dkind, num)
630 	declaration *dec;
631 	defkind dkind;
632 	int num;  /* arg number */
633 {
634 	token tok;
635 	char name[sizeof (ARGNAME) + 10];
636 
637 	if (dkind == DEF_PROGRAM) {
638 		peek(&tok);
639 		if (tok.kind == TOK_RPAREN) { /* no arguments */
640 			dec->rel = REL_ALIAS;
641 			dec->type = "void";
642 			dec->prefix = NULL;
643 			dec->name = NULL;
644 			return;
645 		}
646 	}
647 	get_type(&dec->prefix, &dec->type, dkind);
648 	dec->rel = REL_ALIAS;
649 	if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
650 		dec->name = strdup(tok.str);
651 	else {
652 		/* default name of argument */
653 		snprintf(name, sizeof (name), "%s%d", ARGNAME, num);
654 		dec->name = strdup(name);
655 	}
656 	if (dec->name == NULL)
657 		error("internal error -- out of memory");
658 
659 	if (streq(dec->type, "void")) {
660 		return;
661 	}
662 
663 	if (streq(dec->type, "opaque")) {
664 		error("opaque -- illegal argument type");
665 	}
666 	if (peekscan(TOK_STAR, &tok)) {
667 		if (streq(dec->type, "string")) {
668 			error("pointer to string not allowed "
669 			    "in program arguments\n");
670 		}
671 		dec->rel = REL_POINTER;
672 		if (peekscan(TOK_IDENT, &tok))
673 			/* optional name of argument */
674 			dec->name = strdup(tok.str);
675 	}
676 	if (peekscan(TOK_LANGLE, &tok)) {
677 		if (!streq(dec->type, "string")) {
678 			error("arrays cannot be declared as arguments "
679 			    "to procedures -- use typedef");
680 		}
681 		dec->rel = REL_ARRAY;
682 		if (peekscan(TOK_RANGLE, &tok)) {
683 			dec->array_max = "~0";
684 			/* unspecified size, use max */
685 		} else {
686 			scan_num(&tok);
687 			dec->array_max = tok.str;
688 			scan(TOK_RANGLE, &tok);
689 		}
690 	}
691 	if (streq(dec->type, "string")) {
692 		if (dec->rel != REL_ARRAY) {
693 			/*
694 			 * .x specifies just string as
695 			 * type of argument
696 			 * - make it string<>
697 			 */
698 			dec->rel = REL_ARRAY;
699 			dec->array_max = "~0"; /* unspecified size, use max */
700 		}
701 	}
702 }
703 
704 
705 
706 static
707 get_type(prefixp, typep, dkind)
708 	char **prefixp;
709 	char **typep;
710 	defkind dkind;
711 {
712 	token tok;
713 
714 	*prefixp = NULL;
715 	get_token(&tok);
716 	switch (tok.kind) {
717 	case TOK_IDENT:
718 		*typep = tok.str;
719 		break;
720 	case TOK_STRUCT:
721 	case TOK_ENUM:
722 	case TOK_UNION:
723 		*prefixp = tok.str;
724 		scan(TOK_IDENT, &tok);
725 		*typep = tok.str;
726 		break;
727 	case TOK_UNSIGNED:
728 		unsigned_dec(typep);
729 		break;
730 	case TOK_SHORT:
731 		*typep = "short";
732 		(void) peekscan(TOK_INT, &tok);
733 		break;
734 	case TOK_LONG:
735 		*typep = "long";
736 		(void) peekscan(TOK_INT, &tok);
737 		break;
738 	case TOK_HYPER:
739 		*typep = "longlong_t";
740 		(void) peekscan(TOK_INT, &tok);
741 		break;
742 
743 	case TOK_VOID:
744 		if (dkind != DEF_UNION && dkind != DEF_PROGRAM &&
745 		    dkind != DEF_RESULT) {
746 			error("voids allowed only inside union and "
747 			    "program definitions with one argument");
748 		}
749 		*typep = tok.str;
750 		break;
751 	case TOK_ONEWAY:
752 		if (dkind != DEF_RESULT) {
753 			error("oneways allowed only inside result definitions");
754 		}
755 		*typep = tok.str;
756 		break;
757 	case TOK_STRING:
758 	case TOK_OPAQUE:
759 	case TOK_CHAR:
760 	case TOK_INT:
761 	case TOK_FLOAT:
762 	case TOK_DOUBLE:
763 	case TOK_BOOL:
764 	case TOK_QUAD:
765 		*typep = tok.str;
766 		break;
767 	default:
768 		error("expected type specifier");
769 	}
770 }
771 
772 static
773 unsigned_dec(typep)
774 	char **typep;
775 {
776 	token tok;
777 
778 	peek(&tok);
779 	switch (tok.kind) {
780 	case TOK_CHAR:
781 		get_token(&tok);
782 		*typep = "u_char";
783 		break;
784 	case TOK_SHORT:
785 		get_token(&tok);
786 		*typep = "u_short";
787 		(void) peekscan(TOK_INT, &tok);
788 		break;
789 	case TOK_LONG:
790 		get_token(&tok);
791 		*typep = "u_long";
792 		(void) peekscan(TOK_INT, &tok);
793 		break;
794 	case TOK_HYPER:
795 		get_token(&tok);
796 		*typep = "u_longlong_t";
797 		(void) peekscan(TOK_INT, &tok);
798 		break;
799 	case TOK_INT:
800 		get_token(&tok);
801 		*typep = "u_int";
802 		break;
803 	default:
804 		*typep = "u_int";
805 		break;
806 	}
807 }
808