Home | History | Annotate | Download | only in ndrgen
      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