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