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 67 analyze(void) 68 { 69 seed_basic_types(); 70 seed_construct_types(); 71 72 analyze_typeinfo_list(); 73 } 74 75 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 * 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 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 1036 construct_fixup(ndr_node_t *construct_np) 1037 { 1038 construct_np->n_c_typename->n_sym->typedefn = construct_np; 1039 } 1040