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