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