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
analyze(void)65 analyze(void)
66 {
67 seed_basic_types();
68 seed_construct_types();
69
70 analyze_typeinfo_list();
71 }
72
73 void
show_typeinfo_list(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
type_extern_suffix(ndr_typeinfo_t * tsti,char * funcbuf,size_t buflen)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
type_ident_decl1(struct tup * tup,char * funcbuf,size_t buflen,char * ident)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
type_ident_decl(ndr_typeinfo_t * tsti,char * funcbuf,size_t buflen,char * ident)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
type_null_decl(ndr_typeinfo_t * tsti,char * funcbuf,size_t buflen)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
type_name_decl(ndr_typeinfo_t * tsti,char * funcbuf,size_t buflen,char * name)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
show_advice(ndr_advice_t * adv,int indent)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
analyze_typeinfo_list(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
analyze_typeinfo_typedef(ndr_typeinfo_t * ti)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
analyze_typeinfo_struct(ndr_typeinfo_t * ti)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
analyze_typeinfo_union(ndr_typeinfo_t * ti)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
analyze_typeinfo_aggregate_finish(ndr_typeinfo_t * ti)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
analyze_member(ndr_node_t * mem_np,ndr_member_t * mem,unsigned long * offsetp,int allow)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
seed_basic_types(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
seed_construct_types(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
append_typeinfo(ndr_typeinfo_t * ti)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 *
bind_typeinfo(ndr_typeinfo_t * proto_ti)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 *
find_typeinfo_by_name(ndr_node_t * typename)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
determine_advice(ndr_advice_t * advice,ndr_node_t * advice_list)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 *
find_advice(ndr_node_t * advice_list,int label)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
member_fixup(ndr_node_t * member_np)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
construct_fixup(ndr_node_t * construct_np)1033 construct_fixup(ndr_node_t *construct_np)
1034 {
1035 construct_np->n_c_typename->n_sym->typedefn = construct_np;
1036 }
1037