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