ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

header.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.