1 /* 2 * IDL Compiler 3 * 4 * Copyright 2002 Ove Kaaven 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #ifdef HAVE_UNISTD_H 27 # include <unistd.h> 28 #endif 29 #include <string.h> 30 #include <ctype.h> 31 32 #include "widl.h" 33 #include "utils.h" 34 #include "parser.h" 35 #include "header.h" 36 #include "expr.h" 37 #include "typetree.h" 38 #include "typelib.h" 39 40 static int indentation = 0; 41 static int is_object_interface = 0; 42 user_type_list_t user_type_list = LIST_INIT(user_type_list); 43 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); 44 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list); 45 46 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name); 47 48 static void indent(FILE *h, int delta) 49 { 50 int c; 51 if (delta < 0) indentation += delta; 52 for (c=0; c<indentation; c++) fprintf(h, " "); 53 if (delta > 0) indentation += delta; 54 } 55 56 static void write_line(FILE *f, int delta, const char *fmt, ...) 57 { 58 va_list ap; 59 indent(f, delta); 60 va_start(ap, fmt); 61 vfprintf(f, fmt, ap); 62 va_end(ap); 63 fprintf(f, "\n"); 64 } 65 66 int is_ptrchain_attr(const var_t *var, enum attr_type t) 67 { 68 if (is_attr(var->attrs, t)) 69 return 1; 70 else 71 { 72 type_t *type = var->type; 73 for (;;) 74 { 75 if (is_attr(type->attrs, t)) 76 return 1; 77 else if (type_is_alias(type)) 78 type = type_alias_get_aliasee(type); 79 else if (is_ptr(type)) 80 type = type_pointer_get_ref(type); 81 else return 0; 82 } 83 } 84 } 85 86 int is_aliaschain_attr(const type_t *type, enum attr_type attr) 87 { 88 const type_t *t = type; 89 for (;;) 90 { 91 if (is_attr(t->attrs, attr)) 92 return 1; 93 else if (type_is_alias(t)) 94 t = type_alias_get_aliasee(t); 95 else return 0; 96 } 97 } 98 99 int is_attr(const attr_list_t *list, enum attr_type t) 100 { 101 const attr_t *attr; 102 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 103 if (attr->type == t) return 1; 104 return 0; 105 } 106 107 void *get_attrp(const attr_list_t *list, enum attr_type t) 108 { 109 const attr_t *attr; 110 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 111 if (attr->type == t) return attr->u.pval; 112 return NULL; 113 } 114 115 unsigned int get_attrv(const attr_list_t *list, enum attr_type t) 116 { 117 const attr_t *attr; 118 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 119 if (attr->type == t) return attr->u.ival; 120 return 0; 121 } 122 123 static void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) 124 { 125 if (!uuid) return; 126 fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," 127 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n", 128 guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], 129 uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], 130 uuid->Data4[6], uuid->Data4[7]); 131 } 132 133 static void write_uuid_decl(FILE *f, type_t *type, const UUID *uuid) 134 { 135 char *name = format_namespace(type->namespace, "", "::", type->name); 136 fprintf(f, "#ifdef __CRT_UUID_DECL\n"); 137 fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," 138 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", 139 name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], 140 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], 141 uuid->Data4[7]); 142 fprintf(f, "#endif\n"); 143 free(name); 144 } 145 146 static const char *uuid_string(const UUID *uuid) 147 { 148 static char buf[37]; 149 150 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 151 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], 152 uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); 153 154 return buf; 155 } 156 157 static void write_namespace_start(FILE *header, struct namespace *namespace) 158 { 159 if(is_global_namespace(namespace)) { 160 if(use_abi_namespace) 161 write_line(header, 1, "namespace ABI {"); 162 return; 163 } 164 165 write_namespace_start(header, namespace->parent); 166 write_line(header, 1, "namespace %s {", namespace->name); 167 } 168 169 static void write_namespace_end(FILE *header, struct namespace *namespace) 170 { 171 if(is_global_namespace(namespace)) { 172 if(use_abi_namespace) 173 write_line(header, -1, "}", namespace->name); 174 return; 175 } 176 177 write_line(header, -1, "}", namespace->name); 178 write_namespace_end(header, namespace->parent); 179 } 180 181 const char *get_name(const var_t *v) 182 { 183 static char buffer[256]; 184 185 if (is_attr( v->attrs, ATTR_PROPGET )) 186 strcpy( buffer, "get_" ); 187 else if (is_attr( v->attrs, ATTR_PROPPUT )) 188 strcpy( buffer, "put_" ); 189 else if (is_attr( v->attrs, ATTR_PROPPUTREF )) 190 strcpy( buffer, "putref_" ); 191 else 192 buffer[0] = 0; 193 strcat( buffer, v->name ); 194 return buffer; 195 } 196 197 static void write_fields(FILE *h, var_list_t *fields) 198 { 199 unsigned nameless_struct_cnt = 0, nameless_struct_i = 0, nameless_union_cnt = 0, nameless_union_i = 0; 200 const char *name; 201 char buf[32]; 202 var_t *v; 203 204 if (!fields) return; 205 206 LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { 207 if (!v || !v->type) continue; 208 209 switch(type_get_type_detect_alias(v->type)) { 210 case TYPE_STRUCT: 211 case TYPE_ENCAPSULATED_UNION: 212 nameless_struct_cnt++; 213 break; 214 case TYPE_UNION: 215 nameless_union_cnt++; 216 break; 217 default: 218 ; 219 } 220 } 221 222 LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { 223 if (!v || !v->type) continue; 224 225 indent(h, 0); 226 name = v->name; 227 228 switch(type_get_type_detect_alias(v->type)) { 229 case TYPE_STRUCT: 230 case TYPE_ENCAPSULATED_UNION: 231 if(!v->name) { 232 fprintf(h, "__C89_NAMELESS "); 233 if(nameless_struct_cnt == 1) { 234 name = "__C89_NAMELESSSTRUCTNAME"; 235 }else if(nameless_struct_i < 5 /* # of supporting macros */) { 236 sprintf(buf, "__C89_NAMELESSSTRUCTNAME%d", ++nameless_struct_i); 237 name = buf; 238 } 239 } 240 break; 241 case TYPE_UNION: 242 if(!v->name) { 243 fprintf(h, "__C89_NAMELESS "); 244 if(nameless_union_cnt == 1) { 245 name = "__C89_NAMELESSUNIONNAME"; 246 }else if(nameless_union_i < 8 /* # of supporting macros */ ) { 247 sprintf(buf, "__C89_NAMELESSUNIONNAME%d", ++nameless_union_i); 248 name = buf; 249 } 250 } 251 break; 252 default: 253 ; 254 } 255 write_type_def_or_decl(h, v->type, TRUE, name); 256 fprintf(h, ";\n"); 257 } 258 } 259 260 static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) 261 { 262 var_t *v; 263 if (!enums) return; 264 LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) 265 { 266 if (v->name) { 267 indent(h, 0); 268 if(!enum_name) 269 fprintf(h, "%s", get_name(v)); 270 else 271 fprintf(h, "%s_%s", enum_name, get_name(v)); 272 if (v->eval) { 273 fprintf(h, " = "); 274 write_expr(h, v->eval, 0, 1, NULL, NULL, ""); 275 } 276 } 277 if (list_next( enums, &v->entry )) fprintf(h, ",\n"); 278 } 279 fprintf(h, "\n"); 280 } 281 282 int needs_space_after(type_t *t) 283 { 284 return (type_is_alias(t) || 285 (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name))); 286 } 287 288 void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) 289 { 290 const char *name; 291 292 if (!h) return; 293 294 name = type_get_name(t, name_type); 295 296 if (is_attr(t->attrs, ATTR_CONST) && 297 (type_is_alias(t) || !is_ptr(t))) 298 fprintf(h, "const "); 299 300 if (type_is_alias(t)) fprintf(h, "%s", t->name); 301 else { 302 switch (type_get_type_detect_alias(t)) { 303 case TYPE_ENUM: 304 if (!declonly && t->defined && !t->written) { 305 if (name) fprintf(h, "enum %s {\n", name); 306 else fprintf(h, "enum {\n"); 307 t->written = TRUE; 308 indentation++; 309 write_enums(h, type_enum_get_values(t), is_global_namespace(t->namespace) ? NULL : t->name); 310 indent(h, -1); 311 fprintf(h, "}"); 312 } 313 else fprintf(h, "enum %s", name ? name : ""); 314 break; 315 case TYPE_STRUCT: 316 case TYPE_ENCAPSULATED_UNION: 317 if (!declonly && t->defined && !t->written) { 318 if (name) fprintf(h, "struct %s {\n", name); 319 else fprintf(h, "struct {\n"); 320 t->written = TRUE; 321 indentation++; 322 if (type_get_type(t) != TYPE_STRUCT) 323 write_fields(h, type_encapsulated_union_get_fields(t)); 324 else 325 write_fields(h, type_struct_get_fields(t)); 326 indent(h, -1); 327 fprintf(h, "}"); 328 } 329 else fprintf(h, "struct %s", name ? name : ""); 330 break; 331 case TYPE_UNION: 332 if (!declonly && t->defined && !t->written) { 333 if (t->name) fprintf(h, "union %s {\n", t->name); 334 else fprintf(h, "union {\n"); 335 t->written = TRUE; 336 indentation++; 337 write_fields(h, type_union_get_cases(t)); 338 indent(h, -1); 339 fprintf(h, "}"); 340 } 341 else fprintf(h, "union %s", t->name ? t->name : ""); 342 break; 343 case TYPE_POINTER: 344 write_type_left(h, type_pointer_get_ref(t), name_type, declonly); 345 fprintf(h, "%s*", needs_space_after(type_pointer_get_ref(t)) ? " " : ""); 346 if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); 347 break; 348 case TYPE_ARRAY: 349 if (t->name && type_array_is_decl_as_ptr(t)) 350 fprintf(h, "%s", t->name); 351 else 352 { 353 write_type_left(h, type_array_get_element(t), name_type, declonly); 354 if (type_array_is_decl_as_ptr(t)) 355 fprintf(h, "%s*", needs_space_after(type_array_get_element(t)) ? " " : ""); 356 } 357 break; 358 case TYPE_BASIC: 359 if (type_basic_get_type(t) != TYPE_BASIC_INT32 && 360 type_basic_get_type(t) != TYPE_BASIC_INT64 && 361 type_basic_get_type(t) != TYPE_BASIC_HYPER) 362 { 363 if (type_basic_get_sign(t) < 0) fprintf(h, "signed "); 364 else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned "); 365 } 366 switch (type_basic_get_type(t)) 367 { 368 case TYPE_BASIC_INT8: fprintf(h, "small"); break; 369 case TYPE_BASIC_INT16: fprintf(h, "short"); break; 370 case TYPE_BASIC_INT: fprintf(h, "int"); break; 371 case TYPE_BASIC_INT3264: fprintf(h, "__int3264"); break; 372 case TYPE_BASIC_BYTE: fprintf(h, "byte"); break; 373 case TYPE_BASIC_CHAR: fprintf(h, "char"); break; 374 case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break; 375 case TYPE_BASIC_FLOAT: fprintf(h, "float"); break; 376 case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break; 377 case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break; 378 case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break; 379 case TYPE_BASIC_INT32: 380 if (type_basic_get_sign(t) > 0) 381 fprintf(h, "ULONG"); 382 else 383 fprintf(h, "LONG"); 384 break; 385 case TYPE_BASIC_INT64: 386 if (type_basic_get_sign(t) > 0) 387 fprintf(h, "UINT64"); 388 else 389 fprintf(h, "INT64"); 390 break; 391 case TYPE_BASIC_HYPER: 392 if (type_basic_get_sign(t) > 0) 393 fprintf(h, "MIDL_uhyper"); 394 else 395 fprintf(h, "hyper"); 396 break; 397 } 398 break; 399 case TYPE_INTERFACE: 400 case TYPE_MODULE: 401 case TYPE_COCLASS: 402 fprintf(h, "%s", t->name); 403 break; 404 case TYPE_VOID: 405 fprintf(h, "void"); 406 break; 407 case TYPE_BITFIELD: 408 write_type_left(h, type_bitfield_get_field(t), name_type, declonly); 409 break; 410 case TYPE_ALIAS: 411 case TYPE_FUNCTION: 412 /* handled elsewhere */ 413 assert(0); 414 break; 415 } 416 } 417 } 418 419 void write_type_right(FILE *h, type_t *t, int is_field) 420 { 421 if (!h) return; 422 423 switch (type_get_type(t)) 424 { 425 case TYPE_ARRAY: 426 if (!type_array_is_decl_as_ptr(t)) 427 { 428 if (is_conformant_array(t)) 429 { 430 fprintf(h, "[%s]", is_field ? "1" : ""); 431 t = type_array_get_element(t); 432 } 433 for ( ; 434 type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t); 435 t = type_array_get_element(t)) 436 fprintf(h, "[%u]", type_array_get_dim(t)); 437 } 438 break; 439 case TYPE_BITFIELD: 440 fprintf(h, " : %u", type_bitfield_get_bits(t)->cval); 441 break; 442 case TYPE_VOID: 443 case TYPE_BASIC: 444 case TYPE_ENUM: 445 case TYPE_STRUCT: 446 case TYPE_ENCAPSULATED_UNION: 447 case TYPE_UNION: 448 case TYPE_ALIAS: 449 case TYPE_MODULE: 450 case TYPE_COCLASS: 451 case TYPE_FUNCTION: 452 case TYPE_INTERFACE: 453 case TYPE_POINTER: 454 break; 455 } 456 } 457 458 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name) 459 { 460 type_t *pt = NULL; 461 int ptr_level = 0; 462 463 if (!h) return; 464 465 if (t) { 466 for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) 467 ; 468 469 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 470 int i; 471 const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); 472 if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; 473 if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); 474 write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly); 475 fputc(' ', h); 476 if (ptr_level) fputc('(', h); 477 if (callconv) fprintf(h, "%s ", callconv); 478 for (i = 0; i < ptr_level; i++) 479 fputc('*', h); 480 } else 481 write_type_left(h, t, NAME_DEFAULT, declonly); 482 } 483 484 if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); 485 486 if (t) { 487 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 488 const var_list_t *args = type_function_get_args(pt); 489 490 if (ptr_level) fputc(')', h); 491 fputc('(', h); 492 if (args) 493 write_args(h, args, NULL, 0, FALSE); 494 else 495 fprintf(h, "void"); 496 fputc(')', h); 497 } else 498 write_type_right(h, t, is_field); 499 } 500 } 501 502 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name) 503 { 504 write_type_v(f, t, field, FALSE, name); 505 } 506 507 static void write_type_definition(FILE *f, type_t *t) 508 { 509 int in_namespace = t->namespace && !is_global_namespace(t->namespace); 510 int save_written = t->written; 511 512 if(in_namespace) { 513 fprintf(f, "#ifdef __cplusplus\n"); 514 fprintf(f, "} /* extern \"C\" */\n"); 515 write_namespace_start(f, t->namespace); 516 } 517 indent(f, 0); 518 write_type_left(f, t, NAME_DEFAULT, FALSE); 519 fprintf(f, ";\n"); 520 if(in_namespace) { 521 t->written = save_written; 522 write_namespace_end(f, t->namespace); 523 fprintf(f, "extern \"C\" {\n"); 524 fprintf(f, "#else\n"); 525 write_type_left(f, t, NAME_C, FALSE); 526 fprintf(f, ";\n"); 527 fprintf(f, "#endif\n\n"); 528 } 529 } 530 531 void write_type_decl(FILE *f, type_t *t, const char *name) 532 { 533 write_type_v(f, t, FALSE, TRUE, name); 534 } 535 536 void write_type_decl_left(FILE *f, type_t *t) 537 { 538 write_type_left(f, t, NAME_DEFAULT, TRUE); 539 } 540 541 static int user_type_registered(const char *name) 542 { 543 user_type_t *ut; 544 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 545 if (!strcmp(name, ut->name)) 546 return 1; 547 return 0; 548 } 549 550 static int context_handle_registered(const char *name) 551 { 552 context_handle_t *ch; 553 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 554 if (!strcmp(name, ch->name)) 555 return 1; 556 return 0; 557 } 558 559 static int generic_handle_registered(const char *name) 560 { 561 generic_handle_t *gh; 562 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 563 if (!strcmp(name, gh->name)) 564 return 1; 565 return 0; 566 } 567 568 unsigned int get_context_handle_offset( const type_t *type ) 569 { 570 context_handle_t *ch; 571 unsigned int index = 0; 572 573 while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) 574 { 575 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 576 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 577 else error( "internal error: %s is not a context handle\n", type->name ); 578 } 579 LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) 580 { 581 if (!strcmp( type->name, ch->name )) return index; 582 index++; 583 } 584 error( "internal error: %s is not registered as a context handle\n", type->name ); 585 return index; 586 } 587 588 unsigned int get_generic_handle_offset( const type_t *type ) 589 { 590 generic_handle_t *gh; 591 unsigned int index = 0; 592 593 while (!is_attr( type->attrs, ATTR_HANDLE )) 594 { 595 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 596 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 597 else error( "internal error: %s is not a generic handle\n", type->name ); 598 } 599 LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) 600 { 601 if (!strcmp( type->name, gh->name )) return index; 602 index++; 603 } 604 error( "internal error: %s is not registered as a generic handle\n", type->name ); 605 return index; 606 } 607 608 /* check for types which require additional prototypes to be generated in the 609 * header */ 610 void check_for_additional_prototype_types(const var_list_t *list) 611 { 612 const var_t *v; 613 614 if (!list) return; 615 LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) 616 { 617 type_t *type = v->type; 618 if (!type) continue; 619 for (;;) { 620 const char *name = type->name; 621 if (type->user_types_registered) break; 622 type->user_types_registered = 1; 623 if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { 624 if (!context_handle_registered(name)) 625 { 626 context_handle_t *ch = xmalloc(sizeof(*ch)); 627 ch->name = xstrdup(name); 628 list_add_tail(&context_handle_list, &ch->entry); 629 } 630 /* don't carry on parsing fields within this type */ 631 break; 632 } 633 if ((type_get_type(type) != TYPE_BASIC || 634 type_basic_get_type(type) != TYPE_BASIC_HANDLE) && 635 is_attr(type->attrs, ATTR_HANDLE)) { 636 if (!generic_handle_registered(name)) 637 { 638 generic_handle_t *gh = xmalloc(sizeof(*gh)); 639 gh->name = xstrdup(name); 640 list_add_tail(&generic_handle_list, &gh->entry); 641 } 642 /* don't carry on parsing fields within this type */ 643 break; 644 } 645 if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { 646 if (!user_type_registered(name)) 647 { 648 user_type_t *ut = xmalloc(sizeof *ut); 649 ut->name = xstrdup(name); 650 list_add_tail(&user_type_list, &ut->entry); 651 } 652 /* don't carry on parsing fields within this type as we are already 653 * using a wire marshaled type */ 654 break; 655 } 656 else if (type_is_complete(type)) 657 { 658 var_list_t *vars; 659 switch (type_get_type_detect_alias(type)) 660 { 661 case TYPE_ENUM: 662 vars = type_enum_get_values(type); 663 break; 664 case TYPE_STRUCT: 665 vars = type_struct_get_fields(type); 666 break; 667 case TYPE_UNION: 668 vars = type_union_get_cases(type); 669 break; 670 default: 671 vars = NULL; 672 break; 673 } 674 check_for_additional_prototype_types(vars); 675 } 676 677 if (type_is_alias(type)) 678 type = type_alias_get_aliasee(type); 679 else if (is_ptr(type)) 680 type = type_pointer_get_ref(type); 681 else if (is_array(type)) 682 type = type_array_get_element(type); 683 else 684 break; 685 } 686 } 687 } 688 689 static void write_user_types(FILE *header) 690 { 691 user_type_t *ut; 692 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 693 { 694 const char *name = ut->name; 695 fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name); 696 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name); 697 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name); 698 fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name); 699 } 700 } 701 702 static void write_context_handle_rundowns(FILE *header) 703 { 704 context_handle_t *ch; 705 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 706 { 707 const char *name = ch->name; 708 fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name); 709 } 710 } 711 712 static void write_generic_handle_routines(FILE *header) 713 { 714 generic_handle_t *gh; 715 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 716 { 717 const char *name = gh->name; 718 fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name); 719 fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name); 720 } 721 } 722 723 static void write_typedef(FILE *header, type_t *type) 724 { 725 fprintf(header, "typedef "); 726 write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); 727 fprintf(header, ";\n"); 728 } 729 730 int is_const_decl(const var_t *var) 731 { 732 const type_t *t; 733 /* strangely, MIDL accepts a const attribute on any pointer in the 734 * declaration to mean that data isn't being instantiated. this appears 735 * to be a bug, but there is no benefit to being incompatible with MIDL, 736 * so we'll do the same thing */ 737 for (t = var->type; ; ) 738 { 739 if (is_attr(t->attrs, ATTR_CONST)) 740 return TRUE; 741 else if (is_ptr(t)) 742 t = type_pointer_get_ref(t); 743 else break; 744 } 745 return FALSE; 746 } 747 748 static void write_declaration(FILE *header, const var_t *v) 749 { 750 if (is_const_decl(v) && v->eval) 751 { 752 fprintf(header, "#define %s (", v->name); 753 write_expr(header, v->eval, 0, 1, NULL, NULL, ""); 754 fprintf(header, ")\n\n"); 755 } 756 else 757 { 758 switch (v->stgclass) 759 { 760 case STG_NONE: 761 case STG_REGISTER: /* ignored */ 762 break; 763 case STG_STATIC: 764 fprintf(header, "static "); 765 break; 766 case STG_EXTERN: 767 fprintf(header, "extern "); 768 break; 769 } 770 write_type_def_or_decl(header, v->type, FALSE, v->name); 771 fprintf(header, ";\n\n"); 772 } 773 } 774 775 static void write_library(FILE *header, const typelib_t *typelib) 776 { 777 const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID); 778 fprintf(header, "\n"); 779 write_guid(header, "LIBID", typelib->name, uuid); 780 fprintf(header, "\n"); 781 } 782 783 784 const type_t* get_explicit_generic_handle_type(const var_t* var) 785 { 786 const type_t *t; 787 for (t = var->type; 788 is_ptr(t) || type_is_alias(t); 789 t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) 790 if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && 791 is_attr(t->attrs, ATTR_HANDLE)) 792 return t; 793 return NULL; 794 } 795 796 const var_t *get_func_handle_var( const type_t *iface, const var_t *func, 797 unsigned char *explicit_fc, unsigned char *implicit_fc ) 798 { 799 const var_t *var; 800 const var_list_t *args = type_get_function_args( func->type ); 801 802 *explicit_fc = *implicit_fc = 0; 803 if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 804 { 805 if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue; 806 if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 807 { 808 *explicit_fc = RPC_FC_BIND_PRIMITIVE; 809 return var; 810 } 811 if (get_explicit_generic_handle_type( var )) 812 { 813 *explicit_fc = RPC_FC_BIND_GENERIC; 814 return var; 815 } 816 if (is_context_handle( var->type )) 817 { 818 *explicit_fc = RPC_FC_BIND_CONTEXT; 819 return var; 820 } 821 } 822 823 if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE ))) 824 { 825 if (type_get_type( var->type ) == TYPE_BASIC && 826 type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 827 *implicit_fc = RPC_FC_BIND_PRIMITIVE; 828 else 829 *implicit_fc = RPC_FC_BIND_GENERIC; 830 return var; 831 } 832 833 *implicit_fc = RPC_FC_AUTO_HANDLE; 834 return NULL; 835 } 836 837 int has_out_arg_or_return(const var_t *func) 838 { 839 const var_t *var; 840 841 if (!is_void(type_function_get_rettype(func->type))) 842 return 1; 843 844 if (!type_get_function_args(func->type)) 845 return 0; 846 847 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 848 if (is_attr(var->attrs, ATTR_OUT)) 849 return 1; 850 851 return 0; 852 } 853 854 855 /********** INTERFACES **********/ 856 857 int is_object(const type_t *iface) 858 { 859 const attr_t *attr; 860 if (type_is_defined(iface) && type_iface_get_inherit(iface)) 861 return 1; 862 if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) 863 if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; 864 return 0; 865 } 866 867 int is_local(const attr_list_t *a) 868 { 869 return is_attr(a, ATTR_LOCAL); 870 } 871 872 const var_t *is_callas(const attr_list_t *a) 873 { 874 return get_attrp(a, ATTR_CALLAS); 875 } 876 877 static int is_inherited_method(const type_t *iface, const var_t *func) 878 { 879 while ((iface = type_iface_get_inherit(iface))) 880 { 881 const statement_t *stmt; 882 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 883 { 884 const var_t *funccmp = stmt->u.var; 885 886 if (!is_callas(func->attrs)) 887 { 888 char inherit_name[256]; 889 /* compare full name including property prefix */ 890 strcpy(inherit_name, get_name(funccmp)); 891 if (!strcmp(inherit_name, get_name(func))) return 1; 892 } 893 } 894 } 895 896 return 0; 897 } 898 899 static int is_override_method(const type_t *iface, const type_t *child, const var_t *func) 900 { 901 if (iface == child) 902 return 0; 903 904 do 905 { 906 const statement_t *stmt; 907 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(child)) 908 { 909 const var_t *funccmp = stmt->u.var; 910 911 if (!is_callas(func->attrs)) 912 { 913 char inherit_name[256]; 914 /* compare full name including property prefix */ 915 strcpy(inherit_name, get_name(funccmp)); 916 if (!strcmp(inherit_name, get_name(func))) return 1; 917 } 918 } 919 } 920 while ((child = type_iface_get_inherit(child)) && child != iface); 921 922 return 0; 923 } 924 925 static int is_aggregate_return(const var_t *func) 926 { 927 enum type_type type = type_get_type(type_function_get_rettype(func->type)); 928 return type == TYPE_STRUCT || type == TYPE_UNION || 929 type == TYPE_COCLASS || type == TYPE_INTERFACE; 930 } 931 932 static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) 933 { 934 static char buff[255]; 935 if (is_inherited_method(iface, func)) 936 sprintf(buff, "%s_%s", iface->name, get_name(func)); 937 else 938 sprintf(buff, "%s", get_name(func)); 939 return buff; 940 } 941 942 static void write_method_macro(FILE *header, const type_t *iface, const type_t *child, const char *name) 943 { 944 const statement_t *stmt; 945 int first_iface = 1; 946 947 if (type_iface_get_inherit(iface)) 948 write_method_macro(header, type_iface_get_inherit(iface), child, name); 949 950 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 951 { 952 const var_t *func = stmt->u.var; 953 954 if (first_iface) 955 { 956 fprintf(header, "/*** %s methods ***/\n", iface->name); 957 first_iface = 0; 958 } 959 960 if (is_override_method(iface, child, func)) 961 continue; 962 963 if (!is_callas(func->attrs) && !is_aggregate_return(func)) { 964 const var_t *arg; 965 966 fprintf(header, "#define %s_%s(This", name, get_name(func)); 967 if (type_get_function_args(func->type)) 968 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 969 fprintf(header, ",%s", arg->name); 970 fprintf(header, ") "); 971 972 fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func)); 973 if (type_get_function_args(func->type)) 974 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 975 fprintf(header, ",%s", arg->name); 976 fprintf(header, ")\n"); 977 } 978 } 979 } 980 981 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent) 982 { 983 const var_t *arg; 984 int count = 0; 985 986 if (do_indent) 987 { 988 indentation++; 989 indent(h, 0); 990 } 991 if (method == 1) { 992 fprintf(h, "%s* This", name); 993 count++; 994 } 995 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { 996 if (count) { 997 if (do_indent) 998 { 999 fprintf(h, ",\n"); 1000 indent(h, 0); 1001 } 1002 else fprintf(h, ","); 1003 } 1004 write_type_decl(h, arg->type, arg->name); 1005 if (method == 2) { 1006 const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); 1007 if (expr) { 1008 const var_t *tail_arg; 1009 1010 /* Output default value only if all following arguments also have default value. */ 1011 LIST_FOR_EACH_ENTRY_REV( tail_arg, args, const var_t, entry ) { 1012 if(tail_arg == arg) { 1013 expr_t bstr; 1014 1015 /* Fixup the expression type for a BSTR like midl does. */ 1016 if (get_type_vt(arg->type) == VT_BSTR && expr->type == EXPR_STRLIT) 1017 { 1018 bstr = *expr; 1019 bstr.type = EXPR_WSTRLIT; 1020 expr = &bstr; 1021 } 1022 1023 fprintf(h, " = "); 1024 write_expr( h, expr, 0, 1, NULL, NULL, "" ); 1025 break; 1026 } 1027 if(!get_attrp(tail_arg->attrs, ATTR_DEFAULTVALUE)) 1028 break; 1029 } 1030 } 1031 } 1032 count++; 1033 } 1034 if (do_indent) indentation--; 1035 } 1036 1037 static void write_cpp_method_def(FILE *header, const type_t *iface) 1038 { 1039 const statement_t *stmt; 1040 1041 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1042 { 1043 const var_t *func = stmt->u.var; 1044 if (!is_callas(func->attrs)) { 1045 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1046 const var_list_t *args = type_get_function_args(func->type); 1047 const var_t *arg; 1048 1049 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1050 1051 if (is_aggregate_return(func)) { 1052 fprintf(header, "#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS\n"); 1053 1054 indent(header, 0); 1055 fprintf(header, "virtual "); 1056 write_type_decl_left(header, type_function_get_rettype(func->type)); 1057 fprintf(header, "* %s %s(\n", callconv, get_name(func)); 1058 ++indentation; 1059 indent(header, 0); 1060 write_type_decl_left(header, type_function_get_rettype(func->type)); 1061 fprintf(header, " *__ret"); 1062 --indentation; 1063 if (args) { 1064 fprintf(header, ",\n"); 1065 write_args(header, args, iface->name, 2, TRUE); 1066 } 1067 fprintf(header, ") = 0;\n"); 1068 1069 indent(header, 0); 1070 write_type_decl_left(header, type_function_get_rettype(func->type)); 1071 fprintf(header, " %s %s(\n", callconv, get_name(func)); 1072 write_args(header, args, iface->name, 2, TRUE); 1073 fprintf(header, ")\n"); 1074 indent(header, 0); 1075 fprintf(header, "{\n"); 1076 ++indentation; 1077 indent(header, 0); 1078 write_type_decl_left(header, type_function_get_rettype(func->type)); 1079 fprintf(header, " __ret;\n"); 1080 indent(header, 0); 1081 fprintf(header, "return *%s(&__ret", get_name(func)); 1082 if (args) 1083 LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry) 1084 fprintf(header, ", %s", arg->name); 1085 fprintf(header, ");\n"); 1086 --indentation; 1087 indent(header, 0); 1088 fprintf(header, "}\n"); 1089 1090 fprintf(header, "#else\n"); 1091 } 1092 1093 indent(header, 0); 1094 fprintf(header, "virtual "); 1095 write_type_decl_left(header, type_function_get_rettype(func->type)); 1096 fprintf(header, " %s %s(\n", callconv, get_name(func)); 1097 write_args(header, args, iface->name, 2, TRUE); 1098 fprintf(header, ") = 0;\n"); 1099 1100 if (is_aggregate_return(func)) 1101 fprintf(header, "#endif\n"); 1102 fprintf(header, "\n"); 1103 } 1104 } 1105 } 1106 1107 static void write_inline_wrappers(FILE *header, const type_t *iface, const type_t *child, const char *name) 1108 { 1109 const statement_t *stmt; 1110 int first_iface = 1; 1111 1112 if (type_iface_get_inherit(iface)) 1113 write_inline_wrappers(header, type_iface_get_inherit(iface), child, name); 1114 1115 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1116 { 1117 const var_t *func = stmt->u.var; 1118 1119 if (first_iface) 1120 { 1121 fprintf(header, "/*** %s methods ***/\n", iface->name); 1122 first_iface = 0; 1123 } 1124 1125 if (is_override_method(iface, child, func)) 1126 continue; 1127 1128 if (!is_callas(func->attrs)) { 1129 const var_t *arg; 1130 1131 fprintf(header, "FORCEINLINE "); 1132 write_type_decl_left(header, type_function_get_rettype(func->type)); 1133 fprintf(header, " %s_%s(", name, get_name(func)); 1134 write_args(header, type_get_function_args(func->type), name, 1, FALSE); 1135 fprintf(header, ") {\n"); 1136 ++indentation; 1137 if (!is_aggregate_return(func)) { 1138 indent(header, 0); 1139 fprintf(header, "%sThis->lpVtbl->%s(This", 1140 is_void(type_function_get_rettype(func->type)) ? "" : "return ", 1141 get_vtbl_entry_name(iface, func)); 1142 } else { 1143 indent(header, 0); 1144 write_type_decl_left(header, type_function_get_rettype(func->type)); 1145 fprintf(header, " __ret;\n"); 1146 indent(header, 0); 1147 fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func)); 1148 } 1149 if (type_get_function_args(func->type)) 1150 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 1151 fprintf(header, ",%s", arg->name); 1152 fprintf(header, ");\n"); 1153 --indentation; 1154 fprintf(header, "}\n"); 1155 } 1156 } 1157 } 1158 1159 static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name) 1160 { 1161 const statement_t *stmt; 1162 int first_iface = 1; 1163 1164 if (type_iface_get_inherit(iface)) 1165 do_write_c_method_def(header, type_iface_get_inherit(iface), name); 1166 else if (type_iface_get_stmts(iface) == NULL) 1167 { 1168 fprintf(header, "#ifndef __cplusplus\n"); 1169 indent(header, 0); 1170 fprintf(header, "char dummy;\n"); 1171 fprintf(header, "#endif\n"); 1172 fprintf(header, "\n"); 1173 return; 1174 } 1175 1176 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1177 { 1178 const var_t *func = stmt->u.var; 1179 if (first_iface) { 1180 indent(header, 0); 1181 fprintf(header, "/*** %s methods ***/\n", iface->name); 1182 first_iface = 0; 1183 } 1184 if (!is_callas(func->attrs)) { 1185 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1186 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1187 indent(header, 0); 1188 write_type_decl_left(header, type_function_get_rettype(func->type)); 1189 if (is_aggregate_return(func)) 1190 fprintf(header, " *"); 1191 if (is_inherited_method(iface, func)) 1192 fprintf(header, " (%s *%s_%s)(\n", callconv, iface->name, func->name); 1193 else 1194 fprintf(header, " (%s *%s)(\n", callconv, get_name(func)); 1195 ++indentation; 1196 indent(header, 0); 1197 fprintf(header, "%s *This", name); 1198 if (is_aggregate_return(func)) { 1199 fprintf(header, ",\n"); 1200 indent(header, 0); 1201 write_type_decl_left(header, type_function_get_rettype(func->type)); 1202 fprintf(header, " *__ret"); 1203 } 1204 --indentation; 1205 if (type_get_function_args(func->type)) { 1206 fprintf(header, ",\n"); 1207 write_args(header, type_get_function_args(func->type), name, 0, TRUE); 1208 } 1209 fprintf(header, ");\n"); 1210 fprintf(header, "\n"); 1211 } 1212 } 1213 } 1214 1215 static void write_c_method_def(FILE *header, const type_t *iface) 1216 { 1217 do_write_c_method_def(header, iface, iface->c_name); 1218 } 1219 1220 static void write_c_disp_method_def(FILE *header, const type_t *iface) 1221 { 1222 do_write_c_method_def(header, type_iface_get_inherit(iface), iface->c_name); 1223 } 1224 1225 static void write_method_proto(FILE *header, const type_t *iface) 1226 { 1227 const statement_t *stmt; 1228 1229 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1230 { 1231 const var_t *func = stmt->u.var; 1232 1233 if (is_callas(func->attrs)) { 1234 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1235 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1236 /* proxy prototype */ 1237 write_type_decl_left(header, type_function_get_rettype(func->type)); 1238 fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); 1239 write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE); 1240 fprintf(header, ");\n"); 1241 /* stub prototype */ 1242 fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); 1243 fprintf(header, " IRpcStubBuffer* This,\n"); 1244 fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); 1245 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n"); 1246 fprintf(header, " DWORD* pdwStubPhase);\n"); 1247 } 1248 } 1249 } 1250 1251 static void write_locals(FILE *fp, const type_t *iface, int body) 1252 { 1253 static const char comment[] 1254 = "/* WIDL-generated stub. You must provide an implementation for this. */"; 1255 const statement_t *stmt; 1256 1257 if (!is_object(iface)) 1258 return; 1259 1260 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { 1261 const var_t *func = stmt->u.var; 1262 const var_t *cas = is_callas(func->attrs); 1263 1264 if (cas) { 1265 const statement_t *stmt2 = NULL; 1266 STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) 1267 if (!strcmp(stmt2->u.var->name, cas->name)) 1268 break; 1269 if (&stmt2->entry != type_iface_get_stmts(iface)) { 1270 const var_t *m = stmt2->u.var; 1271 /* proxy prototype - use local prototype */ 1272 write_type_decl_left(fp, type_function_get_rettype(m->type)); 1273 fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); 1274 write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE); 1275 fprintf(fp, ")"); 1276 if (body) { 1277 type_t *rt = type_function_get_rettype(m->type); 1278 fprintf(fp, "\n{\n"); 1279 fprintf(fp, " %s\n", comment); 1280 if (rt->name && strcmp(rt->name, "HRESULT") == 0) 1281 fprintf(fp, " return E_NOTIMPL;\n"); 1282 else if (type_get_type(rt) != TYPE_VOID) { 1283 fprintf(fp, " "); 1284 write_type_decl(fp, rt, "rv"); 1285 fprintf(fp, ";\n"); 1286 fprintf(fp, " memset(&rv, 0, sizeof rv);\n"); 1287 fprintf(fp, " return rv;\n"); 1288 } 1289 fprintf(fp, "}\n\n"); 1290 } 1291 else 1292 fprintf(fp, ";\n"); 1293 /* stub prototype - use remotable prototype */ 1294 write_type_decl_left(fp, type_function_get_rettype(func->type)); 1295 fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); 1296 write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE); 1297 fprintf(fp, ")"); 1298 if (body) 1299 /* Remotable methods must all return HRESULTs. */ 1300 fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment); 1301 else 1302 fprintf(fp, ";\n"); 1303 } 1304 else 1305 error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name); 1306 } 1307 } 1308 } 1309 1310 static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts) 1311 { 1312 const statement_t *stmt; 1313 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1314 { 1315 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 1316 write_locals(local_stubs, stmt->u.type, TRUE); 1317 } 1318 } 1319 1320 void write_local_stubs(const statement_list_t *stmts) 1321 { 1322 FILE *local_stubs; 1323 1324 if (!local_stubs_name) return; 1325 1326 local_stubs = fopen(local_stubs_name, "w"); 1327 if (!local_stubs) { 1328 error("Could not open %s for output\n", local_stubs_name); 1329 return; 1330 } 1331 fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name); 1332 fprintf(local_stubs, "#include <objbase.h>\n"); 1333 fprintf(local_stubs, "#include \"%s\"\n\n", header_name); 1334 1335 write_local_stubs_stmts(local_stubs, stmts); 1336 1337 fclose(local_stubs); 1338 } 1339 1340 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix) 1341 { 1342 const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV); 1343 1344 if (!callconv) callconv = "__cdecl"; 1345 /* FIXME: do we need to handle call_as? */ 1346 write_type_decl_left(header, type_function_get_rettype(fun->type)); 1347 fprintf(header, " %s ", callconv); 1348 fprintf(header, "%s%s(\n", prefix, get_name(fun)); 1349 if (type_get_function_args(fun->type)) 1350 write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE); 1351 else 1352 fprintf(header, " void"); 1353 fprintf(header, ");\n\n"); 1354 } 1355 1356 static void write_forward(FILE *header, type_t *iface) 1357 { 1358 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name); 1359 fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->c_name); 1360 fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); 1361 fprintf(header, "#ifdef __cplusplus\n"); 1362 write_namespace_start(header, iface->namespace); 1363 write_line(header, 0, "interface %s;", iface->name); 1364 write_namespace_end(header, iface->namespace); 1365 fprintf(header, "#endif /* __cplusplus */\n"); 1366 fprintf(header, "#endif\n\n" ); 1367 } 1368 1369 static void write_com_interface_start(FILE *header, const type_t *iface) 1370 { 1371 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 1372 fprintf(header, "/*****************************************************************************\n"); 1373 fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); 1374 fprintf(header, " */\n"); 1375 fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : ""); 1376 fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); 1377 } 1378 1379 static void write_com_interface_end(FILE *header, type_t *iface) 1380 { 1381 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 1382 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); 1383 type_t *type; 1384 1385 if (uuid) 1386 write_guid(header, dispinterface ? "DIID" : "IID", iface->c_name, uuid); 1387 1388 /* C++ interface */ 1389 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); 1390 if (!is_global_namespace(iface->namespace)) { 1391 write_line(header, 0, "} /* extern \"C\" */"); 1392 write_namespace_start(header, iface->namespace); 1393 } 1394 if (uuid) { 1395 write_line(header, 0, "MIDL_INTERFACE(\"%s\")", uuid_string(uuid)); 1396 indent(header, 0); 1397 }else { 1398 indent(header, 0); 1399 fprintf(header, "interface "); 1400 } 1401 if (type_iface_get_inherit(iface)) 1402 { 1403 fprintf(header, "%s : public %s\n", iface->name, 1404 type_iface_get_inherit(iface)->name); 1405 write_line(header, 1, "{"); 1406 } 1407 else 1408 { 1409 fprintf(header, "%s\n", iface->name); 1410 write_line(header, 1, "{\n"); 1411 write_line(header, 0, "BEGIN_INTERFACE\n"); 1412 } 1413 /* dispinterfaces don't have real functions, so don't write C++ functions for 1414 * them */ 1415 if (!dispinterface) 1416 write_cpp_method_def(header, iface); 1417 if (!type_iface_get_inherit(iface)) 1418 write_line(header, 0, "END_INTERFACE\n"); 1419 write_line(header, -1, "};"); 1420 if (!is_global_namespace(iface->namespace)) { 1421 write_namespace_end(header, iface->namespace); 1422 write_line(header, 0, "extern \"C\" {"); 1423 } 1424 if (uuid) 1425 write_uuid_decl(header, iface, uuid); 1426 fprintf(header, "#else\n"); 1427 /* C interface */ 1428 write_line(header, 1, "typedef struct %sVtbl {", iface->c_name); 1429 write_line(header, 0, "BEGIN_INTERFACE\n"); 1430 if (dispinterface) 1431 write_c_disp_method_def(header, iface); 1432 else 1433 write_c_method_def(header, iface); 1434 write_line(header, 0, "END_INTERFACE"); 1435 write_line(header, -1, "} %sVtbl;\n", iface->c_name); 1436 fprintf(header, "interface %s {\n", iface->c_name); 1437 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->c_name); 1438 fprintf(header, "};\n\n"); 1439 fprintf(header, "#ifdef COBJMACROS\n"); 1440 /* dispinterfaces don't have real functions, so don't write macros for them, 1441 * only for the interface this interface inherits from, i.e. IDispatch */ 1442 fprintf(header, "#ifndef WIDL_C_INLINE_WRAPPERS\n"); 1443 type = dispinterface ? type_iface_get_inherit(iface) : iface; 1444 write_method_macro(header, type, type, iface->c_name); 1445 fprintf(header, "#else\n"); 1446 write_inline_wrappers(header, type, type, iface->c_name); 1447 fprintf(header, "#endif\n"); 1448 fprintf(header, "#endif\n"); 1449 fprintf(header, "\n"); 1450 fprintf(header, "#endif\n"); 1451 fprintf(header, "\n"); 1452 /* dispinterfaces don't have real functions, so don't write prototypes for 1453 * them */ 1454 if (!dispinterface && !winrt_mode) 1455 { 1456 write_method_proto(header, iface); 1457 write_locals(header, iface, FALSE); 1458 fprintf(header, "\n"); 1459 } 1460 fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->c_name, dispinterface ? "DISP" : ""); 1461 } 1462 1463 static void write_rpc_interface_start(FILE *header, const type_t *iface) 1464 { 1465 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 1466 const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 1467 1468 fprintf(header, "/*****************************************************************************\n"); 1469 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1470 fprintf(header, " */\n"); 1471 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); 1472 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); 1473 if (var) 1474 { 1475 fprintf(header, "extern "); 1476 write_type_decl( header, var->type, var->name ); 1477 fprintf(header, ";\n"); 1478 } 1479 if (old_names) 1480 { 1481 fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name); 1482 fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name); 1483 } 1484 else 1485 { 1486 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n", 1487 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1488 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n", 1489 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1490 } 1491 } 1492 1493 static void write_rpc_interface_end(FILE *header, const type_t *iface) 1494 { 1495 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); 1496 } 1497 1498 static void write_coclass(FILE *header, type_t *cocl) 1499 { 1500 const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID); 1501 1502 fprintf(header, "/*****************************************************************************\n"); 1503 fprintf(header, " * %s coclass\n", cocl->name); 1504 fprintf(header, " */\n\n"); 1505 if (uuid) 1506 write_guid(header, "CLSID", cocl->name, uuid); 1507 fprintf(header, "\n#ifdef __cplusplus\n"); 1508 if (uuid) 1509 { 1510 fprintf(header, "class DECLSPEC_UUID(\"%s\") %s;\n", uuid_string(uuid), cocl->name); 1511 write_uuid_decl(header, cocl, uuid); 1512 } 1513 else 1514 { 1515 fprintf(header, "class %s;\n", cocl->name); 1516 } 1517 fprintf(header, "#endif\n"); 1518 fprintf(header, "\n"); 1519 } 1520 1521 static void write_coclass_forward(FILE *header, type_t *cocl) 1522 { 1523 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name); 1524 fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name); 1525 fprintf(header, "#ifdef __cplusplus\n"); 1526 fprintf(header, "typedef class %s %s;\n", cocl->name, cocl->name); 1527 fprintf(header, "#else\n"); 1528 fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name); 1529 fprintf(header, "#endif /* defined __cplusplus */\n"); 1530 fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); 1531 } 1532 1533 static void write_import(FILE *header, const char *fname) 1534 { 1535 char *hname, *p; 1536 1537 hname = dup_basename(fname, ".idl"); 1538 p = hname + strlen(hname) - 2; 1539 if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h"); 1540 1541 fprintf(header, "#include <%s>\n", hname); 1542 free(hname); 1543 } 1544 1545 static void write_imports(FILE *header, const statement_list_t *stmts) 1546 { 1547 const statement_t *stmt; 1548 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1549 { 1550 switch (stmt->type) 1551 { 1552 case STMT_TYPE: 1553 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1554 write_imports(header, type_iface_get_stmts(stmt->u.type)); 1555 break; 1556 case STMT_TYPEREF: 1557 case STMT_IMPORTLIB: 1558 /* not included in header */ 1559 break; 1560 case STMT_IMPORT: 1561 write_import(header, stmt->u.str); 1562 break; 1563 case STMT_TYPEDEF: 1564 case STMT_MODULE: 1565 case STMT_CPPQUOTE: 1566 case STMT_PRAGMA: 1567 case STMT_DECLARATION: 1568 /* not processed here */ 1569 break; 1570 case STMT_LIBRARY: 1571 write_imports(header, stmt->u.lib->stmts); 1572 break; 1573 } 1574 } 1575 } 1576 1577 static void write_forward_decls(FILE *header, const statement_list_t *stmts) 1578 { 1579 const statement_t *stmt; 1580 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1581 { 1582 switch (stmt->type) 1583 { 1584 case STMT_TYPE: 1585 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1586 { 1587 if (is_object(stmt->u.type) || is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE)) 1588 write_forward(header, stmt->u.type); 1589 } 1590 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 1591 write_coclass_forward(header, stmt->u.type); 1592 break; 1593 case STMT_TYPEREF: 1594 case STMT_IMPORTLIB: 1595 /* not included in header */ 1596 break; 1597 case STMT_IMPORT: 1598 case STMT_TYPEDEF: 1599 case STMT_MODULE: 1600 case STMT_CPPQUOTE: 1601 case STMT_PRAGMA: 1602 case STMT_DECLARATION: 1603 /* not processed here */ 1604 break; 1605 case STMT_LIBRARY: 1606 write_forward_decls(header, stmt->u.lib->stmts); 1607 break; 1608 } 1609 } 1610 } 1611 1612 static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs) 1613 { 1614 const statement_t *stmt; 1615 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1616 { 1617 switch (stmt->type) 1618 { 1619 case STMT_TYPE: 1620 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1621 { 1622 type_t *iface = stmt->u.type; 1623 if (is_object(iface)) is_object_interface++; 1624 if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) 1625 { 1626 write_com_interface_start(header, iface); 1627 write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE); 1628 write_com_interface_end(header, iface); 1629 } 1630 else 1631 { 1632 write_rpc_interface_start(header, iface); 1633 write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE); 1634 write_rpc_interface_end(header, iface); 1635 } 1636 if (is_object(iface)) is_object_interface--; 1637 } 1638 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 1639 write_coclass(header, stmt->u.type); 1640 else 1641 { 1642 write_type_definition(header, stmt->u.type); 1643 } 1644 break; 1645 case STMT_TYPEREF: 1646 /* FIXME: shouldn't write out forward declarations for undefined 1647 * interfaces but a number of our IDL files depend on this */ 1648 if (type_get_type(stmt->u.type) == TYPE_INTERFACE && !stmt->u.type->written) 1649 write_forward(header, stmt->u.type); 1650 break; 1651 case STMT_IMPORTLIB: 1652 case STMT_MODULE: 1653 case STMT_PRAGMA: 1654 /* not included in header */ 1655 break; 1656 case STMT_IMPORT: 1657 /* not processed here */ 1658 break; 1659 case STMT_TYPEDEF: 1660 { 1661 const type_list_t *type_entry = stmt->u.type_list; 1662 for (; type_entry; type_entry = type_entry->next) 1663 write_typedef(header, type_entry->type); 1664 break; 1665 } 1666 case STMT_LIBRARY: 1667 write_library(header, stmt->u.lib); 1668 write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE); 1669 break; 1670 case STMT_CPPQUOTE: 1671 fprintf(header, "%s\n", stmt->u.str); 1672 break; 1673 case STMT_DECLARATION: 1674 if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION) 1675 { 1676 if (!ignore_funcs) 1677 { 1678 int prefixes_differ = strcmp(prefix_client, prefix_server); 1679 1680 if (prefixes_differ) 1681 { 1682 fprintf(header, "/* client prototype */\n"); 1683 write_function_proto(header, iface, stmt->u.var, prefix_client); 1684 fprintf(header, "/* server prototype */\n"); 1685 } 1686 write_function_proto(header, iface, stmt->u.var, prefix_server); 1687 } 1688 } 1689 else 1690 write_declaration(header, stmt->u.var); 1691 break; 1692 } 1693 } 1694 } 1695 1696 void write_header(const statement_list_t *stmts) 1697 { 1698 FILE *header; 1699 1700 if (!do_header) return; 1701 1702 if(!(header = fopen(header_name, "w"))) { 1703 error("Could not open %s for output\n", header_name); 1704 return; 1705 } 1706 fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name); 1707 1708 fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n"); 1709 fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n"); 1710 fprintf(header, "#endif\n\n"); 1711 1712 fprintf(header, "#ifdef __REACTOS__\n"); 1713 fprintf(header, "#define WIN32_LEAN_AND_MEAN\n"); 1714 fprintf(header, "#endif\n\n"); 1715 1716 fprintf(header, "#include <rpc.h>\n" ); 1717 fprintf(header, "#include <rpcndr.h>\n\n" ); 1718 1719 fprintf(header, "#ifndef COM_NO_WINDOWS_H\n"); 1720 fprintf(header, "#include <windows.h>\n"); 1721 fprintf(header, "#include <ole2.h>\n"); 1722 fprintf(header, "#endif\n\n"); 1723 1724 fprintf(header, "#ifndef __%s__\n", header_token); 1725 fprintf(header, "#define __%s__\n\n", header_token); 1726 1727 fprintf(header, "/* Forward declarations */\n\n"); 1728 write_forward_decls(header, stmts); 1729 1730 fprintf(header, "/* Headers for imported files */\n\n"); 1731 write_imports(header, stmts); 1732 fprintf(header, "\n"); 1733 start_cplusplus_guard(header); 1734 1735 write_header_stmts(header, stmts, NULL, FALSE); 1736 1737 fprintf(header, "/* Begin additional prototypes for all interfaces */\n"); 1738 fprintf(header, "\n"); 1739 write_user_types(header); 1740 write_generic_handle_routines(header); 1741 write_context_handle_rundowns(header); 1742 fprintf(header, "\n"); 1743 fprintf(header, "/* End additional prototypes */\n"); 1744 fprintf(header, "\n"); 1745 1746 end_cplusplus_guard(header); 1747 fprintf(header, "#endif /* __%s__ */\n", header_token); 1748 1749 fclose(header); 1750 } 1751