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 2009 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 * Copyright 2024 OmniOS Community Edition (OmniOSce) Association. 30 */ 31 32 #include <string.h> 33 #include "ndrgen.h" 34 #include "y.tab.h" 35 36 37 static void generate_struct(ndr_typeinfo_t *); 38 static void generate_params(ndr_typeinfo_t *); 39 static void generate_union(ndr_typeinfo_t *); 40 static void generate_arg(ndr_node_t *); 41 static void generate_member_macro(char *, char *, ndr_member_t *, 42 ndr_typeinfo_t *); 43 static void generate_member_macro_with_arg(char *, char *, ndr_member_t *, 44 ndr_typeinfo_t *, ndr_node_t *); 45 static void generate_prototypes(ndr_typeinfo_t *, char *); 46 static void generate_member_prototypes(ndr_typeinfo_t *, ndr_member_t *, 47 char *); 48 static void generate_member(ndr_typeinfo_t *, ndr_member_t *); 49 static void generate_aggregate_common_begin(ndr_typeinfo_t *); 50 static void generate_aggregate_common_finish(ndr_typeinfo_t *); 51 static void generate_typeinfo_packing(ndr_typeinfo_t *); 52 static void generate_typeinfo_typeinfo(ndr_typeinfo_t *, int, char *); 53 54 55 void 56 generate(void) 57 { 58 ndr_typeinfo_t *ti; 59 char fname_type[NDLBUFSZ]; 60 61 (void) printf("\n"); 62 63 for (ti = typeinfo_list; ti; ti = ti->next) { 64 if (ti->is_extern || ti->advice.a_extern) { 65 type_extern_suffix(ti, fname_type, NDLBUFSZ); 66 (void) printf( 67 "extern struct ndr_typeinfo ndt_%s;\n", 68 fname_type); 69 continue; 70 } 71 72 switch (ti->type_op) { 73 case STRUCT_KW: 74 if (ti->advice.a_operation) 75 generate_params(ti); 76 else 77 generate_struct(ti); 78 break; 79 80 case UNION_KW: 81 generate_union(ti); 82 break; 83 84 case TYPEDEF_KW: 85 /* silently skip */ 86 continue; 87 88 case STRING_KW: 89 case STAR: 90 case LB: 91 case BASIC_TYPE: 92 if (!ti->is_referenced) { 93 type_extern_suffix(ti, fname_type, NDLBUFSZ); 94 (void) printf("extern ndt_%s\n", fname_type); 95 type_null_decl(ti, fname_type, NDLBUFSZ); 96 (void) printf("/* %s */\n", fname_type); 97 } 98 break; 99 100 default: 101 continue; 102 } 103 } 104 } 105 106 static void 107 generate_struct(ndr_typeinfo_t *ti) 108 { 109 int i; 110 ndr_member_t *mem; 111 112 if (ti->advice.a_no_reorder) { 113 /* just use generate_params(), which can safely do this */ 114 generate_params(ti); 115 return; 116 } 117 118 generate_aggregate_common_begin(ti); 119 120 (void) printf(" /* do all basic elements first */\n"); 121 for (i = 0; i < ti->n_member; i++) { 122 mem = &ti->member[i]; 123 if (mem->type->type_op != BASIC_TYPE) 124 continue; 125 126 generate_member(ti, mem); 127 } 128 129 (void) printf("\n"); 130 (void) printf(" /* do all constructed elements w/o pointers */\n"); 131 for (i = 0; i < ti->n_member; i++) { 132 mem = &ti->member[i]; 133 if (mem->type->type_op == BASIC_TYPE) 134 continue; 135 136 if (mem->type->has_pointers) 137 continue; 138 139 generate_member(ti, mem); 140 } 141 142 (void) printf("\n"); 143 (void) printf(" /* do members with pointers in order */\n"); 144 for (i = 0; i < ti->n_member; i++) { 145 mem = &ti->member[i]; 146 if (mem->type->type_op == BASIC_TYPE) 147 continue; 148 149 if (!mem->type->has_pointers) 150 continue; 151 152 generate_member(ti, mem); 153 } 154 155 generate_aggregate_common_finish(ti); 156 } 157 158 static void 159 generate_params(ndr_typeinfo_t *ti) 160 { 161 int i; 162 ndr_member_t *mem; 163 164 generate_aggregate_common_begin(ti); 165 166 (void) printf(" /* do all members in order */\n"); 167 for (i = 0; i < ti->n_member; i++) { 168 mem = &ti->member[i]; 169 170 generate_member(ti, mem); 171 } 172 173 generate_aggregate_common_finish(ti); 174 } 175 176 static void 177 generate_union(ndr_typeinfo_t *ti) 178 { 179 int i; 180 ndr_member_t *mem; 181 int have_default = 0; 182 ndr_node_t *np; 183 184 generate_aggregate_common_begin(ti); 185 186 (void) printf(" switch (encl_ref->switch_is) {\n"); 187 188 for (i = 0; i < ti->n_member; i++) { 189 mem = &ti->member[i]; 190 191 if ((np = mem->advice.a_case) != 0) { 192 (void) printf(" case "); 193 print_node(np->n_a_arg); 194 (void) printf(":\n"); 195 } else if ((np = mem->advice.a_default) != 0) { 196 (void) printf(" default:\n"); 197 if (have_default++) { 198 compile_error("multiple defaults"); 199 } 200 } else { 201 compile_error("syntax error"); 202 } 203 204 generate_member(ti, mem); 205 (void) printf(" break;\n\n"); 206 } 207 208 if (!have_default) { 209 (void) printf(" default:\n"); 210 (void) printf(" NDR_SET_ERROR(encl_ref, " 211 "NDR_ERR_SWITCH_VALUE_INVALID);\n"); 212 (void) printf(" return 0;\n"); 213 (void) printf(" break;\n"); 214 } 215 216 (void) printf(" }\n"); 217 (void) printf("\n"); 218 219 generate_aggregate_common_finish(ti); 220 } 221 222 static void 223 generate_arg(ndr_node_t *np) 224 { 225 ndr_node_t *arg = np; 226 227 if (np == NULL) { 228 compile_error("invalid node pointer <null>"); 229 return; 230 } 231 232 if (np->label != IDENTIFIER && np->label != INTEGER) 233 arg = np->n_a_arg; 234 235 switch (np->label) { 236 case SIZE_IS_KW: 237 case LENGTH_IS_KW: 238 case SWITCH_IS_KW: 239 (void) printf("val->"); 240 print_field_attr(np); 241 break; 242 default: 243 if (arg->label == IDENTIFIER) 244 (void) printf("val->%s", arg->n_sym->name); 245 else 246 print_node(arg); 247 break; 248 } 249 } 250 251 static void 252 generate_member_macro(char *memkind, char *macro, ndr_member_t *mem, 253 ndr_typeinfo_t *ti) 254 { 255 char fname_type[NDLBUFSZ]; 256 257 if (!macro) 258 macro = ""; 259 if (!ti) 260 ti = mem->type; 261 262 type_extern_suffix(ti, fname_type, NDLBUFSZ); 263 264 if (memkind) { 265 (void) printf(" NDR_%sMEMBER%s (%s, %s);\n", 266 memkind, macro, fname_type, mem->name); 267 } else { 268 (void) printf(" NDR_MEMBER%s (%s, %s, %uUL);\n", 269 macro, fname_type, mem->name, mem->pdu_offset); 270 } 271 } 272 273 static void 274 generate_member_macro_with_arg(char *memkind, char *macro, 275 ndr_member_t *mem, ndr_typeinfo_t *ti, ndr_node_t *np) 276 { 277 char fname_type[NDLBUFSZ]; 278 279 if (!macro) 280 macro = "_WITH_ARG"; 281 if (!ti) 282 ti = mem->type; 283 284 type_extern_suffix(ti, fname_type, NDLBUFSZ); 285 286 if (memkind) { 287 (void) printf(" NDR_%sMEMBER%s (%s, %s,\n", 288 memkind, macro, fname_type, mem->name); 289 } else { 290 (void) printf(" NDR_MEMBER%s (%s, %s, %uUL,\n", 291 macro, fname_type, mem->name, mem->pdu_offset); 292 } 293 294 (void) printf("\t\t"); 295 generate_arg(np); 296 (void) printf(");\n"); 297 } 298 299 static void 300 generate_prototypes(ndr_typeinfo_t *ti, char *fname_type) 301 { 302 ndr_member_t *mem; 303 int i; 304 305 if (ti->type_op == STRUCT_KW && ti->advice.a_operation) { 306 for (i = 0; i < ti->n_member; i++) { 307 mem = &ti->member[i]; 308 309 generate_member_prototypes(ti, mem, fname_type); 310 } 311 } 312 } 313 314 static void 315 generate_member_prototypes(ndr_typeinfo_t *ti, 316 ndr_member_t *mem, char *fname_type) 317 { 318 char val_buf[NDLBUFSZ]; 319 ndr_typeinfo_t ptr; 320 321 if (mem->type->type_op == UNION_KW) { 322 if (!mem->advice.a_in && mem->advice.a_out) { 323 ptr.type_op = STAR; 324 ptr.type_down = ti; 325 type_name_decl(&ptr, val_buf, NDLBUFSZ, "val"); 326 327 (void) printf("\nextern void fixup%s(%s);\n", 328 fname_type, val_buf); 329 } 330 } 331 } 332 333 static void 334 generate_member(ndr_typeinfo_t *ti, ndr_member_t *mem) 335 { 336 static char *fixup[] = { 337 "/*", 338 " * Cannot use the canned offsets to unmarshall multiple", 339 " * entry discriminated unions. The service must provide", 340 " * this function to patch the offsets at runtime.", 341 " */" 342 }; 343 344 char fname_type[NDLBUFSZ]; 345 ndr_node_t *np; 346 int is_reference = 0; 347 char *memkind = 0; 348 int cond_pending = 0; 349 int i; 350 351 if (ti->advice.a_operation) 352 memkind = "TOPMOST_"; 353 else if (ti->advice.a_interface) 354 memkind = "PARAMS_"; 355 356 if (mem->advice.a_in && !mem->advice.a_out) { 357 cond_pending = 1; 358 (void) printf(" if (NDR_DIR_IS_IN) {\n"); 359 } 360 361 if (!mem->advice.a_in && mem->advice.a_out) { 362 cond_pending = 1; 363 (void) printf(" if (NDR_DIR_IS_OUT) {\n"); 364 } 365 366 type_extern_suffix(ti, fname_type, NDLBUFSZ); 367 368 switch (mem->type->type_op) { 369 case BASIC_TYPE: 370 case STRUCT_KW: 371 generate_member_macro(memkind, 0, mem, 0); 372 break; 373 374 case UNION_KW: 375 np = mem->advice.a_switch_is; 376 377 if (!mem->advice.a_in && mem->advice.a_out) { 378 for (i = 0; i < sizeof (fixup)/sizeof (fixup[0]); ++i) 379 (void) printf("\t%s\n", fixup[i]); 380 381 (void) printf("\tfixup%s(val);\n", fname_type); 382 } 383 384 generate_member_macro_with_arg(memkind, 385 "_WITH_SWITCH_IS", mem, 0, np); 386 break; 387 388 case STAR: 389 if (mem->advice.a_reference) 390 is_reference = 1; 391 else 392 is_reference = 0; 393 394 np = mem->advice.a_size_is; 395 if (np) { 396 generate_member_macro_with_arg(memkind, 397 is_reference ? 398 "_REF_WITH_SIZE_IS" : "_PTR_WITH_SIZE_IS", 399 mem, mem->type->type_down, np); 400 break; 401 } 402 403 np = mem->advice.a_length_is; 404 if (np) { 405 generate_member_macro_with_arg(memkind, 406 is_reference ? 407 "_REF_WITH_LENGTH_IS" : "_PTR_WITH_LENGTH_IS", 408 mem, mem->type->type_down, np); 409 break; 410 } 411 412 generate_member_macro(memkind, 413 is_reference ? "_REF" : "_PTR", 414 mem, mem->type->type_down); 415 break; 416 417 case LB: 418 np = mem->advice.a_size_is; 419 if (np) { 420 generate_member_macro_with_arg(memkind, 421 "_ARR_WITH_SIZE_IS", 422 mem, mem->type->type_down, np); 423 break; 424 } 425 426 np = mem->advice.a_length_is; 427 if (np) { 428 generate_member_macro_with_arg(memkind, 429 "_WITH_LENGTH_IS", 430 mem, mem->type->type_down, np); 431 break; 432 } 433 434 generate_member_macro_with_arg(memkind, 435 "_ARR_WITH_DIMENSION", 436 mem, mem->type->type_down, mem->type->type_dim); 437 break; 438 439 default: 440 generate_member_macro(memkind, "_???", mem, 0); 441 break; 442 } 443 444 if (cond_pending) 445 (void) printf(" }\n"); 446 } 447 448 static void 449 generate_aggregate_common_begin(ndr_typeinfo_t *ti) 450 { 451 char val_buf[NDLBUFSZ]; 452 char cast_buf[NDLBUFSZ]; 453 char fname_type[NDLBUFSZ]; 454 ndr_typeinfo_t ptr; 455 456 type_extern_suffix(ti, fname_type, NDLBUFSZ); 457 generate_typeinfo_typeinfo(ti, 0, fname_type); 458 generate_prototypes(ti, fname_type); 459 460 (void) printf("\n"); 461 (void) printf("/*\n * "); 462 show_advice(&ti->advice, 0); 463 (void) printf(" */\n"); 464 (void) printf("int\n"); 465 (void) printf("ndr_%s (struct ndr_reference *encl_ref)\n", 466 fname_type); 467 (void) printf("{\n"); 468 469 ptr.type_op = STAR; 470 ptr.type_down = ti; 471 472 type_name_decl(&ptr, val_buf, NDLBUFSZ, "val"); 473 type_null_decl(&ptr, cast_buf, NDLBUFSZ); 474 475 (void) printf(" %s = %s encl_ref->datum;\n", val_buf, cast_buf); 476 477 (void) printf(" struct ndr_reference myref;\n"); 478 (void) printf("\n"); 479 (void) printf(" (void) bzero(&myref, sizeof (myref));\n"); 480 (void) printf(" myref.enclosing = encl_ref;\n"); 481 (void) printf(" myref.stream = encl_ref->stream;\n"); 482 generate_typeinfo_packing(ti); 483 (void) printf("\n"); 484 } 485 486 /* ARGSUSED */ 487 static void 488 generate_aggregate_common_finish(ndr_typeinfo_t *ti) 489 { 490 (void) printf("\n"); 491 (void) printf(" return 1;\n"); 492 (void) printf("}\n"); 493 } 494 495 /* 496 * Structures are normally 4-byte (dword) aligned but the align directive 497 * can be used to pack on a 2-byte (word) boundary. An align value of 498 * zero is taken to mean use default (dword) alignment. Default packing 499 * doesn't need to be flagged. 500 */ 501 static void 502 generate_typeinfo_packing(ndr_typeinfo_t *ti) 503 { 504 ndr_node_t *np; 505 unsigned long packing; 506 507 if ((np = ti->advice.a_align) == NULL) 508 return; 509 510 if ((np = np->n_a_arg) == NULL) 511 return; 512 513 packing = np->n_int; 514 if ((packing == 0) || (packing == 4)) { 515 /* default alignment */ 516 return; 517 } 518 519 if (packing != 2) { 520 fatal_error("invalid align directive: %lu", packing); 521 /* NOTREACHED */ 522 } 523 524 (void) printf(" myref.packed_alignment = %lu;\n", packing); 525 } 526 527 static void 528 generate_typeinfo_typeinfo(ndr_typeinfo_t *ti, int is_static, char *fname_type) 529 { 530 char flags[NDLBUFSZ]; 531 532 *flags = 0; 533 if (ti->is_conformant) 534 (void) strlcat(flags, "|NDR_F_CONFORMANT", NDLBUFSZ); 535 536 if (ti->advice.a_fake) 537 (void) strlcat(flags, "|NDR_F_FAKE", NDLBUFSZ); 538 539 if (ti->type_op == STRUCT_KW) { 540 if (ti->advice.a_operation) 541 (void) strlcat(flags, "|NDR_F_OPERATION", NDLBUFSZ); 542 else 543 (void) strlcat(flags, "|NDR_F_STRUCT", NDLBUFSZ); 544 } 545 546 if (ti->type_op == UNION_KW) { 547 if (ti->advice.a_interface) 548 (void) strlcat(flags, "|NDR_F_INTERFACE", NDLBUFSZ); 549 else 550 (void) strlcat(flags, "|NDR_F_UNION", NDLBUFSZ); 551 } 552 553 if (ti->type_op == STRING_KW) 554 (void) strlcat(flags, "|NDR_F_STRING", NDLBUFSZ); 555 if (ti->type_op == LB) 556 (void) strlcat(flags, "|NDR_F_ARRAY", NDLBUFSZ); 557 if (ti->type_op == STAR) 558 (void) strlcat(flags, "|NDR_F_POINTER", NDLBUFSZ); 559 560 if (*flags == 0) 561 (void) strlcpy(flags, "NDR_F_NONE", NDLBUFSZ); 562 else 563 (void) memmove(flags, flags + 1, NDLBUFSZ - 1); 564 565 (void) printf("\n\n\n"); 566 if (is_static) 567 (void) printf("static "); 568 569 (void) printf("int ndr_%s (struct ndr_reference *encl_ref);\n", 570 fname_type); 571 if (is_static) 572 (void) printf("static "); 573 574 (void) printf("struct ndr_typeinfo ndt_%s = {\n", fname_type); 575 (void) printf("\t1, /* NDR version */\n"); 576 (void) printf("\t%d, /* alignment */\n", ti->alignment); 577 (void) printf("\t%s, /* flags */\n", flags); 578 (void) printf("\tndr_%s, /* ndr_func */\n", fname_type); 579 (void) printf("\t%d, /* pdu_size_fixed_part */\n", 580 ti->size_fixed_part); 581 (void) printf("\t%d, /* pdu_size_variable_part */\n", 582 ti->size_variable_part); 583 584 (void) printf("\t%d, /* c_size_fixed_part */\n", 585 ti->size_fixed_part); 586 (void) printf("\t%d, /* c_size_variable_part */\n", 587 ti->size_variable_part); 588 (void) printf("};\n\n"); 589 } 590