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