Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenheader.c
Go to the documentation of this file.
00001 /* 00002 * IDL Compiler 00003 * 00004 * Copyright 2002 Ove Kaaven 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <stdarg.h> 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #ifdef HAVE_UNISTD_H 00027 # include <unistd.h> 00028 #endif 00029 #include <string.h> 00030 #include <ctype.h> 00031 00032 #include "widl.h" 00033 #include "utils.h" 00034 #include "parser.h" 00035 #include "header.h" 00036 #include "expr.h" 00037 #include "typetree.h" 00038 00039 static int indentation = 0; 00040 static int is_object_interface = 0; 00041 user_type_list_t user_type_list = LIST_INIT(user_type_list); 00042 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); 00043 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list); 00044 00045 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name); 00046 00047 static void indent(FILE *h, int delta) 00048 { 00049 int c; 00050 if (delta < 0) indentation += delta; 00051 for (c=0; c<indentation; c++) fprintf(h, " "); 00052 if (delta > 0) indentation += delta; 00053 } 00054 00055 int is_ptrchain_attr(const var_t *var, enum attr_type t) 00056 { 00057 if (is_attr(var->attrs, t)) 00058 return 1; 00059 else 00060 { 00061 type_t *type = var->type; 00062 for (;;) 00063 { 00064 if (is_attr(type->attrs, t)) 00065 return 1; 00066 else if (type_is_alias(type)) 00067 type = type_alias_get_aliasee(type); 00068 else if (is_ptr(type)) 00069 type = type_pointer_get_ref(type); 00070 else return 0; 00071 } 00072 } 00073 } 00074 00075 int is_aliaschain_attr(const type_t *type, enum attr_type attr) 00076 { 00077 const type_t *t = type; 00078 for (;;) 00079 { 00080 if (is_attr(t->attrs, attr)) 00081 return 1; 00082 else if (type_is_alias(t)) 00083 t = type_alias_get_aliasee(t); 00084 else return 0; 00085 } 00086 } 00087 00088 int is_attr(const attr_list_t *list, enum attr_type t) 00089 { 00090 const attr_t *attr; 00091 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 00092 if (attr->type == t) return 1; 00093 return 0; 00094 } 00095 00096 void *get_attrp(const attr_list_t *list, enum attr_type t) 00097 { 00098 const attr_t *attr; 00099 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 00100 if (attr->type == t) return attr->u.pval; 00101 return NULL; 00102 } 00103 00104 unsigned int get_attrv(const attr_list_t *list, enum attr_type t) 00105 { 00106 const attr_t *attr; 00107 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) 00108 if (attr->type == t) return attr->u.ival; 00109 return 0; 00110 } 00111 00112 int is_void(const type_t *t) 00113 { 00114 return type_get_type(t) == TYPE_VOID; 00115 } 00116 00117 int is_conformant_array(const type_t *t) 00118 { 00119 return is_array(t) && type_array_has_conformance(t); 00120 } 00121 00122 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) 00123 { 00124 if (!uuid) return; 00125 fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," 00126 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n", 00127 guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], 00128 uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], 00129 uuid->Data4[6], uuid->Data4[7]); 00130 } 00131 00132 static void write_uuid_decl(FILE *f, const char *name, const UUID *uuid) 00133 { 00134 fprintf(f, "#ifdef __CRT_UUID_DECL\n"); 00135 fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," 00136 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", 00137 name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], 00138 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], 00139 uuid->Data4[7]); 00140 fprintf(f, "#endif\n"); 00141 } 00142 00143 static const char *uuid_string(const UUID *uuid) 00144 { 00145 static char buf[37]; 00146 00147 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 00148 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], 00149 uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); 00150 00151 return buf; 00152 } 00153 00154 const char *get_name(const var_t *v) 00155 { 00156 static char buffer[256]; 00157 00158 if (is_attr( v->attrs, ATTR_PROPGET )) 00159 strcpy( buffer, "get_" ); 00160 else if (is_attr( v->attrs, ATTR_PROPPUT )) 00161 strcpy( buffer, "put_" ); 00162 else if (is_attr( v->attrs, ATTR_PROPPUTREF )) 00163 strcpy( buffer, "putref_" ); 00164 else 00165 buffer[0] = 0; 00166 strcat( buffer, v->name ); 00167 return buffer; 00168 } 00169 00170 static void write_field(FILE *h, var_t *v) 00171 { 00172 if (!v) return; 00173 if (v->type) { 00174 indent(h, 0); 00175 write_type_def_or_decl(h, v->type, TRUE, v->name); 00176 fprintf(h, ";\n"); 00177 } 00178 } 00179 00180 static void write_fields(FILE *h, var_list_t *fields) 00181 { 00182 var_t *v; 00183 if (!fields) return; 00184 LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v); 00185 } 00186 00187 static void write_enums(FILE *h, var_list_t *enums) 00188 { 00189 var_t *v; 00190 if (!enums) return; 00191 LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) 00192 { 00193 if (v->name) { 00194 indent(h, 0); 00195 fprintf(h, "%s", get_name(v)); 00196 if (v->eval) { 00197 fprintf(h, " = "); 00198 write_expr(h, v->eval, 0, 1, NULL, NULL, ""); 00199 } 00200 } 00201 if (list_next( enums, &v->entry )) fprintf(h, ",\n"); 00202 } 00203 fprintf(h, "\n"); 00204 } 00205 00206 int needs_space_after(type_t *t) 00207 { 00208 return (type_is_alias(t) || 00209 (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name))); 00210 } 00211 00212 void write_type_left(FILE *h, type_t *t, int declonly) 00213 { 00214 if (!h) return; 00215 00216 if (is_attr(t->attrs, ATTR_CONST) && 00217 (type_is_alias(t) || !is_ptr(t))) 00218 fprintf(h, "const "); 00219 00220 if (type_is_alias(t)) fprintf(h, "%s", t->name); 00221 else { 00222 switch (type_get_type_detect_alias(t)) { 00223 case TYPE_ENUM: 00224 if (!declonly && t->defined && !t->written) { 00225 if (t->name) fprintf(h, "enum %s {\n", t->name); 00226 else fprintf(h, "enum {\n"); 00227 t->written = TRUE; 00228 indentation++; 00229 write_enums(h, type_enum_get_values(t)); 00230 indent(h, -1); 00231 fprintf(h, "}"); 00232 } 00233 else fprintf(h, "enum %s", t->name ? t->name : ""); 00234 break; 00235 case TYPE_STRUCT: 00236 case TYPE_ENCAPSULATED_UNION: 00237 if (!declonly && t->defined && !t->written) { 00238 if (t->name) fprintf(h, "struct %s {\n", t->name); 00239 else fprintf(h, "struct {\n"); 00240 t->written = TRUE; 00241 indentation++; 00242 if (type_get_type(t) != TYPE_STRUCT) 00243 write_fields(h, type_encapsulated_union_get_fields(t)); 00244 else 00245 write_fields(h, type_struct_get_fields(t)); 00246 indent(h, -1); 00247 fprintf(h, "}"); 00248 } 00249 else fprintf(h, "struct %s", t->name ? t->name : ""); 00250 break; 00251 case TYPE_UNION: 00252 if (!declonly && t->defined && !t->written) { 00253 if (t->name) fprintf(h, "union %s {\n", t->name); 00254 else fprintf(h, "union {\n"); 00255 t->written = TRUE; 00256 indentation++; 00257 write_fields(h, type_union_get_cases(t)); 00258 indent(h, -1); 00259 fprintf(h, "}"); 00260 } 00261 else fprintf(h, "union %s", t->name ? t->name : ""); 00262 break; 00263 case TYPE_POINTER: 00264 write_type_left(h, type_pointer_get_ref(t), declonly); 00265 fprintf(h, "%s*", needs_space_after(type_pointer_get_ref(t)) ? " " : ""); 00266 if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); 00267 break; 00268 case TYPE_ARRAY: 00269 if (t->name && type_array_is_decl_as_ptr(t)) 00270 fprintf(h, "%s", t->name); 00271 else 00272 { 00273 write_type_left(h, type_array_get_element(t), declonly); 00274 if (type_array_is_decl_as_ptr(t)) 00275 fprintf(h, "%s*", needs_space_after(type_array_get_element(t)) ? " " : ""); 00276 } 00277 break; 00278 case TYPE_BASIC: 00279 if (type_basic_get_type(t) != TYPE_BASIC_INT32 && 00280 type_basic_get_type(t) != TYPE_BASIC_INT64 && 00281 type_basic_get_type(t) != TYPE_BASIC_HYPER) 00282 { 00283 if (type_basic_get_sign(t) < 0) fprintf(h, "signed "); 00284 else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned "); 00285 } 00286 switch (type_basic_get_type(t)) 00287 { 00288 case TYPE_BASIC_INT8: fprintf(h, "small"); break; 00289 case TYPE_BASIC_INT16: fprintf(h, "short"); break; 00290 case TYPE_BASIC_INT: fprintf(h, "int"); break; 00291 case TYPE_BASIC_INT3264: fprintf(h, "__int3264"); break; 00292 case TYPE_BASIC_BYTE: fprintf(h, "byte"); break; 00293 case TYPE_BASIC_CHAR: fprintf(h, "char"); break; 00294 case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break; 00295 case TYPE_BASIC_FLOAT: fprintf(h, "float"); break; 00296 case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break; 00297 case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break; 00298 case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break; 00299 case TYPE_BASIC_INT32: 00300 if (type_basic_get_sign(t) > 0) 00301 fprintf(h, "ULONG"); 00302 else 00303 fprintf(h, "LONG"); 00304 break; 00305 case TYPE_BASIC_INT64: 00306 if (type_basic_get_sign(t) > 0) 00307 fprintf(h, "UINT64"); 00308 else 00309 fprintf(h, "INT64"); 00310 break; 00311 case TYPE_BASIC_HYPER: 00312 if (type_basic_get_sign(t) > 0) 00313 fprintf(h, "MIDL_uhyper"); 00314 else 00315 fprintf(h, "hyper"); 00316 break; 00317 } 00318 break; 00319 case TYPE_INTERFACE: 00320 case TYPE_MODULE: 00321 case TYPE_COCLASS: 00322 fprintf(h, "%s", t->name); 00323 break; 00324 case TYPE_VOID: 00325 fprintf(h, "void"); 00326 break; 00327 case TYPE_BITFIELD: 00328 write_type_left(h, type_bitfield_get_field(t), declonly); 00329 break; 00330 case TYPE_ALIAS: 00331 case TYPE_FUNCTION: 00332 /* handled elsewhere */ 00333 assert(0); 00334 break; 00335 } 00336 } 00337 } 00338 00339 void write_type_right(FILE *h, type_t *t, int is_field) 00340 { 00341 if (!h) return; 00342 00343 switch (type_get_type(t)) 00344 { 00345 case TYPE_ARRAY: 00346 if (!type_array_is_decl_as_ptr(t)) 00347 { 00348 if (is_conformant_array(t)) 00349 { 00350 fprintf(h, "[%s]", is_field ? "1" : ""); 00351 t = type_array_get_element(t); 00352 } 00353 for ( ; 00354 type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t); 00355 t = type_array_get_element(t)) 00356 fprintf(h, "[%u]", type_array_get_dim(t)); 00357 } 00358 break; 00359 case TYPE_BITFIELD: 00360 fprintf(h, " : %u", type_bitfield_get_bits(t)->cval); 00361 break; 00362 case TYPE_VOID: 00363 case TYPE_BASIC: 00364 case TYPE_ENUM: 00365 case TYPE_STRUCT: 00366 case TYPE_ENCAPSULATED_UNION: 00367 case TYPE_UNION: 00368 case TYPE_ALIAS: 00369 case TYPE_MODULE: 00370 case TYPE_COCLASS: 00371 case TYPE_FUNCTION: 00372 case TYPE_INTERFACE: 00373 case TYPE_POINTER: 00374 break; 00375 } 00376 } 00377 00378 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name) 00379 { 00380 type_t *pt = NULL; 00381 int ptr_level = 0; 00382 00383 if (!h) return; 00384 00385 if (t) { 00386 for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) 00387 ; 00388 00389 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 00390 int i; 00391 const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); 00392 if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; 00393 if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); 00394 write_type_left(h, type_function_get_rettype(pt), declonly); 00395 fputc(' ', h); 00396 if (ptr_level) fputc('(', h); 00397 if (callconv) fprintf(h, "%s ", callconv); 00398 for (i = 0; i < ptr_level; i++) 00399 fputc('*', h); 00400 } else 00401 write_type_left(h, t, declonly); 00402 } 00403 00404 if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); 00405 00406 if (t) { 00407 if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { 00408 const var_list_t *args = type_function_get_args(pt); 00409 00410 if (ptr_level) fputc(')', h); 00411 fputc('(', h); 00412 if (args) 00413 write_args(h, args, NULL, 0, FALSE); 00414 else 00415 fprintf(h, "void"); 00416 fputc(')', h); 00417 } else 00418 write_type_right(h, t, is_field); 00419 } 00420 } 00421 00422 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name) 00423 { 00424 write_type_v(f, t, field, FALSE, name); 00425 } 00426 00427 void write_type_decl(FILE *f, type_t *t, const char *name) 00428 { 00429 write_type_v(f, t, FALSE, TRUE, name); 00430 } 00431 00432 void write_type_decl_left(FILE *f, type_t *t) 00433 { 00434 write_type_left(f, t, TRUE); 00435 } 00436 00437 static int user_type_registered(const char *name) 00438 { 00439 user_type_t *ut; 00440 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 00441 if (!strcmp(name, ut->name)) 00442 return 1; 00443 return 0; 00444 } 00445 00446 static int context_handle_registered(const char *name) 00447 { 00448 context_handle_t *ch; 00449 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 00450 if (!strcmp(name, ch->name)) 00451 return 1; 00452 return 0; 00453 } 00454 00455 static int generic_handle_registered(const char *name) 00456 { 00457 generic_handle_t *gh; 00458 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 00459 if (!strcmp(name, gh->name)) 00460 return 1; 00461 return 0; 00462 } 00463 00464 unsigned int get_context_handle_offset( const type_t *type ) 00465 { 00466 context_handle_t *ch; 00467 unsigned int index = 0; 00468 00469 while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) 00470 { 00471 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 00472 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 00473 else error( "internal error: %s is not a context handle\n", type->name ); 00474 } 00475 LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) 00476 { 00477 if (!strcmp( type->name, ch->name )) return index; 00478 index++; 00479 } 00480 error( "internal error: %s is not registered as a context handle\n", type->name ); 00481 return index; 00482 } 00483 00484 unsigned int get_generic_handle_offset( const type_t *type ) 00485 { 00486 generic_handle_t *gh; 00487 unsigned int index = 0; 00488 00489 while (!is_attr( type->attrs, ATTR_HANDLE )) 00490 { 00491 if (type_is_alias( type )) type = type_alias_get_aliasee( type ); 00492 else if (is_ptr( type )) type = type_pointer_get_ref( type ); 00493 else error( "internal error: %s is not a generic handle\n", type->name ); 00494 } 00495 LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) 00496 { 00497 if (!strcmp( type->name, gh->name )) return index; 00498 index++; 00499 } 00500 error( "internal error: %s is not registered as a generic handle\n", type->name ); 00501 return index; 00502 } 00503 00504 /* check for types which require additional prototypes to be generated in the 00505 * header */ 00506 void check_for_additional_prototype_types(const var_list_t *list) 00507 { 00508 const var_t *v; 00509 00510 if (!list) return; 00511 LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) 00512 { 00513 type_t *type = v->type; 00514 if (!type) continue; 00515 for (;;) { 00516 const char *name = type->name; 00517 if (type->user_types_registered) break; 00518 type->user_types_registered = 1; 00519 if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { 00520 if (!context_handle_registered(name)) 00521 { 00522 context_handle_t *ch = xmalloc(sizeof(*ch)); 00523 ch->name = xstrdup(name); 00524 list_add_tail(&context_handle_list, &ch->entry); 00525 } 00526 /* don't carry on parsing fields within this type */ 00527 break; 00528 } 00529 if ((type_get_type(type) != TYPE_BASIC || 00530 type_basic_get_type(type) != TYPE_BASIC_HANDLE) && 00531 is_attr(type->attrs, ATTR_HANDLE)) { 00532 if (!generic_handle_registered(name)) 00533 { 00534 generic_handle_t *gh = xmalloc(sizeof(*gh)); 00535 gh->name = xstrdup(name); 00536 list_add_tail(&generic_handle_list, &gh->entry); 00537 } 00538 /* don't carry on parsing fields within this type */ 00539 break; 00540 } 00541 if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { 00542 if (!user_type_registered(name)) 00543 { 00544 user_type_t *ut = xmalloc(sizeof *ut); 00545 ut->name = xstrdup(name); 00546 list_add_tail(&user_type_list, &ut->entry); 00547 } 00548 /* don't carry on parsing fields within this type as we are already 00549 * using a wire marshaled type */ 00550 break; 00551 } 00552 else if (type_is_complete(type)) 00553 { 00554 var_list_t *vars; 00555 switch (type_get_type_detect_alias(type)) 00556 { 00557 case TYPE_ENUM: 00558 vars = type_enum_get_values(type); 00559 break; 00560 case TYPE_STRUCT: 00561 vars = type_struct_get_fields(type); 00562 break; 00563 case TYPE_UNION: 00564 vars = type_union_get_cases(type); 00565 break; 00566 default: 00567 vars = NULL; 00568 break; 00569 } 00570 check_for_additional_prototype_types(vars); 00571 } 00572 00573 if (type_is_alias(type)) 00574 type = type_alias_get_aliasee(type); 00575 else if (is_ptr(type)) 00576 type = type_pointer_get_ref(type); 00577 else if (is_array(type)) 00578 type = type_array_get_element(type); 00579 else 00580 break; 00581 } 00582 } 00583 } 00584 00585 static void write_user_types(FILE *header) 00586 { 00587 user_type_t *ut; 00588 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 00589 { 00590 const char *name = ut->name; 00591 fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name); 00592 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name); 00593 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name); 00594 fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name); 00595 } 00596 } 00597 00598 static void write_context_handle_rundowns(FILE *header) 00599 { 00600 context_handle_t *ch; 00601 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) 00602 { 00603 const char *name = ch->name; 00604 fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name); 00605 } 00606 } 00607 00608 static void write_generic_handle_routines(FILE *header) 00609 { 00610 generic_handle_t *gh; 00611 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry) 00612 { 00613 const char *name = gh->name; 00614 fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name); 00615 fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name); 00616 } 00617 } 00618 00619 static void write_typedef(FILE *header, type_t *type) 00620 { 00621 fprintf(header, "typedef "); 00622 write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); 00623 fprintf(header, ";\n"); 00624 } 00625 00626 int is_const_decl(const var_t *var) 00627 { 00628 const type_t *t; 00629 /* strangely, MIDL accepts a const attribute on any pointer in the 00630 * declaration to mean that data isn't being instantiated. this appears 00631 * to be a bug, but there is no benefit to being incompatible with MIDL, 00632 * so we'll do the same thing */ 00633 for (t = var->type; ; ) 00634 { 00635 if (is_attr(t->attrs, ATTR_CONST)) 00636 return TRUE; 00637 else if (is_ptr(t)) 00638 t = type_pointer_get_ref(t); 00639 else break; 00640 } 00641 return FALSE; 00642 } 00643 00644 static void write_declaration(FILE *header, const var_t *v) 00645 { 00646 if (is_const_decl(v) && v->eval) 00647 { 00648 fprintf(header, "#define %s (", v->name); 00649 write_expr(header, v->eval, 0, 1, NULL, NULL, ""); 00650 fprintf(header, ")\n\n"); 00651 } 00652 else 00653 { 00654 switch (v->stgclass) 00655 { 00656 case STG_NONE: 00657 case STG_REGISTER: /* ignored */ 00658 break; 00659 case STG_STATIC: 00660 fprintf(header, "static "); 00661 break; 00662 case STG_EXTERN: 00663 fprintf(header, "extern "); 00664 break; 00665 } 00666 write_type_def_or_decl(header, v->type, FALSE, v->name); 00667 fprintf(header, ";\n\n"); 00668 } 00669 } 00670 00671 static void write_library(FILE *header, const typelib_t *typelib) 00672 { 00673 const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID); 00674 fprintf(header, "\n"); 00675 write_guid(header, "LIBID", typelib->name, uuid); 00676 fprintf(header, "\n"); 00677 } 00678 00679 00680 const type_t* get_explicit_generic_handle_type(const var_t* var) 00681 { 00682 const type_t *t; 00683 for (t = var->type; 00684 is_ptr(t) || type_is_alias(t); 00685 t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) 00686 if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && 00687 is_attr(t->attrs, ATTR_HANDLE)) 00688 return t; 00689 return NULL; 00690 } 00691 00692 const var_t *get_func_handle_var( const type_t *iface, const var_t *func, 00693 unsigned char *explicit_fc, unsigned char *implicit_fc ) 00694 { 00695 const var_t *var; 00696 const var_list_t *args = type_get_function_args( func->type ); 00697 00698 *explicit_fc = *implicit_fc = 0; 00699 if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 00700 { 00701 if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue; 00702 if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 00703 { 00704 *explicit_fc = RPC_FC_BIND_PRIMITIVE; 00705 return var; 00706 } 00707 if (get_explicit_generic_handle_type( var )) 00708 { 00709 *explicit_fc = RPC_FC_BIND_GENERIC; 00710 return var; 00711 } 00712 if (is_context_handle( var->type )) 00713 { 00714 *explicit_fc = RPC_FC_BIND_CONTEXT; 00715 return var; 00716 } 00717 } 00718 00719 if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE ))) 00720 { 00721 if (type_get_type( var->type ) == TYPE_BASIC && 00722 type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) 00723 *implicit_fc = RPC_FC_BIND_PRIMITIVE; 00724 else 00725 *implicit_fc = RPC_FC_BIND_GENERIC; 00726 return var; 00727 } 00728 00729 *implicit_fc = RPC_FC_AUTO_HANDLE; 00730 return NULL; 00731 } 00732 00733 int has_out_arg_or_return(const var_t *func) 00734 { 00735 const var_t *var; 00736 00737 if (!is_void(type_function_get_rettype(func->type))) 00738 return 1; 00739 00740 if (!type_get_function_args(func->type)) 00741 return 0; 00742 00743 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 00744 if (is_attr(var->attrs, ATTR_OUT)) 00745 return 1; 00746 00747 return 0; 00748 } 00749 00750 00751 /********** INTERFACES **********/ 00752 00753 int is_object(const type_t *iface) 00754 { 00755 const attr_t *attr; 00756 if (type_is_defined(iface) && type_iface_get_inherit(iface)) 00757 return 1; 00758 if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) 00759 if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; 00760 return 0; 00761 } 00762 00763 int is_local(const attr_list_t *a) 00764 { 00765 return is_attr(a, ATTR_LOCAL); 00766 } 00767 00768 const var_t *is_callas(const attr_list_t *a) 00769 { 00770 return get_attrp(a, ATTR_CALLAS); 00771 } 00772 00773 static void write_method_macro(FILE *header, const type_t *iface, const char *name) 00774 { 00775 const statement_t *stmt; 00776 int first_iface = 1; 00777 00778 if (type_iface_get_inherit(iface)) 00779 write_method_macro(header, type_iface_get_inherit(iface), name); 00780 00781 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 00782 { 00783 const var_t *func = stmt->u.var; 00784 00785 if (first_iface) 00786 { 00787 fprintf(header, "/*** %s methods ***/\n", iface->name); 00788 first_iface = 0; 00789 } 00790 00791 if (!is_callas(func->attrs)) { 00792 const var_t *arg; 00793 00794 fprintf(header, "#define %s_%s(This", name, get_name(func)); 00795 if (type_get_function_args(func->type)) 00796 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 00797 fprintf(header, ",%s", arg->name); 00798 fprintf(header, ") "); 00799 00800 fprintf(header, "(This)->lpVtbl->%s(This", get_name(func)); 00801 if (type_get_function_args(func->type)) 00802 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) 00803 fprintf(header, ",%s", arg->name); 00804 fprintf(header, ")\n"); 00805 } 00806 } 00807 } 00808 00809 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent) 00810 { 00811 const var_t *arg; 00812 int count = 0; 00813 00814 if (do_indent) 00815 { 00816 indentation++; 00817 indent(h, 0); 00818 } 00819 if (method == 1) { 00820 fprintf(h, "%s* This", name); 00821 count++; 00822 } 00823 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { 00824 if (count) { 00825 if (do_indent) 00826 { 00827 fprintf(h, ",\n"); 00828 indent(h, 0); 00829 } 00830 else fprintf(h, ","); 00831 } 00832 write_type_decl(h, arg->type, arg->name); 00833 count++; 00834 } 00835 if (do_indent) indentation--; 00836 } 00837 00838 static void write_cpp_method_def(FILE *header, const type_t *iface) 00839 { 00840 const statement_t *stmt; 00841 00842 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 00843 { 00844 const var_t *func = stmt->u.var; 00845 if (!is_callas(func->attrs)) { 00846 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 00847 if (!callconv) callconv = "STDMETHODCALLTYPE"; 00848 indent(header, 0); 00849 fprintf(header, "virtual "); 00850 write_type_decl_left(header, type_function_get_rettype(func->type)); 00851 fprintf(header, " %s %s(\n", callconv, get_name(func)); 00852 write_args(header, type_get_function_args(func->type), iface->name, 2, TRUE); 00853 fprintf(header, ") = 0;\n"); 00854 fprintf(header, "\n"); 00855 } 00856 } 00857 } 00858 00859 static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name) 00860 { 00861 const statement_t *stmt; 00862 int first_iface = 1; 00863 00864 if (type_iface_get_inherit(iface)) 00865 do_write_c_method_def(header, type_iface_get_inherit(iface), name); 00866 00867 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 00868 { 00869 const var_t *func = stmt->u.var; 00870 if (first_iface) { 00871 indent(header, 0); 00872 fprintf(header, "/*** %s methods ***/\n", iface->name); 00873 first_iface = 0; 00874 } 00875 if (!is_callas(func->attrs)) { 00876 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 00877 if (!callconv) callconv = "STDMETHODCALLTYPE"; 00878 indent(header, 0); 00879 write_type_decl_left(header, type_function_get_rettype(func->type)); 00880 fprintf(header, " (%s *%s)(\n", callconv, get_name(func)); 00881 write_args(header, type_get_function_args(func->type), name, 1, TRUE); 00882 fprintf(header, ");\n"); 00883 fprintf(header, "\n"); 00884 } 00885 } 00886 } 00887 00888 static void write_c_method_def(FILE *header, const type_t *iface) 00889 { 00890 do_write_c_method_def(header, iface, iface->name); 00891 } 00892 00893 static void write_c_disp_method_def(FILE *header, const type_t *iface) 00894 { 00895 do_write_c_method_def(header, type_iface_get_inherit(iface), iface->name); 00896 } 00897 00898 static void write_method_proto(FILE *header, const type_t *iface) 00899 { 00900 const statement_t *stmt; 00901 00902 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 00903 { 00904 const var_t *func = stmt->u.var; 00905 00906 if (!is_local(func->attrs)) { 00907 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 00908 if (!callconv) callconv = "STDMETHODCALLTYPE"; 00909 /* proxy prototype */ 00910 write_type_decl_left(header, type_function_get_rettype(func->type)); 00911 fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); 00912 write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE); 00913 fprintf(header, ");\n"); 00914 /* stub prototype */ 00915 fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); 00916 fprintf(header, " IRpcStubBuffer* This,\n"); 00917 fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); 00918 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n"); 00919 fprintf(header, " DWORD* pdwStubPhase);\n"); 00920 } 00921 } 00922 } 00923 00924 static void write_locals(FILE *fp, const type_t *iface, int body) 00925 { 00926 static const char comment[] 00927 = "/* WIDL-generated stub. You must provide an implementation for this. */"; 00928 const statement_t *stmt; 00929 00930 if (!is_object(iface)) 00931 return; 00932 00933 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { 00934 const var_t *func = stmt->u.var; 00935 const var_t *cas = is_callas(func->attrs); 00936 00937 if (cas) { 00938 const statement_t *stmt2 = NULL; 00939 STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) 00940 if (!strcmp(stmt2->u.var->name, cas->name)) 00941 break; 00942 if (&stmt2->entry != type_iface_get_stmts(iface)) { 00943 const var_t *m = stmt2->u.var; 00944 /* proxy prototype - use local prototype */ 00945 write_type_decl_left(fp, type_function_get_rettype(m->type)); 00946 fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); 00947 write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE); 00948 fprintf(fp, ")"); 00949 if (body) { 00950 type_t *rt = type_function_get_rettype(m->type); 00951 fprintf(fp, "\n{\n"); 00952 fprintf(fp, " %s\n", comment); 00953 if (rt->name && strcmp(rt->name, "HRESULT") == 0) 00954 fprintf(fp, " return E_NOTIMPL;\n"); 00955 else if (type_get_type(rt) != TYPE_VOID) { 00956 fprintf(fp, " "); 00957 write_type_decl(fp, rt, "rv"); 00958 fprintf(fp, ";\n"); 00959 fprintf(fp, " memset(&rv, 0, sizeof rv);\n"); 00960 fprintf(fp, " return rv;\n"); 00961 } 00962 fprintf(fp, "}\n\n"); 00963 } 00964 else 00965 fprintf(fp, ";\n"); 00966 /* stub prototype - use remotable prototype */ 00967 write_type_decl_left(fp, type_function_get_rettype(func->type)); 00968 fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); 00969 write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE); 00970 fprintf(fp, ")"); 00971 if (body) 00972 /* Remotable methods must all return HRESULTs. */ 00973 fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment); 00974 else 00975 fprintf(fp, ";\n"); 00976 } 00977 else 00978 error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name); 00979 } 00980 } 00981 } 00982 00983 static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts) 00984 { 00985 const statement_t *stmt; 00986 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 00987 { 00988 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 00989 write_locals(local_stubs, stmt->u.type, TRUE); 00990 else if (stmt->type == STMT_LIBRARY) 00991 write_local_stubs_stmts(local_stubs, stmt->u.lib->stmts); 00992 } 00993 } 00994 00995 void write_local_stubs(const statement_list_t *stmts) 00996 { 00997 FILE *local_stubs; 00998 00999 if (!local_stubs_name) return; 01000 01001 local_stubs = fopen(local_stubs_name, "w"); 01002 if (!local_stubs) { 01003 error("Could not open %s for output\n", local_stubs_name); 01004 return; 01005 } 01006 fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name); 01007 fprintf(local_stubs, "#include <objbase.h>\n"); 01008 fprintf(local_stubs, "#include \"%s\"\n\n", header_name); 01009 01010 write_local_stubs_stmts(local_stubs, stmts); 01011 01012 fclose(local_stubs); 01013 } 01014 01015 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix) 01016 { 01017 const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV); 01018 01019 if (!callconv) callconv = "__cdecl"; 01020 /* FIXME: do we need to handle call_as? */ 01021 write_type_decl_left(header, type_function_get_rettype(fun->type)); 01022 fprintf(header, " %s ", callconv); 01023 fprintf(header, "%s%s(\n", prefix, get_name(fun)); 01024 if (type_get_function_args(fun->type)) 01025 write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE); 01026 else 01027 fprintf(header, " void"); 01028 fprintf(header, ");\n\n"); 01029 } 01030 01031 static void write_forward(FILE *header, type_t *iface) 01032 { 01033 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name); 01034 fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name); 01035 fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name); 01036 fprintf(header, "#endif\n\n" ); 01037 } 01038 01039 static void write_com_interface_start(FILE *header, const type_t *iface) 01040 { 01041 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 01042 fprintf(header, "/*****************************************************************************\n"); 01043 fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); 01044 fprintf(header, " */\n"); 01045 fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->name, dispinterface ? "DISP" : ""); 01046 fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->name, dispinterface ? "DISP" : ""); 01047 } 01048 01049 static void write_com_interface_end(FILE *header, type_t *iface) 01050 { 01051 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); 01052 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); 01053 01054 if (uuid) 01055 write_guid(header, dispinterface ? "DIID" : "IID", iface->name, uuid); 01056 01057 /* C++ interface */ 01058 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); 01059 if (uuid) 01060 fprintf(header, "MIDL_INTERFACE(\"%s\")\n", uuid_string(uuid)); 01061 else 01062 fprintf(header, "interface "); 01063 if (type_iface_get_inherit(iface)) 01064 { 01065 fprintf(header, "%s : public %s\n", iface->name, 01066 type_iface_get_inherit(iface)->name); 01067 fprintf(header, "{\n"); 01068 } 01069 else 01070 { 01071 fprintf(header, "%s\n", iface->name); 01072 fprintf(header, "{\n"); 01073 fprintf(header, " BEGIN_INTERFACE\n"); 01074 fprintf(header, "\n"); 01075 } 01076 /* dispinterfaces don't have real functions, so don't write C++ functions for 01077 * them */ 01078 if (!dispinterface) 01079 { 01080 indentation++; 01081 write_cpp_method_def(header, iface); 01082 indentation--; 01083 } 01084 if (!type_iface_get_inherit(iface)) 01085 fprintf(header, " END_INTERFACE\n"); 01086 fprintf(header, "};\n"); 01087 if (uuid) 01088 write_uuid_decl(header, iface->name, uuid); 01089 fprintf(header, "#else\n"); 01090 /* C interface */ 01091 fprintf(header, "typedef struct %sVtbl {\n", iface->name); 01092 indentation++; 01093 fprintf(header, " BEGIN_INTERFACE\n"); 01094 fprintf(header, "\n"); 01095 if (dispinterface) 01096 write_c_disp_method_def(header, iface); 01097 else 01098 write_c_method_def(header, iface); 01099 indentation--; 01100 fprintf(header, " END_INTERFACE\n"); 01101 fprintf(header, "} %sVtbl;\n", iface->name); 01102 fprintf(header, "interface %s {\n", iface->name); 01103 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name); 01104 fprintf(header, "};\n"); 01105 fprintf(header, "\n"); 01106 fprintf(header, "#ifdef COBJMACROS\n"); 01107 /* dispinterfaces don't have real functions, so don't write macros for them, 01108 * only for the interface this interface inherits from, i.e. IDispatch */ 01109 write_method_macro(header, dispinterface ? type_iface_get_inherit(iface) : iface, iface->name); 01110 fprintf(header, "#endif\n"); 01111 fprintf(header, "\n"); 01112 fprintf(header, "#endif\n"); 01113 fprintf(header, "\n"); 01114 /* dispinterfaces don't have real functions, so don't write prototypes for 01115 * them */ 01116 if (!dispinterface) 01117 { 01118 write_method_proto(header, iface); 01119 write_locals(header, iface, FALSE); 01120 fprintf(header, "\n"); 01121 } 01122 fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->name, dispinterface ? "DISP" : ""); 01123 } 01124 01125 static void write_rpc_interface_start(FILE *header, const type_t *iface) 01126 { 01127 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 01128 const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 01129 01130 fprintf(header, "/*****************************************************************************\n"); 01131 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 01132 fprintf(header, " */\n"); 01133 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); 01134 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); 01135 if (var) 01136 { 01137 fprintf(header, "extern "); 01138 write_type_decl( header, var->type, var->name ); 01139 fprintf(header, ";\n"); 01140 } 01141 if (old_names) 01142 { 01143 fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name); 01144 fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name); 01145 } 01146 else 01147 { 01148 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n", 01149 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 01150 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n", 01151 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 01152 } 01153 } 01154 01155 static void write_rpc_interface_end(FILE *header, const type_t *iface) 01156 { 01157 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); 01158 } 01159 01160 static void write_coclass(FILE *header, type_t *cocl) 01161 { 01162 const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID); 01163 01164 fprintf(header, "/*****************************************************************************\n"); 01165 fprintf(header, " * %s coclass\n", cocl->name); 01166 fprintf(header, " */\n\n"); 01167 if (uuid) 01168 write_guid(header, "CLSID", cocl->name, uuid); 01169 fprintf(header, "\n#ifdef __cplusplus\n"); 01170 if (uuid) 01171 { 01172 fprintf(header, "class DECLSPEC_UUID(\"%s\") %s;\n", uuid_string(uuid), cocl->name); 01173 write_uuid_decl(header, cocl->name, uuid); 01174 } 01175 else 01176 { 01177 fprintf(header, "class %s;\n", cocl->name); 01178 } 01179 fprintf(header, "#endif\n"); 01180 fprintf(header, "\n"); 01181 } 01182 01183 static void write_coclass_forward(FILE *header, type_t *cocl) 01184 { 01185 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name); 01186 fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name); 01187 fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name); 01188 fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); 01189 } 01190 01191 static void write_import(FILE *header, const char *fname) 01192 { 01193 char *hname, *p; 01194 01195 hname = dup_basename(fname, ".idl"); 01196 p = hname + strlen(hname) - 2; 01197 if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h"); 01198 01199 fprintf(header, "#include <%s>\n", hname); 01200 free(hname); 01201 } 01202 01203 static void write_imports(FILE *header, const statement_list_t *stmts) 01204 { 01205 const statement_t *stmt; 01206 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 01207 { 01208 switch (stmt->type) 01209 { 01210 case STMT_TYPE: 01211 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 01212 write_imports(header, type_iface_get_stmts(stmt->u.type)); 01213 break; 01214 case STMT_TYPEREF: 01215 case STMT_IMPORTLIB: 01216 /* not included in header */ 01217 break; 01218 case STMT_IMPORT: 01219 write_import(header, stmt->u.str); 01220 break; 01221 case STMT_TYPEDEF: 01222 case STMT_MODULE: 01223 case STMT_CPPQUOTE: 01224 case STMT_DECLARATION: 01225 /* not processed here */ 01226 break; 01227 case STMT_LIBRARY: 01228 write_imports(header, stmt->u.lib->stmts); 01229 break; 01230 } 01231 } 01232 } 01233 01234 static void write_forward_decls(FILE *header, const statement_list_t *stmts) 01235 { 01236 const statement_t *stmt; 01237 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 01238 { 01239 switch (stmt->type) 01240 { 01241 case STMT_TYPE: 01242 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 01243 { 01244 if (is_object(stmt->u.type) || is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE)) 01245 write_forward(header, stmt->u.type); 01246 } 01247 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 01248 write_coclass_forward(header, stmt->u.type); 01249 break; 01250 case STMT_TYPEREF: 01251 case STMT_IMPORTLIB: 01252 /* not included in header */ 01253 break; 01254 case STMT_IMPORT: 01255 case STMT_TYPEDEF: 01256 case STMT_MODULE: 01257 case STMT_CPPQUOTE: 01258 case STMT_DECLARATION: 01259 /* not processed here */ 01260 break; 01261 case STMT_LIBRARY: 01262 write_forward_decls(header, stmt->u.lib->stmts); 01263 break; 01264 } 01265 } 01266 } 01267 01268 static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs) 01269 { 01270 const statement_t *stmt; 01271 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 01272 { 01273 switch (stmt->type) 01274 { 01275 case STMT_TYPE: 01276 if (type_get_type(stmt->u.type) == TYPE_INTERFACE) 01277 { 01278 type_t *iface = stmt->u.type; 01279 if (is_object(iface)) is_object_interface++; 01280 if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) 01281 { 01282 write_com_interface_start(header, iface); 01283 write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE); 01284 write_com_interface_end(header, iface); 01285 } 01286 else 01287 { 01288 write_rpc_interface_start(header, iface); 01289 write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE); 01290 write_rpc_interface_end(header, iface); 01291 } 01292 if (is_object(iface)) is_object_interface--; 01293 } 01294 else if (type_get_type(stmt->u.type) == TYPE_COCLASS) 01295 write_coclass(header, stmt->u.type); 01296 else 01297 { 01298 write_type_def_or_decl(header, stmt->u.type, FALSE, NULL); 01299 fprintf(header, ";\n\n"); 01300 } 01301 break; 01302 case STMT_TYPEREF: 01303 /* FIXME: shouldn't write out forward declarations for undefined 01304 * interfaces but a number of our IDL files depend on this */ 01305 if (type_get_type(stmt->u.type) == TYPE_INTERFACE && !stmt->u.type->written) 01306 write_forward(header, stmt->u.type); 01307 break; 01308 case STMT_IMPORTLIB: 01309 case STMT_MODULE: 01310 /* not included in header */ 01311 break; 01312 case STMT_IMPORT: 01313 /* not processed here */ 01314 break; 01315 case STMT_TYPEDEF: 01316 { 01317 const type_list_t *type_entry = stmt->u.type_list; 01318 for (; type_entry; type_entry = type_entry->next) 01319 write_typedef(header, type_entry->type); 01320 break; 01321 } 01322 case STMT_LIBRARY: 01323 write_library(header, stmt->u.lib); 01324 write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE); 01325 break; 01326 case STMT_CPPQUOTE: 01327 fprintf(header, "%s\n", stmt->u.str); 01328 break; 01329 case STMT_DECLARATION: 01330 if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION) 01331 { 01332 if (!ignore_funcs) 01333 { 01334 int prefixes_differ = strcmp(prefix_client, prefix_server); 01335 01336 if (prefixes_differ) 01337 { 01338 fprintf(header, "/* client prototype */\n"); 01339 write_function_proto(header, iface, stmt->u.var, prefix_client); 01340 fprintf(header, "/* server prototype */\n"); 01341 } 01342 write_function_proto(header, iface, stmt->u.var, prefix_server); 01343 } 01344 } 01345 else 01346 write_declaration(header, stmt->u.var); 01347 break; 01348 } 01349 } 01350 } 01351 01352 void write_header(const statement_list_t *stmts) 01353 { 01354 FILE *header; 01355 01356 if (!do_header) return; 01357 01358 if(!(header = fopen(header_name, "w"))) { 01359 error("Could not open %s for output\n", header_name); 01360 return; 01361 } 01362 fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name); 01363 fprintf(header, "#include <rpc.h>\n" ); 01364 fprintf(header, "#include <rpcndr.h>\n\n" ); 01365 01366 fprintf(header, "#if !defined(COM_NO_WINDOWS_H) && !defined(__WINESRC__)\n"); 01367 fprintf(header, "#include <windows.h>\n"); 01368 fprintf(header, "#include <ole2.h>\n"); 01369 fprintf(header, "#endif\n\n"); 01370 01371 fprintf(header, "#ifndef __WIDL_%s\n", header_token); 01372 fprintf(header, "#define __WIDL_%s\n\n", header_token); 01373 01374 fprintf(header, "/* Forward declarations */\n\n"); 01375 write_forward_decls(header, stmts); 01376 01377 fprintf(header, "/* Headers for imported files */\n\n"); 01378 write_imports(header, stmts); 01379 fprintf(header, "\n"); 01380 start_cplusplus_guard(header); 01381 01382 write_header_stmts(header, stmts, NULL, FALSE); 01383 01384 fprintf(header, "/* Begin additional prototypes for all interfaces */\n"); 01385 fprintf(header, "\n"); 01386 write_user_types(header); 01387 write_generic_handle_routines(header); 01388 write_context_handle_rundowns(header); 01389 fprintf(header, "\n"); 01390 fprintf(header, "/* End additional prototypes */\n"); 01391 fprintf(header, "\n"); 01392 01393 end_cplusplus_guard(header); 01394 fprintf(header, "#endif /* __WIDL_%s */\n", header_token); 01395 01396 fclose(header); 01397 } Generated on Sat May 26 2012 04:21:33 for ReactOS by
1.7.6.1
|