xref: /illumos-gate/usr/src/tools/ndrgen/ndr_anal.c (revision 99dda20867d903eec23291ba1ecb18a82d70096b)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <strings.h>
30 #include <string.h>
31 #include "ndrgen.h"
32 #include "y.tab.h"
33 
34 
35 #define	ALLOW_NOTHING	0
36 #define	ALLOW_VARSIZE	1
37 #define	ALLOW_INOUT	2
38 #define	ALLOW_CASE	4
39 #define	ALLOW_NO_UNIONS	8		/* for topmost structures */
40 #define	ALLOW_NO_SWITCH 16
41 
42 struct tup {
43 	struct tup		*up;
44 	ndr_typeinfo_t		*ti;
45 };
46 
47 static void type_ident_decl(ndr_typeinfo_t *, char *, size_t, char *);
48 static void type_ident_decl1(struct tup *, char *, size_t, char *);
49 static void analyze_typeinfo_list(void);
50 static void analyze_typeinfo_typedef(ndr_typeinfo_t *);
51 static void analyze_typeinfo_struct(ndr_typeinfo_t *);
52 static void analyze_typeinfo_union(ndr_typeinfo_t *);
53 static void analyze_typeinfo_aggregate_finish(ndr_typeinfo_t *);
54 static void analyze_member(ndr_node_t *, ndr_member_t *, unsigned long *, int);
55 static void seed_basic_types(void);
56 static void seed_construct_types(void);
57 static void append_typeinfo(ndr_typeinfo_t *);
58 static ndr_typeinfo_t *bind_typeinfo(ndr_typeinfo_t *);
59 static ndr_typeinfo_t *find_typeinfo_by_name(ndr_node_t *);
60 static void determine_advice(ndr_advice_t *, ndr_node_t *);
61 static ndr_node_t *find_advice(ndr_node_t *advice_list, int label);
62 
63 
64 void
65 analyze(void)
66 {
67 	seed_basic_types();
68 	seed_construct_types();
69 
70 	analyze_typeinfo_list();
71 }
72 
73 void
74 show_typeinfo_list(void)
75 {
76 	ndr_typeinfo_t		*ti;
77 	ndr_typeinfo_t		*tdti;
78 	int			i;
79 	ndr_member_t		*mem;
80 	char			*p;
81 	char			fname_type[NDLBUFSZ];
82 
83 	for (ti = typeinfo_list; ti; ti = ti->next) {
84 		switch (ti->type_op) {
85 		case STRUCT_KW:
86 			p = "struct";
87 			break;
88 
89 		case UNION_KW:
90 			p = "union";
91 			break;
92 
93 		case TYPEDEF_KW:
94 			p = "typedef";
95 			break;
96 
97 		case STRING_KW:
98 		case STAR:
99 		case LB:
100 		case BASIC_TYPE:
101 			type_extern_suffix(ti, fname_type, NDLBUFSZ);
102 			if (ti->is_extern) {
103 				(void) printf("extern ndr_%s()\n",
104 				    fname_type);
105 			} else if (!ti->is_referenced) {
106 				(void) printf("implied ndr_%s\n", fname_type);
107 			}
108 			continue;
109 
110 		default:
111 			(void) printf("show_typeinfo skipping %d\n",
112 			    ti->type_op);
113 			continue;
114 		}
115 
116 		(void) printf("\n\n");
117 		show_advice(&ti->advice, 0);
118 		(void) printf("%s %s {\n", p, ti->type_name->n_sym->name);
119 
120 		for (i = 0; i < ti->n_member; i++) {
121 			mem = &ti->member[i];
122 			show_advice(&mem->advice, 2);
123 			type_extern_suffix(mem->type, fname_type, NDLBUFSZ);
124 			(void) printf("    %-16s ndr_%-13s",
125 			    mem->name, fname_type);
126 
127 			tdti = mem->type;
128 			(void) printf(" fsiz=%d vsiz=%d algn=%d off=%d\n",
129 			    tdti->size_fixed_part,
130 			    tdti->size_variable_part,
131 			    tdti->alignment,
132 			    mem->pdu_offset);
133 		}
134 
135 		(void) printf("} fsiz=%d vsiz=%d algn=%d comp=%d ptrs=%d\n",
136 		    ti->size_fixed_part,
137 		    ti->size_variable_part,
138 		    ti->alignment,
139 		    ti->complete,
140 		    ti->has_pointers);
141 	}
142 }
143 
144 void
145 type_extern_suffix(ndr_typeinfo_t *tsti, char *funcbuf, size_t buflen)
146 {
147 	ndr_typeinfo_t		*ti;
148 	char			*p_fb = funcbuf;
149 
150 	*p_fb = 0;
151 
152 	for (ti = tsti; ti; ti = ti->type_down) {
153 		switch (ti->type_op) {
154 		case BASIC_TYPE:
155 		case STRUCT_KW:
156 		case TYPEDEF_KW:
157 		case UNION_KW:
158 			(void) snprintf(p_fb, buflen, "_%s",
159 			    ti->type_name->n_sym->name);
160 			break;
161 
162 		case STAR:
163 			(void) strlcpy(p_fb, "p", buflen);
164 			break;
165 
166 		case LB:
167 			if (ti->type_dim) {
168 				(void) snprintf(p_fb, buflen, "a%ld",
169 				    ti->type_dim->n_int);
170 			} else {
171 				(void) snprintf(p_fb, buflen, "ac");
172 			}
173 			break;
174 
175 		case STRING_KW:
176 			(void) strlcpy(p_fb, "s", buflen);
177 			break;
178 
179 		default:
180 			(void) snprintf(p_fb, buflen, "?<%d>", ti->type_op);
181 			break;
182 		}
183 		while (*p_fb)
184 			p_fb++;
185 	}
186 }
187 
188 static void
189 type_ident_decl1(struct tup *tup, char *funcbuf, size_t buflen, char *ident)
190 {
191 	ndr_typeinfo_t		*ti;
192 	char			fb[NDLBUFSZ];
193 	char			*p;
194 
195 	if (!tup) {
196 		(void) strlcpy(funcbuf, ident, buflen);
197 		return;
198 	}
199 	ti = tup->ti;
200 
201 	switch (ti->type_op) {
202 	case BASIC_TYPE:
203 	case TYPEDEF_KW:
204 		type_ident_decl1(tup->up, fb, NDLBUFSZ, ident);
205 		(void) snprintf(funcbuf, buflen, "%s%s%s%s",
206 		    "", ti->type_name->n_sym->name, *fb ? " " : "", fb);
207 		break;
208 
209 	case STRUCT_KW:
210 		type_ident_decl1(tup->up, fb, NDLBUFSZ, ident);
211 		(void) snprintf(funcbuf, buflen, "%s%s%s%s",
212 		    "struct ", ti->type_name->n_sym->name, *fb ? " " : "", fb);
213 		break;
214 
215 	case UNION_KW:
216 		type_ident_decl1(tup->up, fb, NDLBUFSZ, ident);
217 		(void) snprintf(funcbuf, buflen, "%s%s%s%s",
218 		    "union ", ti->type_name->n_sym->name, *fb ? " " : "", fb);
219 		break;
220 
221 	case STAR:
222 		*funcbuf = '*';
223 		type_ident_decl1(tup->up, funcbuf+1, buflen - 1, ident);
224 		break;
225 
226 	case LB:
227 		p = fb;
228 		*p++ = '(';
229 		type_ident_decl1(tup->up, p, NDLBUFSZ - 1, ident);
230 		if (*p == '*') {
231 			p = fb;
232 			(void) strlcat(p, ")", NDLBUFSZ);
233 		}
234 		if (ti->type_dim) {
235 			(void) snprintf(funcbuf, buflen, "%s[%ld]",
236 			    p, ti->type_dim->n_int);
237 		} else {
238 			(void) snprintf(funcbuf, buflen,
239 			    "%s[NDR_ANYSIZE_DIM]", p);
240 		}
241 		break;
242 
243 	case STRING_KW:
244 		p = fb;
245 		*p++ = '(';
246 		type_ident_decl1(tup->up, p, NDLBUFSZ - 1, ident);
247 		if (*p == '*') {
248 			p = fb;
249 			(void) strlcat(p, ")", NDLBUFSZ);
250 		}
251 		(void) snprintf(funcbuf, buflen, "%s[NDR_STRING_DIM]", p);
252 		break;
253 
254 	default:
255 		compile_error("unknown type or keyword <%d>", ti->type_op);
256 		break;
257 	}
258 }
259 
260 static void
261 type_ident_decl(ndr_typeinfo_t *tsti, char *funcbuf, size_t buflen, char *ident)
262 {
263 	ndr_typeinfo_t		*ti;
264 	struct tup		tup_tab[40];
265 	struct tup		*tup;
266 	struct tup		*up = 0;
267 	int			n_tt = 0;
268 
269 	for (ti = tsti; ti; ti = ti->type_down, n_tt++) {
270 		tup = &tup_tab[n_tt];
271 		tup->up = up;
272 		tup->ti = ti;
273 		up = tup;
274 	}
275 
276 	type_ident_decl1(up, funcbuf, buflen, ident);
277 }
278 
279 void
280 type_null_decl(ndr_typeinfo_t *tsti, char *funcbuf, size_t buflen)
281 {
282 	funcbuf[0] = '(';
283 	type_ident_decl(tsti, funcbuf+1, buflen, "");
284 	(void) strlcat(funcbuf, ")", buflen);
285 }
286 
287 void
288 type_name_decl(ndr_typeinfo_t *tsti, char *funcbuf, size_t buflen, char *name)
289 {
290 	type_ident_decl(tsti, funcbuf, buflen, name);
291 }
292 
293 void
294 show_advice(ndr_advice_t *adv, int indent)
295 {
296 	int		i;
297 	int		n = 0;
298 
299 	for (i = 0; i < N_ADVICE; i++) {
300 		if (!adv->a_nodes[i])
301 			continue;
302 
303 		if (n++ == 0)
304 			(void) printf("%-*s[", indent, "");
305 		else
306 			(void) printf(" ");
307 
308 		print_node(adv->a_nodes[i]);
309 	}
310 
311 	if (n)
312 		(void) printf("]\n");
313 }
314 
315 static void
316 analyze_typeinfo_list(void)
317 {
318 	ndr_typeinfo_t		*ti;
319 
320 	for (ti = typeinfo_list; ti; ti = ti->next) {
321 		switch (ti->type_op) {
322 		case STRUCT_KW:
323 			analyze_typeinfo_struct(ti);
324 			break;
325 
326 		case UNION_KW:
327 			analyze_typeinfo_union(ti);
328 			break;
329 
330 		case TYPEDEF_KW:
331 			analyze_typeinfo_typedef(ti);
332 			break;
333 		}
334 	}
335 }
336 
337 static void
338 analyze_typeinfo_typedef(ndr_typeinfo_t *ti)
339 {
340 	ndr_node_t		*mem_np;
341 	ndr_member_t		*mem;
342 	int			i;
343 	int			allow;
344 	unsigned long		offset;
345 
346 	assert(ti->type_op == TYPEDEF_KW);
347 
348 	/*
349 	 * Snarf the advice.
350 	 */
351 	determine_advice(&ti->advice, ti->definition->n_c_advice);
352 
353 	/*
354 	 * Convert the members to table.
355 	 * Determine layout metrics along the way.
356 	 */
357 	mem_np = ti->definition->n_c_members;
358 	i = 0;
359 	offset = 0;
360 	assert(i < ti->n_member);
361 	mem = &ti->member[i];
362 
363 	allow = ALLOW_NO_SWITCH;
364 
365 	analyze_member(mem_np, mem,
366 	    &offset,		/* progress offset */
367 	    allow);		/* see above */
368 
369 	assert(1 == ti->n_member);
370 
371 	analyze_typeinfo_aggregate_finish(ti);
372 
373 	/* Align offset to determine overall size */
374 	while (offset & ti->alignment)
375 		offset++;
376 
377 	ti->size_fixed_part = offset;
378 }
379 
380 static void
381 analyze_typeinfo_struct(ndr_typeinfo_t *ti)
382 {
383 	ndr_node_t		*mem_np;
384 	ndr_member_t		*mem;
385 	int			i;
386 	int			allow;
387 	unsigned long		offset;
388 
389 	assert(ti->type_op == STRUCT_KW);
390 
391 	/*
392 	 * Snarf the advice. Only recognize [operation()] for
393 	 * struct definitions.
394 	 */
395 	determine_advice(&ti->advice, ti->definition->n_c_advice);
396 
397 	/*
398 	 * Convert the members from list to table.
399 	 * Determine layout metrics along the way.
400 	 */
401 	mem_np = ti->definition->n_c_members;
402 	i = 0;
403 	offset = 0;
404 	for (; mem_np; i++, mem_np = mem_np->n_next) {
405 		assert(i < ti->n_member);
406 		mem = &ti->member[i];
407 
408 		if (!ti->advice.a_operation /* no var-size in op param */ &&
409 		    i == ti->n_member-1)  /* only last mem may be var-size */
410 			allow = ALLOW_VARSIZE;
411 		else
412 			allow = 0;
413 
414 		analyze_member(mem_np, mem, &offset, allow);
415 	}
416 	assert(i == ti->n_member);
417 
418 	analyze_typeinfo_aggregate_finish(ti);	/* align,complete,ptrs,etc */
419 
420 	/* Align offset to determine overall size */
421 	while (offset & ti->alignment)
422 		offset++;
423 
424 	ti->size_fixed_part = offset;
425 
426 	/* If last member is var-sized, so is this struct */
427 	mem = &ti->member[ti->n_member-1];
428 	ti->size_variable_part = mem->type->size_variable_part;
429 
430 	if (ti->size_variable_part)
431 		ti->is_conformant = 1;
432 }
433 
434 static void
435 analyze_typeinfo_union(ndr_typeinfo_t *ti)
436 {
437 	ndr_node_t		*mem_np;
438 	ndr_member_t		*mem;
439 	int			i;
440 	unsigned long		offset;
441 	unsigned long		size;
442 
443 	assert(ti->type_op == UNION_KW);
444 
445 	/*
446 	 * Snarf the advice. None supported for union definitions.
447 	 * Only [switch_is()] supported for union instances.
448 	 */
449 	determine_advice(&ti->advice, ti->definition->n_c_advice);
450 
451 	/*
452 	 * Convert the members from list to table.
453 	 * Determine layout metrics along the way.
454 	 */
455 	mem_np = ti->definition->n_c_members;
456 	i = 0;
457 	size = 0;
458 	for (; mem_np; i++, mem_np = mem_np->n_next) {
459 		assert(i < ti->n_member);
460 		mem = &ti->member[i];
461 
462 		offset = 0;			/* all members offset=0 */
463 		analyze_member(mem_np, mem,
464 		    &offset,
465 		    ALLOW_CASE+ALLOW_NO_UNIONS); /* var-size disallowed */
466 
467 		if (size < mem->type->size_fixed_part)
468 			size = mem->type->size_fixed_part;
469 	}
470 	assert(i == ti->n_member);
471 
472 	analyze_typeinfo_aggregate_finish(ti);	/* align,complete,ptrs,etc */
473 
474 	/* align size to determine overall size */
475 	while (size & ti->alignment)
476 		size++;
477 
478 	ti->size_fixed_part = size;
479 }
480 
481 static void
482 analyze_typeinfo_aggregate_finish(ndr_typeinfo_t *ti)
483 {
484 	int			i;
485 	ndr_member_t		*mem;
486 	int			complete = 1;
487 	int			has_pointers = 0;
488 
489 	for (i = 0; i < ti->n_member; i++) {
490 		mem = &ti->member[i];
491 
492 		complete &= mem->type->complete;
493 		has_pointers |= mem->type->has_pointers;
494 		ti->alignment |= mem->type->alignment;
495 	}
496 
497 	ti->complete = complete;
498 	ti->has_pointers = has_pointers;
499 }
500 
501 static void
502 analyze_member(ndr_node_t *mem_np, ndr_member_t *mem,
503     unsigned long *offsetp, int allow)
504 {
505 	int			i, n_decl_ops;
506 	ndr_node_t		*decl_ops[NDLBUFSZ];
507 	ndr_typeinfo_t		*type_down;
508 	ndr_typeinfo_t		proto_ti;
509 	ndr_node_t		*np;
510 
511 	/*
512 	 * Set line_number for error reporting (so we know where to look)
513 	 */
514 	line_number = mem_np->line_number;
515 
516 	/*
517 	 * Simple parts of member
518 	 */
519 	mem->definition = mem_np;
520 	determine_advice(&mem->advice, mem_np->n_m_advice);
521 
522 	/*
523 	 * The node list for the declarator is in outside-to-inside
524 	 * order. It is also decorated with the LP nodes for
525 	 * precedence, which are in our way at this point.
526 	 *
527 	 * These two loops reverse the list, which is easier
528 	 * to analyze. For example, the declaration:
529 	 *
530 	 *	ulong *		(id[100]);
531 	 *
532 	 * will have the node list (=> indicates n_d_descend):
533 	 *
534 	 *	ulong  =>  STAR  =>  LP  =>  LB[100]  =>  id
535 	 *
536 	 * and the conversion will result in type info (=> indicates
537 	 * type_down):
538 	 *
539 	 *	id  =>  LB[100]  =>  STAR  =>  ulong
540 	 *
541 	 * which is closer to how you would pronounce the declaration:
542 	 *
543 	 *	id is an array size 100 of pointers to ulong.
544 	 */
545 
546 	/* first pass -- turn the list into a table */
547 	n_decl_ops = 0;
548 	for (np = mem_np->n_m_decl; np; np = np->n_d_descend) {
549 		if (np->label == IDENTIFIER) {
550 			break;		/* done */
551 		}
552 
553 		if (np->label == LP)
554 			continue;	/* ignore precedence nodes */
555 
556 		decl_ops[n_decl_ops++] = np;
557 	}
558 	if (!np) {
559 		compile_error("declaration error");
560 		print_node(mem_np->n_m_decl);
561 		(void) printf("\n");
562 	} else {
563 		mem->name = np->n_sym->name;
564 	}
565 
566 	/* second pass -- turn the table into push-back list */
567 	type_down = find_typeinfo_by_name(mem_np->n_m_type);
568 
569 	if (type_down->type_op == TYPEDEF_KW)
570 		type_down = type_down->member[0].type;
571 
572 	if (mem->advice.a_string) {
573 		bzero(&proto_ti, sizeof (proto_ti));
574 		proto_ti.type_op = STRING_KW;
575 		proto_ti.type_down = type_down;
576 		type_down = bind_typeinfo(&proto_ti);
577 	}
578 
579 	for (i = n_decl_ops; i-- > 0; ) {
580 		np = decl_ops[i];
581 
582 		bzero(&proto_ti, sizeof (proto_ti));
583 
584 		proto_ti.type_op = np->label;
585 		proto_ti.type_down = type_down;
586 
587 		switch (np->label) {
588 		case LB:
589 			proto_ti.type_dim = np->n_d_dim;
590 			break;
591 		}
592 
593 		/*
594 		 * bind_typeinfo() reuses (interns) typeinfo's to
595 		 * make later code generation easier. It will report
596 		 * some errors.
597 		 */
598 		type_down = bind_typeinfo(&proto_ti);
599 	}
600 
601 	/* bind the member to its type info */
602 	mem->type = type_down;
603 	type_down->is_referenced = 1;	/* we handle first-level indirection */
604 
605 	/*
606 	 * Now, apply the type info to the member layout metrics.
607 	 */
608 
609 	/* alignment */
610 	while (*offsetp & type_down->alignment)
611 		++*offsetp;
612 
613 	mem->pdu_offset = *offsetp;
614 
615 	*offsetp += type_down->size_fixed_part;
616 
617 	if (mem->advice.a_length_is)
618 		compile_error("[length_is()] is not supported");
619 
620 	if (mem->advice.a_transmit_as)
621 		compile_error("[transmit_as()] is not supported");
622 
623 	if (mem->advice.a_arg_is)
624 		compile_error("[arg_is()] is not supported");
625 
626 	/*
627 	 * Disallow
628 	 *	[case(x)] TYPE	xxx;
629 	 *	[default] TYPE	xxx;
630 	 *
631 	 * These only make sense within unions.
632 	 */
633 	if (allow & ALLOW_CASE) {
634 		int		n = 0;
635 
636 		if (mem->advice.a_case)
637 			n++;
638 		if (mem->advice.a_default)
639 			n++;
640 
641 		if (n == 0)
642 			compile_error("no [case/default] advice");
643 		else if (n > 1)
644 			compile_error("too many [case/default] advice");
645 	} else {
646 		if (mem->advice.a_case && mem->advice.a_default)
647 			compile_error("[case/default] advice not allowed");
648 	}
649 
650 	/*
651 	 * Disallow
652 	 *	[operation(x)]	TYPE	foo;
653 	 *	[interface(x)]	TYPE	foo;
654 	 *	[uuid(x)]	TYPE	foo;
655 	 *
656 	 * The [operation()] advice may only appear on a struct to
657 	 * indicate that the structure is a top-most (parameter)
658 	 * structure, and the opcode associated with the parameters.
659 	 */
660 	if (mem->advice.a_operation)
661 		compile_error("[operation()] advice not allowed");
662 
663 	if (mem->advice.a_interface)
664 		compile_error("[interface()] advice not allowed");
665 
666 	if (mem->advice.a_uuid)
667 		compile_error("[uuid()] advice not allowed");
668 
669 	/*
670 	 * Allow
671 	 *	[switch_is(x)] union foo	xxx;
672 	 *
673 	 * Disallow [switch_is] on anything which is not a union.
674 	 */
675 	if (mem->advice.a_switch_is && type_down->type_op != UNION_KW) {
676 		compile_error("[switch_is()] advice not allowed");
677 	}
678 
679 	/*
680 	 * Allow
681 	 *	[size_is(x)] TYPE *	ptr;
682 	 *	[size_is(x)] TYPE	arr[];
683 	 *
684 	 * Disallow [size_is()] on anything other than pointer and
685 	 * variable length array.
686 	 */
687 	if (mem->advice.a_size_is &&
688 	    type_down->type_op != STAR &&
689 	    !(type_down->type_op == LB &&
690 	    type_down->type_dim == 0)) {
691 		compile_error("[size_is()] advice not allowed");
692 	}
693 
694 	/*
695 	 * Allow
696 	 *	[string] char *		ptr_string;
697 	 *
698 	 * Disallow [string] on anything else. The determination
699 	 * of size (for the outer header) on anything else is
700 	 * impossible.
701 	 */
702 	if (mem->advice.a_string && type_down->type_op != STAR) {
703 		compile_error("[string] advice not allowed");
704 	}
705 
706 	if (type_down->type_op == LB &&
707 	    type_down->type_dim == 0) { /* var-length array of some sort */
708 
709 		int		n = 0;
710 
711 		/*
712 		 * Requires [size_is()] directive
713 		 *	[size_is(x)] TYPE	array[]
714 		 */
715 
716 		if (mem->advice.a_size_is)
717 			n++;
718 
719 		if (!n)
720 			compile_error("var-size missing sizing directive");
721 		else if (n > 1)
722 			compile_error("var-size too many sizing directives");
723 	}
724 
725 	/*
726 	 * Nested unions and struct members, other than the last one,
727 	 * cannot contain variable sized members.
728 	 */
729 	if (type_down->size_variable_part && !(allow & ALLOW_VARSIZE)) {
730 		compile_error("var-size member not allowed");
731 	}
732 
733 	/*
734 	 * Disallow unions in operations (i.e. [operation()] struct ...),
735 	 * The switch_is() value is not reliably available. DCE/RPC
736 	 * automatically synthesizes an encapsulated union for
737 	 * these situations, which we have to do by hand:
738 	 *
739 	 *	struct { long switch_value; union foo x; } synth;
740 	 *
741 	 * We also can not allow unions within unions because
742 	 * there is no way to pass the separate [switch_is(x)] selector.
743 	 */
744 	if (type_down->type_op == UNION_KW) {
745 		if (allow & ALLOW_NO_UNIONS) {
746 			compile_error("unencapsulated union not allowed");
747 		} else if (!mem->advice.a_switch_is &&
748 		    !(allow & ALLOW_NO_SWITCH)) {
749 			compile_error("union instance without selector");
750 		}
751 	}
752 }
753 
754 static void
755 seed_basic_types(void)
756 {
757 	ndr_symbol_t		*sym;
758 	ndr_typeinfo_t		*ti;
759 	ndr_typeinfo_t		proto_ti;
760 
761 	for (sym = symbol_list; sym; sym = sym->next) {
762 		if (!sym->kw)
763 			continue;
764 
765 		if (sym->kw->token != BASIC_TYPE)
766 			continue;
767 
768 		ti = ndr_alloc(1, sizeof (ndr_typeinfo_t));
769 
770 		ti->type_op = BASIC_TYPE;
771 		ti->definition = &sym->s_node;
772 		ti->type_name = &sym->s_node;
773 		ti->size_fixed_part = sym->kw->value;
774 		ti->alignment = ti->size_fixed_part - 1;
775 		ti->complete = 1;
776 		ti->is_extern = 1;
777 
778 		append_typeinfo(ti);
779 
780 		bzero(&proto_ti, sizeof (proto_ti));
781 		proto_ti.type_op = STRING_KW;
782 		proto_ti.type_down = ti;
783 
784 		ti = bind_typeinfo(&proto_ti);
785 		ti->is_extern = 1;
786 	}
787 }
788 
789 static void
790 seed_construct_types(void)
791 {
792 	ndr_node_t		*construct;
793 	ndr_node_t		*np;
794 	unsigned		n_member;
795 	ndr_typeinfo_t		*ti;
796 
797 	construct = construct_list;
798 	for (; construct; construct = construct->n_next) {
799 		ti = ndr_alloc(1, sizeof (ndr_typeinfo_t));
800 
801 		ti->type_op = construct->label;
802 		ti->definition = construct;
803 
804 		switch (ti->type_op) {
805 		case TYPEDEF_KW:
806 		case STRUCT_KW:
807 		case UNION_KW:
808 			ti->type_name = construct->n_c_typename;
809 
810 			np = construct->n_c_members;
811 			n_member = 0;
812 			for (; np; np = np->n_next)
813 				n_member++;
814 
815 			ti->n_member = n_member;
816 			if (n_member > 0)
817 				ti->member = ndr_alloc(n_member,
818 				    sizeof (ndr_member_t));
819 			break;
820 
821 		default:
822 			fatal_error("seed_construct unknown %d\n", ti->type_op);
823 			break;
824 		}
825 
826 		determine_advice(&ti->advice, construct->n_c_advice);
827 
828 		ti->is_referenced = 1;	/* always generate */
829 
830 		append_typeinfo(ti);
831 	}
832 }
833 
834 static void
835 append_typeinfo(ndr_typeinfo_t *ti)
836 {
837 	ndr_typeinfo_t		**pp;
838 
839 	for (pp = &typeinfo_list; *pp; pp = &(*pp)->next)
840 		;
841 
842 	*pp = ti;
843 	ti->next = 0;
844 }
845 
846 static ndr_typeinfo_t *
847 bind_typeinfo(ndr_typeinfo_t *proto_ti)
848 {
849 	ndr_typeinfo_t		*ti;
850 	ndr_typeinfo_t		*tdti = proto_ti->type_down;
851 
852 	for (ti = typeinfo_list; ti; ti = ti->next) {
853 		if (ti->type_op != proto_ti->type_op)
854 			continue;
855 
856 		switch (ti->type_op) {
857 		case STAR:
858 			if (ti->type_down != proto_ti->type_down)
859 				continue;
860 			break;
861 
862 		case STRING_KW:
863 			if (ti->type_down != proto_ti->type_down)
864 				continue;
865 			break;
866 
867 		case LB:
868 			if (ti->type_down != proto_ti->type_down)
869 				continue;
870 			if (ti->type_dim != proto_ti->type_dim)
871 				continue;
872 			break;
873 
874 		case BASIC_TYPE:
875 		case STRUCT_KW:
876 		case TYPEDEF_KW:
877 		case UNION_KW:
878 			if (ti->type_name != proto_ti->type_name)
879 				continue;
880 			break;
881 
882 		default:
883 			fatal_error("bind_typeinfo unknown %d\n", ti->type_op);
884 			break;
885 		}
886 
887 		return (ti);
888 	}
889 
890 	ti = ndr_alloc(1, sizeof (ndr_typeinfo_t));
891 
892 	*ti = *proto_ti;
893 	append_typeinfo(ti);
894 
895 	switch (ti->type_op) {
896 	case STAR:
897 		ti->size_fixed_part = 4;
898 		ti->alignment = 3;
899 		ti->complete = 1;
900 		ti->has_pointers = 1;
901 		break;
902 
903 	case STRING_KW:
904 	case LB:
905 		if (tdti->complete) {
906 			ti->alignment = tdti->alignment;
907 			if (tdti->size_variable_part) {
908 				compile_error("array of var-size type");
909 			} else if (ti->type_dim) {
910 				ti->size_fixed_part = tdti->size_fixed_part *
911 				    ti->type_dim->n_int;
912 			} else {
913 				ti->size_variable_part = tdti->size_fixed_part;
914 				ti->is_conformant = 1;
915 			}
916 		} else {
917 			compile_error("array of incomplete type");
918 		}
919 
920 		ti->has_pointers = tdti->has_pointers;
921 		ti->complete = 1;
922 		break;
923 
924 	default:
925 		compile_error("bind_type internal error op=%d", ti->type_op);
926 		break;
927 	}
928 
929 	/*
930 	 * Disallow
931 	 *	union foo	*ptrfoo;
932 	 * There is no way to pass the selector (switch_is)in
933 	 */
934 	if (ti->type_op == STAR && ti->type_down->type_op == UNION_KW) {
935 		compile_error("pointers to unions not allowed");
936 	}
937 
938 	/*
939 	 * Disallow
940 	 *	union foo	fooarr[n];
941 	 * Each element needs a distinct selector
942 	 */
943 	if (ti->type_op == LB && ti->type_down->type_op == UNION_KW) {
944 		compile_error("arrays of unions not allowed");
945 	}
946 
947 	return (ti);
948 }
949 
950 static ndr_typeinfo_t *
951 find_typeinfo_by_name(ndr_node_t *typename)
952 {
953 	ndr_typeinfo_t		*ti;
954 
955 	for (ti = typeinfo_list; ti; ti = ti->next) {
956 		if (ti->type_name == typename)
957 			return (ti);
958 	}
959 
960 	compile_error("unknown type %s", typename->n_sym->name);
961 
962 	/* fake BASIC_TYPE */
963 	ti = ndr_alloc(1, sizeof (ndr_typeinfo_t));
964 	ti->type_op = BASIC_TYPE;
965 	ti->definition = typename;
966 	ti->type_name = typename;
967 	ti->size_fixed_part = 0;
968 	ti->alignment = 0;
969 
970 	append_typeinfo(ti);
971 	return (ti);
972 }
973 
974 static void
975 determine_advice(ndr_advice_t *advice, ndr_node_t *advice_list)
976 {
977 	/* alias for basic types */
978 	advice->a_transmit_as = find_advice(advice_list, TRANSMIT_AS_KW);
979 
980 	/* arg used for size, union, or generic purpose */
981 	advice->a_arg_is = find_advice(advice_list, ARG_IS_KW);
982 
983 	/* operation parameter in/out stuff */
984 	advice->a_operation = find_advice(advice_list, OPERATION_KW);
985 	advice->a_in = find_advice(advice_list, IN_KW);
986 	advice->a_out = find_advice(advice_list, OUT_KW);
987 
988 	/* size stuff */
989 	advice->a_string = find_advice(advice_list, STRING_KW);
990 	advice->a_size_is = find_advice(advice_list, SIZE_IS_KW);
991 	advice->a_length_is = find_advice(advice_list, LENGTH_IS_KW);
992 
993 	/* union stuff */
994 	advice->a_case = find_advice(advice_list, CASE_KW);
995 	advice->a_default = find_advice(advice_list, DEFAULT_KW);
996 	advice->a_switch_is = find_advice(advice_list, SWITCH_IS_KW);
997 
998 	/* interface stuff */
999 	advice->a_interface = find_advice(advice_list, INTERFACE_KW);
1000 	advice->a_uuid = find_advice(advice_list, UUID_KW);
1001 	advice->a_no_reorder = find_advice(advice_list, _NO_REORDER_KW);
1002 	advice->a_extern = find_advice(advice_list, EXTERN_KW);
1003 
1004 	advice->a_reference = find_advice(advice_list, REFERENCE_KW);
1005 	advice->a_align = find_advice(advice_list, ALIGN_KW);
1006 }
1007 
1008 static ndr_node_t *
1009 find_advice(ndr_node_t *advice_list, int label)
1010 {
1011 	ndr_node_t		*np;
1012 
1013 	for (np = advice_list; np; np = np->n_next)
1014 		if (np->label == label)
1015 			break;
1016 
1017 	return (np);
1018 }
1019 
1020 void
1021 member_fixup(ndr_node_t *member_np)
1022 {
1023 	ndr_node_t		*np;
1024 
1025 	for (np = member_np->n_m_decl; np; np = np->n_d_descend)
1026 		if (np->label == IDENTIFIER)
1027 			break;
1028 
1029 	member_np->n_m_name = np;
1030 }
1031 
1032 void
1033 construct_fixup(ndr_node_t *construct_np)
1034 {
1035 	construct_np->n_c_typename->n_sym->typedefn = construct_np;
1036 }
1037