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 static void write_pointer_left(FILE *h, type_t *ref) 289 { 290 if (needs_space_after(ref)) 291 fprintf(h, " "); 292 if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) 293 fprintf(h, "("); 294 fprintf(h, "*"); 295 } 296 297 void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) 298 { 299 const char *name; 300 301 if (!h) return; 302 303 name = type_get_name(t, name_type); 304 305 if (is_attr(t->attrs, ATTR_CONST) && 306 (type_is_alias(t) || !is_ptr(t))) 307 fprintf(h, "const "); 308 309 if (type_is_alias(t)) fprintf(h, "%s", t->name); 310 else { 311 switch (type_get_type_detect_alias(t)) { 312 case TYPE_ENUM: 313 if (!declonly && t->defined && !t->written) { 314 if (name) fprintf(h, "enum %s {\n", name); 315 else fprintf(h, "enum {\n"); 316 t->written = TRUE; 317 indentation++; 318 write_enums(h, type_enum_get_values(t), is_global_namespace(t->namespace) ? NULL : t->name); 319 indent(h, -1); 320 fprintf(h, "}"); 321 } 322 else fprintf(h, "enum %s", name ? name : ""); 323 break; 324 case TYPE_STRUCT: 325 case TYPE_ENCAPSULATED_UNION: 326 if (!declonly && t->defined && !t->written) { 327 if (name) fprintf(h, "struct %s {\n", name); 328 else fprintf(h, "struct {\n"); 329 t->written = TRUE; 330 indentation++; 331 if (type_get_type(t) != TYPE_STRUCT) 332 write_fields(h, type_encapsulated_union_get_fields(t)); 333 else 334 write_fields(h, type_struct_get_fields(t)); 335 indent(h, -1); 336 fprintf(h, "}"); 337 } 338 else fprintf(h, "struct %s", name ? name : ""); 339 break; 340 case TYPE_UNION: 341 if (!declonly && t->defined && !t->written) { 342 if (t->name) fprintf(h, "union %s {\n", t->name); 343 else fprintf(h, "union {\n"); 344 t->written = TRUE; 345 indentation++; 346 write_fields(h, type_union_get_cases(t)); 347 indent(h, -1); 348 fprintf(h, "}"); 349 } 350 else fprintf(h, "union %s", t->name ? t->name : ""); 351 break; 352 case TYPE_POINTER: 353 { 354 write_type_left(h, type_pointer_get_ref(t), name_type, declonly); 355 write_pointer_left(h, type_pointer_get_ref(t)); 356 if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); 357 break; 358 } 359 case TYPE_ARRAY: 360 if (t->name && type_array_is_decl_as_ptr(t)) 361 fprintf(h, "%s", t->name); 362 else 363 { 364 write_type_left(h, type_array_get_element(t), name_type, declonly); 365 if (type_array_is_decl_as_ptr(t)) 366 write_pointer_left(h, type_array_get_element(t)); 367 } 368 break; 369 case TYPE_BASIC: 370 if (type_basic_get_type(t) != TYPE_BASIC_INT32 && 371 type_basic_get_type(t) != TYPE_BASIC_INT64 && 372 type_basic_get_type(t) != TYPE_BASIC_LONG && 373 type_basic_get_type(t) != TYPE_BASIC_HYPER) 374 { 375 if (type_basic_get_sign(t) < 0) fprintf(h, "signed "); 376 else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned "); 377 } 378 switch (type_basic_get_type(t)) 379 { 380 case TYPE_BASIC_INT8: fprintf(h, "small"); break; 381 case TYPE_BASIC_INT16: fprintf(h, "short"); break; 382 case TYPE_BASIC_INT: fprintf(h, "int"); break; 383 case TYPE_BASIC_INT3264: fprintf(h, "__int3264"); break; 384 case TYPE_BASIC_BYTE: fprintf(h, "byte"); break; 385 case TYPE_BASIC_CHAR: fprintf(h, "char"); break; 386 case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break; 387 case TYPE_BASIC_FLOAT: fprintf(h, "float"); break; 388 case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break; 389 case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break; 390 case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break; 391 case TYPE_BASIC_INT32: 392 if (type_basic_get_sign(t) > 0) 393 fprintf(h, "UINT32"); 394 else 395 fprintf(h, "INT32"); 396 break; 397 case TYPE_BASIC_LONG: 398 if (type_basic_get_sign(t) > 0) 399 fprintf(h, "ULONG"); 400 else 401 fprintf(h, "LONG"); 402 break; 403 case TYPE_BASIC_INT64: 404 if (type_basic_get_sign(t) > 0) 405 fprintf(h, "UINT64"); 406 else 407 fprintf(h, "INT64"); 408 break; 409 case TYPE_BASIC_HYPER: 410 if (type_basic_get_sign(t) > 0) 411 fprintf(h, "MIDL_uhyper"); 412 else 413 fprintf(h, "hyper"); 414 break; 415 } 416 break; 417 case TYPE_INTERFACE: 418 case TYPE_MODULE: 419 case TYPE_COCLASS: 420 fprintf(h, "%s", t->name); 421 break; 422 case TYPE_VOID: 423 fprintf(h, "void"); 424 break; 425 case TYPE_BITFIELD: 426 write_type_left(h, type_bitfield_get_field(t), name_type, declonly); 427 break; 428 case TYPE_ALIAS: 429 case TYPE_FUNCTION: 430 /* handled elsewhere */ 431 assert(0); 432 break; 433 } 434 } 435 } 436 437 void write_type_right(FILE *h, type_t *t, int is_field) 438 { 439 if (!h) return; 440 if (type_is_alias(t)) return; 441 442 switch (type_get_type(t)) 443 { 444 case TYPE_ARRAY: 445 { 446 type_t *elem = type_array_get_element(t); 447 if (type_array_is_decl_as_ptr(t)) 448 { 449 if (!type_is_alias(elem) && is_array(elem) && !type_array_is_decl_as_ptr(elem)) 450 fprintf(h, ")"); 451 } 452 else 453 { 454 if (is_conformant_array(t)) 455 fprintf(h, "[%s]", is_field ? "1" : ""); 456 else 457 fprintf(h, "[%u]", type_array_get_dim(t)); 458 } 459 write_type_right(h, elem, FALSE); 460 break; 461 } 462 case TYPE_POINTER: 463 { 464 type_t *ref = type_pointer_get_ref(t); 465 if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) 466 fprintf(h, ")"); 467 write_type_right(h, ref, FALSE); 468 break; 469 } 470 case TYPE_BITFIELD: 471 fprintf(h, " : %u", type_bitfield_get_bits(t)->cval); 472 break; 473 case TYPE_VOID: 474 case TYPE_BASIC: 475 case TYPE_ENUM: 476 case TYPE_STRUCT: 477 case TYPE_ENCAPSULATED_UNION: 478 case TYPE_UNION: 479 case TYPE_ALIAS: 480 case TYPE_MODULE: 481 case TYPE_COCLASS: 482 case TYPE_FUNCTION: 483 case TYPE_INTERFACE: 484 break; 485 } 486 } 487 488 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name) 489 { 490 type_t *pt = NULL; 491 int ptr_level = 0; 492 493 if (!h) return; 494 495 if (t) { 496 for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) 497 ; 498 499 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 500 int i; 501 const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); 502 if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; 503 if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); 504 write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly); 505 fputc(' ', h); 506 if (ptr_level) fputc('(', h); 507 if (callconv) fprintf(h, "%s ", callconv); 508 for (i = 0; i < ptr_level; i++) 509 fputc('*', h); 510 } else 511 write_type_left(h, t, NAME_DEFAULT, declonly); 512 } 513 514 if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); 515 516 if (t) { 517 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 518 const var_list_t *args = type_function_get_args(pt); 519 520 if (ptr_level) fputc(')', h); 521 fputc('(', h); 522 if (args) 523 write_args(h, args, NULL, 0, FALSE); 524 else 525 fprintf(h, "void"); 526 fputc(')', h); 527 } else 528 write_type_right(h, t, is_field); 529 } 530 } 531 532 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name) 533 { 534 write_type_v(f, t, field, FALSE, name); 535 } 536 537 static void write_type_definition(FILE *f, type_t *t) 538 { 539 int in_namespace = t->namespace && !is_global_namespace(t->namespace); 540 int save_written = t->written; 541 542 if(in_namespace) { 543 fprintf(f, "#ifdef __cplusplus\n"); 544 fprintf(f, "} /* extern \"C\" */\n"); 545 write_namespace_start(f, t->namespace); 546 } 547 indent(f, 0); 548 write_type_left(f, t, NAME_DEFAULT, FALSE); 549 fprintf(f, ";\n"); 550 if(in_namespace) { 551 t->written = save_written; 552 write_namespace_end(f, t->namespace); 553 fprintf(f, "extern \"C\" {\n"); 554 fprintf(f, "#else\n"); 555 write_type_left(f, t, NAME_C, FALSE); 556 fprintf(f, ";\n"); 557 fprintf(f, "#endif\n\n"); 558 } 559 } 560 561 void write_type_decl(FILE *f, type_t *t, const char *name) 562 { 563 write_type_v(f, t, FALSE, TRUE, name); 564 } 565 566 void write_type_decl_left(FILE *f, type_t *t) 567 { 568 write_type_left(f, t, NAME_DEFAULT, TRUE); 569 } 570 571 static int user_type_registered(const char *name) 572 { 573 user_type_t *ut; 574 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 575 if (!strcmp(name, ut->name)) 576 return 1; 577 return 0; 578 } 579 580 static int context_handle_registered(const char *name) 581 { 582 context_handle_t *ch; 583 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 584 if (!strcmp(name, ch->name)) 585 return 1; 586 return 0; 587 } 588 589 static int generic_handle_registered(const char *name) 590 { 591 generic_handle_t *gh; 592 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 593 if (!strcmp(name, gh->name)) 594 return 1; 595 return 0; 596 } 597 598 unsigned int get_context_handle_offset( const type_t *type ) 599 { 600 context_handle_t *ch; 601 unsigned int index = 0; 602 603 while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) 604 { 605 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 606 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 607 else error( "internal error: %s is not a context handle\n", type->name ); 608 } 609 LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) 610 { 611 if (!strcmp( type->name, ch->name )) return index; 612 index++; 613 } 614 error( "internal error: %s is not registered as a context handle\n", type->name ); 615 return index; 616 } 617 618 unsigned int get_generic_handle_offset( const type_t *type ) 619 { 620 generic_handle_t *gh; 621 unsigned int index = 0; 622 623 while (!is_attr( type->attrs, ATTR_HANDLE )) 624 { 625 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 626 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 627 else error( "internal error: %s is not a generic handle\n", type->name ); 628 } 629 LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) 630 { 631 if (!strcmp( type->name, gh->name )) return index; 632 index++; 633 } 634 error( "internal error: %s is not registered as a generic handle\n", type->name ); 635 return index; 636 } 637 638 /* check for types which require additional prototypes to be generated in the 639 * header */ 640 void check_for_additional_prototype_types(const var_list_t *list) 641 { 642 const var_t *v; 643 644 if (!list) return; 645 LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) 646 { 647 type_t *type = v->type; 648 if (!type) continue; 649 for (;;) { 650 const char *name = type->name; 651 if (type->user_types_registered) break; 652 type->user_types_registered = 1; 653 if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { 654 if (!context_handle_registered(name)) 655 { 656 context_handle_t *ch = xmalloc(sizeof(*ch)); 657 ch->name = xstrdup(name); 658 list_add_tail(&context_handle_list, &ch->entry); 659 } 660 /* don't carry on parsing fields within this type */ 661 break; 662 } 663 if ((type_get_type(type) != TYPE_BASIC || 664 type_basic_get_type(type) != TYPE_BASIC_HANDLE) && 665 is_attr(type->attrs, ATTR_HANDLE)) { 666 if (!generic_handle_registered(name)) 667 { 668 generic_handle_t *gh = xmalloc(sizeof(*gh)); 669 gh->name = xstrdup(name); 670 list_add_tail(&generic_handle_list, &gh->entry); 671 } 672 /* don't carry on parsing fields within this type */ 673 break; 674 } 675 if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { 676 if (!user_type_registered(name)) 677 { 678 user_type_t *ut = xmalloc(sizeof *ut); 679 ut->name = xstrdup(name); 680 list_add_tail(&user_type_list, &ut->entry); 681 } 682 /* don't carry on parsing fields within this type as we are already 683 * using a wire marshaled type */ 684 break; 685 } 686 else if (type_is_complete(type)) 687 { 688 var_list_t *vars; 689 switch (type_get_type_detect_alias(type)) 690 { 691 case TYPE_ENUM: 692 vars = type_enum_get_values(type); 693 break; 694 case TYPE_STRUCT: 695 vars = type_struct_get_fields(type); 696 break; 697 case TYPE_UNION: 698 vars = type_union_get_cases(type); 699 break; 700 default: 701 vars = NULL; 702 break; 703 } 704 check_for_additional_prototype_types(vars); 705 } 706 707 if (type_is_alias(type)) 708 type = type_alias_get_aliasee(type); 709 else if (is_ptr(type)) 710 type = type_pointer_get_ref(type); 711 else if (is_array(type)) 712 type = type_array_get_element(type); 713 else 714 break; 715 } 716 } 717 } 718 719 static int write_serialize_function_decl(FILE *header, const type_t *type) 720 { 721 write_serialize_functions(header, type, NULL); 722 return 1; 723 } 724 725 static int serializable_exists(FILE *header, const type_t *type) 726 { 727 return 0; 728 } 729 730 static int for_each_serializable(const statement_list_t *stmts, FILE *header, 731 int (*proc)(FILE*, const type_t*)) 732 { 733 statement_t *stmt, *iface_stmt; 734 statement_list_t *iface_stmts; 735 const type_list_t *type_entry; 736 737 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) 738 { 739 if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE) 740 continue; 741 742 iface_stmts = type_iface_get_stmts(stmt->u.type); 743 if (iface_stmts) LIST_FOR_EACH_ENTRY( iface_stmt, iface_stmts, statement_t, entry ) 744 { 745 if (iface_stmt->type != STMT_TYPEDEF) continue; 746 for (type_entry = iface_stmt->u.type_list; type_entry; type_entry = type_entry->next) 747 { 748 if (!is_attr(type_entry->type->attrs, ATTR_ENCODE) 749 && !is_attr(type_entry->type->attrs, ATTR_DECODE)) 750 continue; 751 if (!proc(header, type_entry->type)) 752 return 0; 753 } 754 } 755 } 756 757 return 1; 758 } 759 760 static void write_user_types(FILE *header) 761 { 762 user_type_t *ut; 763 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 764 { 765 const char *name = ut->name; 766 fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name); 767 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name); 768 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name); 769 fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name); 770 } 771 } 772 773 static void write_context_handle_rundowns(FILE *header) 774 { 775 context_handle_t *ch; 776 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 777 { 778 const char *name = ch->name; 779 fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name); 780 } 781 } 782 783 static void write_generic_handle_routines(FILE *header) 784 { 785 generic_handle_t *gh; 786 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 787 { 788 const char *name = gh->name; 789 fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name); 790 fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name); 791 } 792 } 793 794 static void write_typedef(FILE *header, type_t *type) 795 { 796 fprintf(header, "typedef "); 797 write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); 798 fprintf(header, ";\n"); 799 } 800 801 int is_const_decl(const var_t *var) 802 { 803 const type_t *t; 804 /* strangely, MIDL accepts a const attribute on any pointer in the 805 * declaration to mean that data isn't being instantiated. this appears 806 * to be a bug, but there is no benefit to being incompatible with MIDL, 807 * so we'll do the same thing */ 808 for (t = var->type; ; ) 809 { 810 if (is_attr(t->attrs, ATTR_CONST)) 811 return TRUE; 812 else if (is_ptr(t)) 813 t = type_pointer_get_ref(t); 814 else break; 815 } 816 return FALSE; 817 } 818 819 static void write_declaration(FILE *header, const var_t *v) 820 { 821 if (is_const_decl(v) && v->eval) 822 { 823 fprintf(header, "#define %s (", v->name); 824 write_expr(header, v->eval, 0, 1, NULL, NULL, ""); 825 fprintf(header, ")\n\n"); 826 } 827 else 828 { 829 switch (v->stgclass) 830 { 831 case STG_NONE: 832 case STG_REGISTER: /* ignored */ 833 break; 834 case STG_STATIC: 835 fprintf(header, "static "); 836 break; 837 case STG_EXTERN: 838 fprintf(header, "extern "); 839 break; 840 } 841 write_type_def_or_decl(header, v->type, FALSE, v->name); 842 fprintf(header, ";\n\n"); 843 } 844 } 845 846 static void write_library(FILE *header, const typelib_t *typelib) 847 { 848 const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID); 849 fprintf(header, "\n"); 850 write_guid(header, "LIBID", typelib->name, uuid); 851 fprintf(header, "\n"); 852 } 853 854 855 const type_t* get_explicit_generic_handle_type(const var_t* var) 856 { 857 const type_t *t; 858 for (t = var->type; 859 is_ptr(t) || type_is_alias(t); 860 t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) 861 if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && 862 is_attr(t->attrs, ATTR_HANDLE)) 863 return t; 864 return NULL; 865 } 866 867 const var_t *get_func_handle_var( const type_t *iface, const var_t *func, 868 unsigned char *explicit_fc, unsigned char *implicit_fc ) 869 { 870 const var_t *var; 871 const var_list_t *args = type_get_function_args( func->type ); 872 873 *explicit_fc = *implicit_fc = 0; 874 if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 875 { 876 if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue; 877 if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 878 { 879 *explicit_fc = FC_BIND_PRIMITIVE; 880 return var; 881 } 882 if (get_explicit_generic_handle_type( var )) 883 { 884 *explicit_fc = FC_BIND_GENERIC; 885 return var; 886 } 887 if (is_context_handle( var->type )) 888 { 889 *explicit_fc = FC_BIND_CONTEXT; 890 return var; 891 } 892 } 893 894 if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE ))) 895 { 896 if (type_get_type( var->type ) == TYPE_BASIC && 897 type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 898 *implicit_fc = FC_BIND_PRIMITIVE; 899 else 900 *implicit_fc = FC_BIND_GENERIC; 901 return var; 902 } 903 904 *implicit_fc = FC_AUTO_HANDLE; 905 return NULL; 906 } 907 908 int has_out_arg_or_return(const var_t *func) 909 { 910 const var_t *var; 911 912 if (!is_void(type_function_get_rettype(func->type))) 913 return 1; 914 915 if (!type_get_function_args(func->type)) 916 return 0; 917 918 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 919 if (is_attr(var->attrs, ATTR_OUT)) 920 return 1; 921 922 return 0; 923 } 924 925 926 /********** INTERFACES **********/ 927 928 int is_object(const type_t *iface) 929 { 930 const attr_t *attr; 931 if (type_is_defined(iface) && type_iface_get_inherit(iface)) 932 return 1; 933 if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) 934 if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; 935 return 0; 936 } 937 938 int is_local(const attr_list_t *a) 939 { 940 return is_attr(a, ATTR_LOCAL); 941 } 942 943 const var_t *is_callas(const attr_list_t *a) 944 { 945 return get_attrp(a, ATTR_CALLAS); 946 } 947 948 static int is_inherited_method(const type_t *iface, const var_t *func) 949 { 950 while ((iface = type_iface_get_inherit(iface))) 951 { 952 const statement_t *stmt; 953 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 954 { 955 const var_t *funccmp = stmt->u.var; 956 957 if (!is_callas(func->attrs)) 958 { 959 char inherit_name[256]; 960 /* compare full name including property prefix */ 961 strcpy(inherit_name, get_name(funccmp)); 962 if (!strcmp(inherit_name, get_name(func))) return 1; 963 } 964 } 965 } 966 967 return 0; 968 } 969 970 static int is_override_method(const type_t *iface, const type_t *child, const var_t *func) 971 { 972 if (iface == child) 973 return 0; 974 975 do 976 { 977 const statement_t *stmt; 978 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(child)) 979 { 980 const var_t *funccmp = stmt->u.var; 981 982 if (!is_callas(func->attrs)) 983 { 984 char inherit_name[256]; 985 /* compare full name including property prefix */ 986 strcpy(inherit_name, get_name(funccmp)); 987 if (!strcmp(inherit_name, get_name(func))) return 1; 988 } 989 } 990 } 991 while ((child = type_iface_get_inherit(child)) && child != iface); 992 993 return 0; 994 } 995 996 static int is_aggregate_return(const var_t *func) 997 { 998 enum type_type type = type_get_type(type_function_get_rettype(func->type)); 999 return type == TYPE_STRUCT || type == TYPE_UNION || 1000 type == TYPE_COCLASS || type == TYPE_INTERFACE; 1001 } 1002 1003 static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) 1004 { 1005 static char buff[255]; 1006 if (is_inherited_method(iface, func)) 1007 sprintf(buff, "%s_%s", iface->name, get_name(func)); 1008 else 1009 sprintf(buff, "%s", get_name(func)); 1010 return buff; 1011 } 1012 1013 static void write_method_macro(FILE *header, const type_t *iface, const type_t *child, const char *name) 1014 { 1015 const statement_t *stmt; 1016 int first_iface = 1; 1017 1018 if (type_iface_get_inherit(iface)) 1019 write_method_macro(header, type_iface_get_inherit(iface), child, name); 1020 1021 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1022 { 1023 const var_t *func = stmt->u.var; 1024 1025 if (first_iface) 1026 { 1027 fprintf(header, "/*** %s methods ***/\n", iface->name); 1028 first_iface = 0; 1029 } 1030 1031 if (is_override_method(iface, child, func)) 1032 continue; 1033 1034 if (!is_callas(func->attrs)) { 1035 const var_t *arg; 1036 1037 fprintf(header, "#define %s_%s(This", name, get_name(func)); 1038 if (type_get_function_args(func->type)) 1039 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 1040 fprintf(header, ",%s", arg->name); 1041 fprintf(header, ") "); 1042 1043 if (is_aggregate_return(func)) 1044 { 1045 fprintf(header, "%s_%s_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support\n", name, get_name(func)); 1046 continue; 1047 } 1048 1049 fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func)); 1050 if (type_get_function_args(func->type)) 1051 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 1052 fprintf(header, ",%s", arg->name); 1053 fprintf(header, ")\n"); 1054 } 1055 } 1056 } 1057 1058 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent) 1059 { 1060 const var_t *arg; 1061 int count = 0; 1062 1063 if (do_indent) 1064 { 1065 indentation++; 1066 indent(h, 0); 1067 } 1068 if (method == 1) { 1069 fprintf(h, "%s* This", name); 1070 count++; 1071 } 1072 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { 1073 if (count) { 1074 if (do_indent) 1075 { 1076 fprintf(h, ",\n"); 1077 indent(h, 0); 1078 } 1079 else fprintf(h, ","); 1080 } 1081 write_type_decl(h, arg->type, arg->name); 1082 if (method == 2) { 1083 const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); 1084 if (expr) { 1085 const var_t *tail_arg; 1086 1087 /* Output default value only if all following arguments also have default value. */ 1088 LIST_FOR_EACH_ENTRY_REV( tail_arg, args, const var_t, entry ) { 1089 if(tail_arg == arg) { 1090 expr_t bstr; 1091 1092 /* Fixup the expression type for a BSTR like midl does. */ 1093 if (get_type_vt(arg->type) == VT_BSTR && expr->type == EXPR_STRLIT) 1094 { 1095 bstr = *expr; 1096 bstr.type = EXPR_WSTRLIT; 1097 expr = &bstr; 1098 } 1099 1100 fprintf(h, " = "); 1101 write_expr( h, expr, 0, 1, NULL, NULL, "" ); 1102 break; 1103 } 1104 if(!get_attrp(tail_arg->attrs, ATTR_DEFAULTVALUE)) 1105 break; 1106 } 1107 } 1108 } 1109 count++; 1110 } 1111 if (do_indent) indentation--; 1112 } 1113 1114 static void write_cpp_method_def(FILE *header, const type_t *iface) 1115 { 1116 const statement_t *stmt; 1117 1118 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1119 { 1120 const var_t *func = stmt->u.var; 1121 if (!is_callas(func->attrs)) { 1122 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1123 const var_list_t *args = type_get_function_args(func->type); 1124 const var_t *arg; 1125 1126 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1127 1128 if (is_aggregate_return(func)) { 1129 fprintf(header, "#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS\n"); 1130 1131 indent(header, 0); 1132 fprintf(header, "virtual "); 1133 write_type_decl_left(header, type_function_get_rettype(func->type)); 1134 fprintf(header, "* %s %s(\n", callconv, get_name(func)); 1135 ++indentation; 1136 indent(header, 0); 1137 write_type_decl_left(header, type_function_get_rettype(func->type)); 1138 fprintf(header, " *__ret"); 1139 --indentation; 1140 if (args) { 1141 fprintf(header, ",\n"); 1142 write_args(header, args, iface->name, 2, TRUE); 1143 } 1144 fprintf(header, ") = 0;\n"); 1145 1146 indent(header, 0); 1147 write_type_decl_left(header, type_function_get_rettype(func->type)); 1148 fprintf(header, " %s %s(\n", callconv, get_name(func)); 1149 write_args(header, args, iface->name, 2, TRUE); 1150 fprintf(header, ")\n"); 1151 indent(header, 0); 1152 fprintf(header, "{\n"); 1153 ++indentation; 1154 indent(header, 0); 1155 write_type_decl_left(header, type_function_get_rettype(func->type)); 1156 fprintf(header, " __ret;\n"); 1157 indent(header, 0); 1158 fprintf(header, "return *%s(&__ret", get_name(func)); 1159 if (args) 1160 LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry) 1161 fprintf(header, ", %s", arg->name); 1162 fprintf(header, ");\n"); 1163 --indentation; 1164 indent(header, 0); 1165 fprintf(header, "}\n"); 1166 1167 fprintf(header, "#else\n"); 1168 } 1169 1170 indent(header, 0); 1171 fprintf(header, "virtual "); 1172 write_type_decl_left(header, type_function_get_rettype(func->type)); 1173 fprintf(header, " %s %s(\n", callconv, get_name(func)); 1174 write_args(header, args, iface->name, 2, TRUE); 1175 fprintf(header, ") = 0;\n"); 1176 1177 if (is_aggregate_return(func)) 1178 fprintf(header, "#endif\n"); 1179 fprintf(header, "\n"); 1180 } 1181 } 1182 } 1183 1184 static void write_inline_wrappers(FILE *header, const type_t *iface, const type_t *child, const char *name) 1185 { 1186 const statement_t *stmt; 1187 int first_iface = 1; 1188 1189 if (type_iface_get_inherit(iface)) 1190 write_inline_wrappers(header, type_iface_get_inherit(iface), child, name); 1191 1192 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1193 { 1194 const var_t *func = stmt->u.var; 1195 1196 if (first_iface) 1197 { 1198 fprintf(header, "/*** %s methods ***/\n", iface->name); 1199 first_iface = 0; 1200 } 1201 1202 if (is_override_method(iface, child, func)) 1203 continue; 1204 1205 if (!is_callas(func->attrs)) { 1206 const var_t *arg; 1207 1208 #ifdef __REACTOS__ 1209 fprintf(header, "FORCEINLINE "); 1210 #else 1211 fprintf(header, "static FORCEINLINE "); 1212 #endif 1213 write_type_decl_left(header, type_function_get_rettype(func->type)); 1214 fprintf(header, " %s_%s(", name, get_name(func)); 1215 write_args(header, type_get_function_args(func->type), name, 1, FALSE); 1216 fprintf(header, ") {\n"); 1217 ++indentation; 1218 if (!is_aggregate_return(func)) { 1219 indent(header, 0); 1220 fprintf(header, "%sThis->lpVtbl->%s(This", 1221 is_void(type_function_get_rettype(func->type)) ? "" : "return ", 1222 get_vtbl_entry_name(iface, func)); 1223 } else { 1224 indent(header, 0); 1225 write_type_decl_left(header, type_function_get_rettype(func->type)); 1226 fprintf(header, " __ret;\n"); 1227 indent(header, 0); 1228 fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func)); 1229 } 1230 if (type_get_function_args(func->type)) 1231 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 1232 fprintf(header, ",%s", arg->name); 1233 fprintf(header, ");\n"); 1234 --indentation; 1235 fprintf(header, "}\n"); 1236 } 1237 } 1238 } 1239 1240 static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name) 1241 { 1242 const statement_t *stmt; 1243 int first_iface = 1; 1244 1245 if (type_iface_get_inherit(iface)) 1246 do_write_c_method_def(header, type_iface_get_inherit(iface), name); 1247 #ifdef __REACTOS__ /* r59312 / 3ab1571 */ 1248 else if (type_iface_get_stmts(iface) == NULL) 1249 { 1250 fprintf(header, "#ifndef __cplusplus\n"); 1251 indent(header, 0); 1252 fprintf(header, "char dummy;\n"); 1253 fprintf(header, "#endif\n"); 1254 fprintf(header, "\n"); 1255 return; 1256 } 1257 #endif 1258 1259 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1260 { 1261 const var_t *func = stmt->u.var; 1262 if (first_iface) { 1263 indent(header, 0); 1264 fprintf(header, "/*** %s methods ***/\n", iface->name); 1265 first_iface = 0; 1266 } 1267 if (!is_callas(func->attrs)) { 1268 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1269 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1270 indent(header, 0); 1271 write_type_decl_left(header, type_function_get_rettype(func->type)); 1272 if (is_aggregate_return(func)) 1273 fprintf(header, " *"); 1274 if (is_inherited_method(iface, func)) 1275 fprintf(header, " (%s *%s_%s)(\n", callconv, iface->name, func->name); 1276 else 1277 fprintf(header, " (%s *%s)(\n", callconv, get_name(func)); 1278 ++indentation; 1279 indent(header, 0); 1280 fprintf(header, "%s *This", name); 1281 if (is_aggregate_return(func)) { 1282 fprintf(header, ",\n"); 1283 indent(header, 0); 1284 write_type_decl_left(header, type_function_get_rettype(func->type)); 1285 fprintf(header, " *__ret"); 1286 } 1287 --indentation; 1288 if (type_get_function_args(func->type)) { 1289 fprintf(header, ",\n"); 1290 write_args(header, type_get_function_args(func->type), name, 0, TRUE); 1291 } 1292 fprintf(header, ");\n"); 1293 fprintf(header, "\n"); 1294 } 1295 } 1296 } 1297 1298 static void write_c_method_def(FILE *header, const type_t *iface) 1299 { 1300 do_write_c_method_def(header, iface, iface->c_name); 1301 } 1302 1303 static void write_c_disp_method_def(FILE *header, const type_t *iface) 1304 { 1305 do_write_c_method_def(header, type_iface_get_inherit(iface), iface->c_name); 1306 } 1307 1308 static void write_method_proto(FILE *header, const type_t *iface) 1309 { 1310 const statement_t *stmt; 1311 1312 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1313 { 1314 const var_t *func = stmt->u.var; 1315 1316 if (is_callas(func->attrs)) { 1317 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 1318 if (!callconv) callconv = "STDMETHODCALLTYPE"; 1319 /* proxy prototype */ 1320 write_type_decl_left(header, type_function_get_rettype(func->type)); 1321 fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); 1322 write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE); 1323 fprintf(header, ");\n"); 1324 /* stub prototype */ 1325 fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); 1326 fprintf(header, " IRpcStubBuffer* This,\n"); 1327 fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); 1328 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n"); 1329 fprintf(header, " DWORD* pdwStubPhase);\n"); 1330 } 1331 } 1332 } 1333 1334 static void write_locals(FILE *fp, const type_t *iface, int body) 1335 { 1336 static const char comment[] 1337 = "/* WIDL-generated stub. You must provide an implementation for this. */"; 1338 const statement_t *stmt; 1339 1340 if (!is_object(iface)) 1341 return; 1342 1343 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { 1344 const var_t *func = stmt->u.var; 1345 const var_t *cas = is_callas(func->attrs); 1346 1347 if (cas) { 1348 const statement_t *stmt2 = NULL; 1349 STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) 1350 if (!strcmp(get_name(stmt2->u.var), cas->name)) 1351 break; 1352 if (&stmt2->entry != type_iface_get_stmts(iface)) { 1353 const var_t *m = stmt2->u.var; 1354 /* proxy prototype - use local prototype */ 1355 write_type_decl_left(fp, type_function_get_rettype(m->type)); 1356 fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); 1357 write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE); 1358 fprintf(fp, ")"); 1359 if (body) { 1360 type_t *rt = type_function_get_rettype(m->type); 1361 fprintf(fp, "\n{\n"); 1362 fprintf(fp, " %s\n", comment); 1363 if (rt->name && strcmp(rt->name, "HRESULT") == 0) 1364 fprintf(fp, " return E_NOTIMPL;\n"); 1365 else if (type_get_type(rt) != TYPE_VOID) { 1366 fprintf(fp, " "); 1367 write_type_decl(fp, rt, "rv"); 1368 fprintf(fp, ";\n"); 1369 fprintf(fp, " memset(&rv, 0, sizeof rv);\n"); 1370 fprintf(fp, " return rv;\n"); 1371 } 1372 fprintf(fp, "}\n\n"); 1373 } 1374 else 1375 fprintf(fp, ";\n"); 1376 /* stub prototype - use remotable prototype */ 1377 write_type_decl_left(fp, type_function_get_rettype(func->type)); 1378 fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); 1379 write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE); 1380 fprintf(fp, ")"); 1381 if (body) 1382 /* Remotable methods must all return HRESULTs. */ 1383 fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment); 1384 else 1385 fprintf(fp, ";\n"); 1386 } 1387 else 1388 error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name); 1389 } 1390 } 1391 } 1392 1393 static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts) 1394 { 1395 const statement_t *stmt; 1396 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1397 { 1398 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 1399 write_locals(local_stubs, stmt->u.type, TRUE); 1400 } 1401 } 1402 1403 void write_local_stubs(const statement_list_t *stmts) 1404 { 1405 FILE *local_stubs; 1406 1407 if (!local_stubs_name) return; 1408 1409 local_stubs = fopen(local_stubs_name, "w"); 1410 if (!local_stubs) { 1411 error("Could not open %s for output\n", local_stubs_name); 1412 return; 1413 } 1414 fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name); 1415 fprintf(local_stubs, "#include <objbase.h>\n"); 1416 fprintf(local_stubs, "#include \"%s\"\n\n", header_name); 1417 1418 write_local_stubs_stmts(local_stubs, stmts); 1419 1420 fclose(local_stubs); 1421 } 1422 1423 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix) 1424 { 1425 const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV); 1426 1427 if (!callconv) callconv = "__cdecl"; 1428 /* FIXME: do we need to handle call_as? */ 1429 write_type_decl_left(header, type_function_get_rettype(fun->type)); 1430 fprintf(header, " %s ", callconv); 1431 fprintf(header, "%s%s(\n", prefix, get_name(fun)); 1432 if (type_get_function_args(fun->type)) 1433 write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE); 1434 else 1435 fprintf(header, " void"); 1436 fprintf(header, ");\n\n"); 1437 } 1438 1439 static void write_forward(FILE *header, type_t *iface) 1440 { 1441 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name); 1442 fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->c_name); 1443 fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); 1444 fprintf(header, "#ifdef __cplusplus\n"); 1445 write_namespace_start(header, iface->namespace); 1446 write_line(header, 0, "interface %s;", iface->name); 1447 write_namespace_end(header, iface->namespace); 1448 fprintf(header, "#endif /* __cplusplus */\n"); 1449 fprintf(header, "#endif\n\n" ); 1450 } 1451 1452 static void write_com_interface_start(FILE *header, const type_t *iface) 1453 { 1454 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 1455 fprintf(header, "/*****************************************************************************\n"); 1456 fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); 1457 fprintf(header, " */\n"); 1458 fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : ""); 1459 fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); 1460 } 1461 1462 static void write_com_interface_end(FILE *header, type_t *iface) 1463 { 1464 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 1465 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); 1466 type_t *type; 1467 1468 if (uuid) 1469 write_guid(header, dispinterface ? "DIID" : "IID", iface->c_name, uuid); 1470 1471 /* C++ interface */ 1472 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); 1473 if (!is_global_namespace(iface->namespace)) { 1474 write_line(header, 0, "} /* extern \"C\" */"); 1475 write_namespace_start(header, iface->namespace); 1476 } 1477 if (uuid) { 1478 write_line(header, 0, "MIDL_INTERFACE(\"%s\")", uuid_string(uuid)); 1479 indent(header, 0); 1480 }else { 1481 indent(header, 0); 1482 fprintf(header, "interface "); 1483 } 1484 if (type_iface_get_inherit(iface)) 1485 { 1486 fprintf(header, "%s : public %s\n", iface->name, 1487 type_iface_get_inherit(iface)->name); 1488 write_line(header, 1, "{"); 1489 } 1490 else 1491 { 1492 fprintf(header, "%s\n", iface->name); 1493 write_line(header, 1, "{\n"); 1494 write_line(header, 0, "BEGIN_INTERFACE\n"); 1495 } 1496 /* dispinterfaces don't have real functions, so don't write C++ functions for 1497 * them */ 1498 if (!dispinterface) 1499 write_cpp_method_def(header, iface); 1500 if (!type_iface_get_inherit(iface)) 1501 write_line(header, 0, "END_INTERFACE\n"); 1502 write_line(header, -1, "};"); 1503 if (!is_global_namespace(iface->namespace)) { 1504 write_namespace_end(header, iface->namespace); 1505 write_line(header, 0, "extern \"C\" {"); 1506 } 1507 if (uuid) 1508 write_uuid_decl(header, iface, uuid); 1509 fprintf(header, "#else\n"); 1510 /* C interface */ 1511 write_line(header, 1, "typedef struct %sVtbl {", iface->c_name); 1512 write_line(header, 0, "BEGIN_INTERFACE\n"); 1513 if (dispinterface) 1514 write_c_disp_method_def(header, iface); 1515 else 1516 write_c_method_def(header, iface); 1517 write_line(header, 0, "END_INTERFACE"); 1518 write_line(header, -1, "} %sVtbl;\n", iface->c_name); 1519 fprintf(header, "interface %s {\n", iface->c_name); 1520 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->c_name); 1521 fprintf(header, "};\n\n"); 1522 fprintf(header, "#ifdef COBJMACROS\n"); 1523 /* dispinterfaces don't have real functions, so don't write macros for them, 1524 * only for the interface this interface inherits from, i.e. IDispatch */ 1525 fprintf(header, "#ifndef WIDL_C_INLINE_WRAPPERS\n"); 1526 type = dispinterface ? type_iface_get_inherit(iface) : iface; 1527 write_method_macro(header, type, type, iface->c_name); 1528 fprintf(header, "#else\n"); 1529 write_inline_wrappers(header, type, type, iface->c_name); 1530 fprintf(header, "#endif\n"); 1531 fprintf(header, "#endif\n"); 1532 fprintf(header, "\n"); 1533 fprintf(header, "#endif\n"); 1534 fprintf(header, "\n"); 1535 /* dispinterfaces don't have real functions, so don't write prototypes for 1536 * them */ 1537 if (!dispinterface && !winrt_mode) 1538 { 1539 write_method_proto(header, iface); 1540 write_locals(header, iface, FALSE); 1541 fprintf(header, "\n"); 1542 } 1543 fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->c_name, dispinterface ? "DISP" : ""); 1544 } 1545 1546 static void write_rpc_interface_start(FILE *header, const type_t *iface) 1547 { 1548 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 1549 const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 1550 1551 fprintf(header, "/*****************************************************************************\n"); 1552 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1553 fprintf(header, " */\n"); 1554 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); 1555 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); 1556 if (var) 1557 { 1558 fprintf(header, "extern "); 1559 write_type_decl( header, var->type, var->name ); 1560 fprintf(header, ";\n"); 1561 } 1562 if (old_names) 1563 { 1564 fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name); 1565 fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name); 1566 } 1567 else 1568 { 1569 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n", 1570 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1571 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n", 1572 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 1573 } 1574 } 1575 1576 static void write_rpc_interface_end(FILE *header, const type_t *iface) 1577 { 1578 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); 1579 } 1580 1581 static void write_coclass(FILE *header, type_t *cocl) 1582 { 1583 const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID); 1584 1585 fprintf(header, "/*****************************************************************************\n"); 1586 fprintf(header, " * %s coclass\n", cocl->name); 1587 fprintf(header, " */\n\n"); 1588 if (uuid) 1589 write_guid(header, "CLSID", cocl->name, uuid); 1590 fprintf(header, "\n#ifdef __cplusplus\n"); 1591 if (uuid) 1592 { 1593 fprintf(header, "class DECLSPEC_UUID(\"%s\") %s;\n", uuid_string(uuid), cocl->name); 1594 write_uuid_decl(header, cocl, uuid); 1595 } 1596 else 1597 { 1598 fprintf(header, "class %s;\n", cocl->name); 1599 } 1600 fprintf(header, "#endif\n"); 1601 fprintf(header, "\n"); 1602 } 1603 1604 static void write_coclass_forward(FILE *header, type_t *cocl) 1605 { 1606 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name); 1607 fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name); 1608 fprintf(header, "#ifdef __cplusplus\n"); 1609 fprintf(header, "typedef class %s %s;\n", cocl->name, cocl->name); 1610 fprintf(header, "#else\n"); 1611 fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name); 1612 fprintf(header, "#endif /* defined __cplusplus */\n"); 1613 fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); 1614 } 1615 1616 static void write_import(FILE *header, const char *fname) 1617 { 1618 char *hname, *p; 1619 1620 hname = dup_basename(fname, ".idl"); 1621 p = hname + strlen(hname) - 2; 1622 if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h"); 1623 1624 fprintf(header, "#include <%s>\n", hname); 1625 free(hname); 1626 } 1627 1628 static void write_imports(FILE *header, const statement_list_t *stmts) 1629 { 1630 const statement_t *stmt; 1631 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1632 { 1633 switch (stmt->type) 1634 { 1635 case STMT_TYPE: 1636 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1637 write_imports(header, type_iface_get_stmts(stmt->u.type)); 1638 break; 1639 case STMT_TYPEREF: 1640 case STMT_IMPORTLIB: 1641 /* not included in header */ 1642 break; 1643 case STMT_IMPORT: 1644 write_import(header, stmt->u.str); 1645 break; 1646 case STMT_TYPEDEF: 1647 case STMT_MODULE: 1648 case STMT_CPPQUOTE: 1649 case STMT_PRAGMA: 1650 case STMT_DECLARATION: 1651 /* not processed here */ 1652 break; 1653 case STMT_LIBRARY: 1654 write_imports(header, stmt->u.lib->stmts); 1655 break; 1656 } 1657 } 1658 } 1659 1660 static void write_forward_decls(FILE *header, const statement_list_t *stmts) 1661 { 1662 const statement_t *stmt; 1663 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1664 { 1665 switch (stmt->type) 1666 { 1667 case STMT_TYPE: 1668 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1669 { 1670 type_t *iface = stmt->u.type; 1671 if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) 1672 { 1673 write_forward(header, iface); 1674 if (iface->details.iface->async_iface) 1675 write_forward(header, iface->details.iface->async_iface); 1676 } 1677 } 1678 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 1679 write_coclass_forward(header, stmt->u.type); 1680 break; 1681 case STMT_TYPEREF: 1682 case STMT_IMPORTLIB: 1683 /* not included in header */ 1684 break; 1685 case STMT_IMPORT: 1686 case STMT_TYPEDEF: 1687 case STMT_MODULE: 1688 case STMT_CPPQUOTE: 1689 case STMT_PRAGMA: 1690 case STMT_DECLARATION: 1691 /* not processed here */ 1692 break; 1693 case STMT_LIBRARY: 1694 write_forward_decls(header, stmt->u.lib->stmts); 1695 break; 1696 } 1697 } 1698 } 1699 1700 static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs) 1701 { 1702 const statement_t *stmt; 1703 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 1704 { 1705 switch (stmt->type) 1706 { 1707 case STMT_TYPE: 1708 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 1709 { 1710 type_t *iface = stmt->u.type; 1711 type_t *async_iface = iface->details.iface->async_iface; 1712 if (is_object(iface)) is_object_interface++; 1713 if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) 1714 { 1715 write_com_interface_start(header, iface); 1716 write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE); 1717 write_com_interface_end(header, iface); 1718 if (async_iface) 1719 { 1720 write_com_interface_start(header, async_iface); 1721 write_com_interface_end(header, async_iface); 1722 } 1723 } 1724 else 1725 { 1726 write_rpc_interface_start(header, iface); 1727 write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE); 1728 write_rpc_interface_end(header, iface); 1729 } 1730 if (is_object(iface)) is_object_interface--; 1731 } 1732 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 1733 write_coclass(header, stmt->u.type); 1734 else 1735 { 1736 write_type_definition(header, stmt->u.type); 1737 } 1738 break; 1739 case STMT_TYPEREF: 1740 /* FIXME: shouldn't write out forward declarations for undefined 1741 * interfaces but a number of our IDL files depend on this */ 1742 if (type_get_type(stmt->u.type) == TYPE_INTERFACE && !stmt->u.type->written) 1743 write_forward(header, stmt->u.type); 1744 break; 1745 case STMT_IMPORTLIB: 1746 case STMT_MODULE: 1747 case STMT_PRAGMA: 1748 /* not included in header */ 1749 break; 1750 case STMT_IMPORT: 1751 /* not processed here */ 1752 break; 1753 case STMT_TYPEDEF: 1754 { 1755 const type_list_t *type_entry = stmt->u.type_list; 1756 for (; type_entry; type_entry = type_entry->next) 1757 write_typedef(header, type_entry->type); 1758 break; 1759 } 1760 case STMT_LIBRARY: 1761 write_library(header, stmt->u.lib); 1762 write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE); 1763 break; 1764 case STMT_CPPQUOTE: 1765 fprintf(header, "%s\n", stmt->u.str); 1766 break; 1767 case STMT_DECLARATION: 1768 if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION) 1769 { 1770 if (!ignore_funcs) 1771 { 1772 int prefixes_differ = strcmp(prefix_client, prefix_server); 1773 1774 if (prefixes_differ) 1775 { 1776 fprintf(header, "/* client prototype */\n"); 1777 write_function_proto(header, iface, stmt->u.var, prefix_client); 1778 fprintf(header, "/* server prototype */\n"); 1779 } 1780 write_function_proto(header, iface, stmt->u.var, prefix_server); 1781 } 1782 } 1783 else 1784 write_declaration(header, stmt->u.var); 1785 break; 1786 } 1787 } 1788 } 1789 1790 void write_header(const statement_list_t *stmts) 1791 { 1792 FILE *header; 1793 1794 if (!do_header) return; 1795 1796 if(!(header = fopen(header_name, "w"))) { 1797 error("Could not open %s for output\n", header_name); 1798 return; 1799 } 1800 fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name); 1801 1802 fprintf(header, "#ifdef _WIN32\n"); 1803 fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n"); 1804 fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n"); 1805 fprintf(header, "#endif\n\n"); 1806 1807 fprintf(header, "#ifdef __REACTOS__\n"); 1808 fprintf(header, "#define WIN32_LEAN_AND_MEAN\n"); 1809 fprintf(header, "#endif\n\n"); 1810 1811 fprintf(header, "#include <rpc.h>\n" ); 1812 fprintf(header, "#include <rpcndr.h>\n" ); 1813 if (!for_each_serializable(stmts, NULL, serializable_exists)) 1814 fprintf(header, "#include <midles.h>\n" ); 1815 fprintf(header, "#endif\n\n"); 1816 1817 fprintf(header, "#ifndef COM_NO_WINDOWS_H\n"); 1818 fprintf(header, "#include <windows.h>\n"); 1819 fprintf(header, "#include <ole2.h>\n"); 1820 fprintf(header, "#endif\n\n"); 1821 1822 fprintf(header, "#ifndef __%s__\n", header_token); 1823 fprintf(header, "#define __%s__\n\n", header_token); 1824 1825 fprintf(header, "/* Forward declarations */\n\n"); 1826 write_forward_decls(header, stmts); 1827 1828 fprintf(header, "/* Headers for imported files */\n\n"); 1829 write_imports(header, stmts); 1830 fprintf(header, "\n"); 1831 start_cplusplus_guard(header); 1832 1833 write_header_stmts(header, stmts, NULL, FALSE); 1834 1835 fprintf(header, "/* Begin additional prototypes for all interfaces */\n"); 1836 fprintf(header, "\n"); 1837 for_each_serializable(stmts, header, write_serialize_function_decl); 1838 write_user_types(header); 1839 write_generic_handle_routines(header); 1840 write_context_handle_rundowns(header); 1841 fprintf(header, "\n"); 1842 fprintf(header, "/* End additional prototypes */\n"); 1843 fprintf(header, "\n"); 1844 1845 end_cplusplus_guard(header); 1846 fprintf(header, "#endif /* __%s__ */\n", header_token); 1847 1848 fclose(header); 1849 } 1850