Back to index

lightning-sunbird  0.9+nobinonly
xpidl_typelib.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Generate typelib files for use with InterfaceInfo.
00040  * http://www.mozilla.org/scriptable/typelib_file.html
00041  */
00042 
00043 #include "xpidl.h"
00044 #include <xpt_xdr.h>
00045 #include <xpt_struct.h>
00046 #include <time.h>               /* XXX XP? */
00047 
00048 struct priv_data {
00049     XPTHeader *header;
00050     uint16 ifaces;
00051     GHashTable *interface_map;
00052     XPTInterfaceDescriptor *current;
00053     XPTArena *arena;
00054     uint16 next_method;
00055     uint16 next_const;
00056     uint16 next_type;   /* used for 'additional_types' for idl arrays */
00057 };
00058 
00059 #define HEADER(state)     (((struct priv_data *)state->priv)->header)
00060 #define IFACES(state)     (((struct priv_data *)state->priv)->ifaces)
00061 #define IFACE_MAP(state)  (((struct priv_data *)state->priv)->interface_map)
00062 #define CURRENT(state)    (((struct priv_data *)state->priv)->current)
00063 #define ARENA(state)      (((struct priv_data *)state->priv)->arena)
00064 #define NEXT_METH(state)  (((struct priv_data *)state->priv)->next_method)
00065 #define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const)
00066 #define NEXT_TYPE(state)  (((struct priv_data *)state->priv)->next_type)
00067 
00068 #ifdef DEBUG_shaver
00069 /* #define DEBUG_shaver_sort */
00070 #endif
00071 
00072 typedef struct {
00073     char     *full_name;
00074     char     *name;
00075     char     *name_space;
00076     char     *iid;
00077     gboolean is_forward_dcl;
00078 } NewInterfaceHolder;
00079 
00080 static NewInterfaceHolder*
00081 CreateNewInterfaceHolder(char *name, char *name_space, char *iid, 
00082                          gboolean is_forward_dcl)
00083 {
00084     NewInterfaceHolder *holder = calloc(1, sizeof(NewInterfaceHolder));
00085     if (holder) {
00086         holder->is_forward_dcl = is_forward_dcl;
00087         if (name)
00088             holder->name = xpidl_strdup(name);
00089         if (name_space)
00090             holder->name_space = xpidl_strdup(name_space);
00091         if (holder->name && holder->name_space) {
00092             holder->full_name = calloc(1, strlen(holder->name) +
00093                                           strlen(holder->name_space) + 2);
00094         }
00095         if (holder->full_name) {
00096             strcpy(holder->full_name, holder->name_space);
00097             strcat(holder->full_name, ".");
00098             strcat(holder->full_name, holder->name);
00099         }
00100         else
00101             holder->full_name = holder->name;
00102         if (iid)
00103             holder->iid = xpidl_strdup(iid);
00104     }
00105     return holder;
00106 }
00107 
00108 static void
00109 DeleteNewInterfaceHolder(NewInterfaceHolder *holder)
00110 {
00111     if (holder) {
00112         if (holder->full_name && holder->full_name != holder->name)
00113             free(holder->full_name);
00114         if (holder->name)
00115             free(holder->name);
00116         if (holder->name_space)
00117             free(holder->name_space);
00118         if (holder->iid)
00119             free(holder->iid);
00120         free(holder);
00121     }
00122 }
00123 
00124 /*
00125  * If p is an ident for an interface, and we don't have an entry in the
00126  * interface map yet, add one.
00127  */
00128 static gboolean
00129 add_interface_maybe(IDL_tree_func_data *tfd, gpointer user_data)
00130 {
00131     TreeState *state = user_data;
00132     IDL_tree up;
00133     if (IDL_NODE_TYPE(tfd->tree) == IDLN_IDENT) {
00134         IDL_tree_type node_type = IDL_NODE_TYPE((up = IDL_NODE_UP(tfd->tree)));
00135         if (node_type == IDLN_INTERFACE || node_type == IDLN_FORWARD_DCL) {
00136 
00137             /* We only want to add a new entry if there is no entry by this 
00138              * name or if the previously found entry was just a forward 
00139              * declaration and the new entry is not.
00140              */
00141 
00142             char *iface = IDL_IDENT(tfd->tree).str;
00143             NewInterfaceHolder *old_holder = (NewInterfaceHolder *) 
00144                     g_hash_table_lookup(IFACE_MAP(state), iface);
00145             if (old_holder && old_holder->is_forward_dcl &&
00146                 node_type != IDLN_FORWARD_DCL)
00147             {
00148                 g_hash_table_remove(IFACE_MAP(state), iface);
00149                 DeleteNewInterfaceHolder(old_holder);
00150                 old_holder = NULL;
00151             }
00152             if (!old_holder) {
00153                 /* XXX should we parse here and store a struct nsID *? */
00154                 char *iid = (char *)IDL_tree_property_get(tfd->tree, "uuid");
00155                 char *name_space = (char *)
00156                             IDL_tree_property_get(tfd->tree, "namespace");
00157                 NewInterfaceHolder *holder =
00158                         CreateNewInterfaceHolder(iface, name_space, iid,
00159                                      (gboolean) node_type == IDLN_FORWARD_DCL);
00160                 if (!holder)
00161                     return FALSE;
00162                 g_hash_table_insert(IFACE_MAP(state),
00163                                     holder->full_name, holder);
00164                 IFACES(state)++;
00165 #ifdef DEBUG_shaver_ifaces
00166                 fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
00167                         iface, iid[0] ? iid : "<unresolved>");
00168 #endif
00169             }
00170         } else {
00171 #ifdef DEBUG_shaver_ifaces
00172             fprintf(stderr, "ident %s isn't an interface (%s)\n",
00173                     IDL_IDENT(tfd->tree).str, IDL_NODE_TYPE_NAME(up));
00174 #endif
00175         }
00176     }
00177 
00178     return TRUE;
00179 }
00180 
00181 /* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
00182 static gboolean
00183 find_interfaces(IDL_tree_func_data *tfd, gpointer user_data)
00184 {
00185     IDL_tree node = NULL;
00186 
00187     switch (IDL_NODE_TYPE(tfd->tree)) {
00188       case IDLN_ATTR_DCL:
00189         node = IDL_ATTR_DCL(tfd->tree).param_type_spec;
00190         break;
00191       case IDLN_OP_DCL:
00192          IDL_tree_walk_in_order(IDL_OP_DCL(tfd->tree).parameter_dcls, find_interfaces,
00193                                user_data);
00194         node = IDL_OP_DCL(tfd->tree).op_type_spec;
00195         break;
00196       case IDLN_PARAM_DCL:
00197         node = IDL_PARAM_DCL(tfd->tree).param_type_spec;
00198         break;
00199       case IDLN_INTERFACE:
00200         node = IDL_INTERFACE(tfd->tree).inheritance_spec;
00201         if (node)
00202             xpidl_list_foreach(node, add_interface_maybe, user_data);
00203         node = IDL_INTERFACE(tfd->tree).ident;
00204         break;
00205       case IDLN_FORWARD_DCL:
00206         node = IDL_FORWARD_DCL(tfd->tree).ident;
00207         break;
00208       default:
00209         node = NULL;
00210     }
00211 
00212     if (node && IDL_NODE_TYPE(node) == IDLN_IDENT) {
00213         IDL_tree_func_data new_tfd;
00214         new_tfd.tree = node;
00215         add_interface_maybe(&new_tfd, user_data);
00216     }
00217 
00218     return TRUE;
00219 }
00220 
00221 #ifdef DEBUG_shaver
00222 /* for calling from gdb */
00223 static void
00224 print_IID(struct nsID *iid, FILE *file)
00225 {
00226     char iid_buf[UUID_LENGTH];
00227 
00228     xpidl_sprint_iid(iid, iid_buf);
00229     fprintf(file, "%s\n", iid_buf);
00230 }
00231 #endif
00232 
00233 /* fill the interface_directory IDE table from the interface_map */
00234 static gboolean
00235 fill_ide_table(gpointer key, gpointer value, gpointer user_data)
00236 {
00237     TreeState *state = user_data;
00238     NewInterfaceHolder *holder = (NewInterfaceHolder *) value;
00239     struct nsID id;
00240     XPTInterfaceDirectoryEntry *ide;
00241 
00242     XPT_ASSERT(holder);
00243 
00244 #ifdef DEBUG_shaver_ifaces
00245     fprintf(stderr, "filling %s\n", holder->full_name);
00246 #endif
00247 
00248     if (holder->iid) {
00249         if (strlen(holder->iid) != 36) {
00250             IDL_tree_error(state->tree, "IID %s is the wrong length\n",
00251                            holder->iid);
00252             return FALSE;
00253         }
00254         if (!xpidl_parse_iid(&id, holder->iid)) {
00255             IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid);
00256             return FALSE;
00257         }
00258     } else {
00259         memset(&id, 0, sizeof(id));
00260     }
00261 
00262     ide = &(HEADER(state)->interface_directory[IFACES(state)]);
00263     if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name,
00264                                          holder->name_space, NULL)) {
00265         IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n",
00266                        holder->full_name);
00267         return FALSE;
00268     }
00269 
00270     IFACES(state)++;
00271     DeleteNewInterfaceHolder(holder);
00272     return TRUE;
00273 }
00274 
00275 static int
00276 compare_IDEs(const void *ap, const void *bp)
00277 {
00278     const XPTInterfaceDirectoryEntry *a = ap, *b = bp;
00279     const nsID *aid = &a->iid, *bid = &b->iid;
00280     const char *ans, *bns;
00281 
00282     int i;
00283 #define COMPARE(field) if (aid->field > bid->field) return 1; \
00284                        if (bid->field > aid->field) return -1;
00285     COMPARE(m0);
00286     COMPARE(m1);
00287     COMPARE(m2);
00288     for (i = 0; i < 8; i++) {
00289         COMPARE(m3[i]);
00290     }
00291 
00292     /* defend against NULL name_space by using empty string. */
00293     ans = a->name_space ? a->name_space : "";
00294     bns = b->name_space ? b->name_space : "";
00295 
00296     if (a->name_space && b->name_space) {
00297         if ((i = strcmp(a->name_space, b->name_space)))
00298             return i;
00299     } else {
00300         if (a->name_space || b->name_space) {
00301             if (a->name_space)
00302                 return -1;
00303             return 1;
00304         }
00305     }
00306     /* these had better not be NULL... */
00307     return strcmp(a->name, b->name);
00308 #undef COMPARE
00309 }
00310 
00311 /* sort the IDE block as per the typelib spec: IID order, unresolved first */
00312 static void
00313 sort_ide_block(TreeState *state)
00314 {
00315     XPTInterfaceDirectoryEntry *ide;
00316     int i;
00317 
00318     /* boy, I sure hope qsort works correctly everywhere */
00319 #ifdef DEBUG_shaver_sort
00320     fputs("before sort:\n", stderr);
00321     for (i = 0; i < IFACES(state); i++) {
00322         fputs("  ", stderr);
00323         print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
00324         fputc('\n', stderr);
00325     }
00326 #endif
00327     qsort(HEADER(state)->interface_directory, IFACES(state),
00328           sizeof(*ide), compare_IDEs);
00329 #ifdef DEBUG_shaver_sort
00330     fputs("after sort:\n", stderr);
00331     for (i = 0; i < IFACES(state); i++) {
00332         fputs("  ", stderr);
00333         print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
00334         fputc('\n', stderr);
00335     }
00336 #endif
00337 
00338     for (i = 0; i < IFACES(state); i++) {
00339         ide = HEADER(state)->interface_directory + i;
00340         g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
00341     }
00342 
00343     return;
00344 }
00345 
00346 static gboolean
00347 typelib_list(TreeState *state)
00348 {
00349     IDL_tree iter;
00350     for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
00351         state->tree = IDL_LIST(iter).data;
00352         if (!xpidl_process_node(state))
00353             return FALSE;
00354     }
00355     return TRUE;
00356 }
00357 
00358 static gboolean
00359 typelib_prolog(TreeState *state)
00360 {
00361     state->priv = calloc(1, sizeof(struct priv_data));
00362     if (!state->priv)
00363         return FALSE;
00364     IFACES(state) = 0;
00365     IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
00366     if (!IFACE_MAP(state)) {
00367         /* XXX report error */
00368         free(state->priv);
00369         return FALSE;
00370     }
00371     /* find all interfaces, top-level and referenced by others */
00372     IDL_tree_walk_in_order(state->tree, find_interfaces, state);
00373     ARENA(state) = XPT_NewArena(1024, sizeof(double), "main xpidl arena");
00374     HEADER(state) = XPT_NewHeader(ARENA(state), IFACES(state), 
00375                                   major_version, minor_version);
00376 
00377     /* fill IDEs from hash table */
00378     IFACES(state) = 0;
00379     g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
00380 
00381     /* if any are left then we must have failed in fill_ide_table */
00382     if (g_hash_table_size(IFACE_MAP(state)))
00383         return FALSE;
00384 
00385     /* sort the IDEs by IID order and store indices in the interface map */
00386     sort_ide_block(state);
00387 
00388     return TRUE;
00389 }
00390 
00391 static gboolean
00392 typelib_epilog(TreeState *state)
00393 {
00394     XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
00395     XPTCursor curs, *cursor = &curs;
00396     PRUint32 i, len, header_sz;
00397     PRUint32 oldOffset;
00398     PRUint32 newOffset;
00399     char *data;
00400 
00401     /* Write any annotations */
00402     if (emit_typelib_annotations) {
00403         PRUint32 annotation_len, written_so_far;
00404         char *annotate_val, *timestr;
00405         time_t now;
00406         static char *annotation_format = 
00407             "Created from %s.idl\nCreation date: %sInterfaces:";
00408 
00409         /* fill in the annotations, listing resolved interfaces in order */
00410 
00411         (void)time(&now);
00412         timestr = ctime(&now);
00413 
00414         /* Avoid dependence on nspr; no PR_smprintf and friends. */
00415 
00416         /* How large should the annotation string be? */
00417         annotation_len = strlen(annotation_format) + strlen(state->basename) +
00418             strlen(timestr);
00419         for (i = 0; i < HEADER(state)->num_interfaces; i++) {
00420             XPTInterfaceDirectoryEntry *ide;
00421             ide = &HEADER(state)->interface_directory[i];
00422             if (ide->interface_descriptor) {
00423                 annotation_len += strlen(ide->name) + 1;
00424             }
00425         }
00426 
00427         annotate_val = (char *) malloc(annotation_len);
00428         written_so_far = sprintf(annotate_val, annotation_format,
00429                                  state->basename, timestr);
00430         
00431         for (i = 0; i < HEADER(state)->num_interfaces; i++) {
00432             XPTInterfaceDirectoryEntry *ide;
00433             ide = &HEADER(state)->interface_directory[i];
00434             if (ide->interface_descriptor) {
00435                 written_so_far += sprintf(annotate_val + written_so_far, " %s",
00436                                           ide->name);
00437             }
00438         }
00439 
00440         HEADER(state)->annotations =
00441             XPT_NewAnnotation(ARENA(state), 
00442                               XPT_ANN_LAST | XPT_ANN_PRIVATE,
00443                               XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"),
00444                               XPT_NewStringZ(ARENA(state), annotate_val));
00445         free(annotate_val);
00446     } else {
00447         HEADER(state)->annotations =
00448             XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL);
00449     }
00450 
00451     if (!HEADER(state)->annotations) {
00452         /* XXX report out of memory error */
00453         return FALSE;
00454     }
00455 
00456     /* Write the typelib */
00457     header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
00458 
00459     if (!xstate ||
00460         !XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
00461         goto destroy_header;
00462     oldOffset = cursor->offset;
00463     if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state)))
00464         goto destroy;
00465     newOffset = cursor->offset;
00466     XPT_GetXDRDataLength(xstate, XPT_HEADER, &len);
00467     HEADER(state)->file_length = len;
00468     XPT_GetXDRDataLength(xstate, XPT_DATA, &len);
00469     HEADER(state)->file_length += len;
00470     XPT_SeekTo(cursor, oldOffset);
00471     if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL))
00472         goto destroy;
00473     XPT_SeekTo(cursor, newOffset);
00474     XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
00475     fwrite(data, len, 1, state->file);
00476     XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
00477     fwrite(data, len, 1, state->file);
00478 
00479  destroy:
00480     XPT_DestroyXDRState(xstate);
00481  destroy_header:
00482     /* XXX XPT_DestroyHeader(HEADER(state)) */
00483 
00484     XPT_FreeHeader(ARENA(state), HEADER(state));
00485     XPT_DestroyArena(ARENA(state));
00486 
00487     /* XXX should destroy priv_data here */
00488 
00489     return TRUE;
00490 }
00491 
00492 static XPTInterfaceDirectoryEntry *
00493 FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
00494                     const char *name)
00495 {
00496     uint16 i;
00497     for (i = 0; i < num_interfaces; i++) {
00498         if (!strcmp(ides[i].name, name))
00499             return &ides[i];
00500     }
00501     return NULL;
00502 }
00503 
00504 static gboolean
00505 typelib_interface(TreeState *state)
00506 {
00507     IDL_tree iface = state->tree, iter;
00508     char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
00509     XPTInterfaceDirectoryEntry *ide;
00510     XPTInterfaceDescriptor *id;
00511     uint16 parent_id = 0;
00512     PRUint8 interface_flags = 0;
00513 
00514     if (!verify_interface_declaration(iface))
00515         return FALSE;
00516 
00517     if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
00518         interface_flags |= XPT_ID_SCRIPTABLE;
00519 
00520     if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function"))
00521         interface_flags |= XPT_ID_FUNCTION;
00522 
00523     ide = FindInterfaceByName(HEADER(state)->interface_directory,
00524                               HEADER(state)->num_interfaces, name);
00525     if (!ide) {
00526         IDL_tree_error(iface, "ERROR: didn't find interface %s in "
00527                        "IDE block. Giving up.\n", name);
00528         return FALSE;
00529     }
00530 
00531     if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
00532         char *parent;
00533         if (IDL_LIST(iter).next) {
00534             IDL_tree_error(iface,
00535                            "ERROR: more than one parent interface for %s\n",
00536                            name);
00537             return FALSE;
00538         }
00539         parent = IDL_IDENT(IDL_LIST(iter).data).str;
00540         parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
00541                                                         parent);
00542         if (!parent_id) {
00543             IDL_tree_error(iface,
00544                            "ERROR: no index found for %s. Giving up.\n",
00545                            parent);
00546             return FALSE;
00547         }
00548     }
00549 
00550     id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0, 
00551                                     interface_flags);
00552     if (!id)
00553         return FALSE;
00554 
00555     CURRENT(state) = ide->interface_descriptor = id;
00556 #ifdef DEBUG_shaver_ifaces
00557     fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id);
00558 #endif
00559 
00560     NEXT_METH(state) = 0;
00561     NEXT_CONST(state) = 0;
00562     NEXT_TYPE(state) = 0;
00563 
00564     state->tree = IDL_INTERFACE(iface).body;
00565     if (state->tree && !xpidl_process_node(state))
00566         return FALSE;
00567 #ifdef DEBUG_shaver_ifaces
00568     fprintf(stderr, "DBG: ending interface %s\n", name);
00569 #endif
00570     return TRUE;
00571 }
00572 
00573 static gboolean
00574 find_arg_with_name(TreeState *state, const char *name, int16 *argnum)
00575 {
00576     int16 count;
00577     IDL_tree params;
00578 
00579     XPT_ASSERT(state);
00580     XPT_ASSERT(name);
00581     XPT_ASSERT(argnum);
00582 
00583     params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
00584     for (count = 0;
00585          params != NULL && IDL_LIST(params).data != NULL;
00586          params = IDL_LIST(params).next, count++)
00587     {
00588         const char *cur_name = IDL_IDENT(
00589                 IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
00590         if (!strcmp(cur_name, name)) {
00591             /* XXX ought to verify that this is the right type here */
00592             /* XXX for iid_is this must be an iid */
00593             /* XXX for size_is and length_is this must be a uint32 */
00594             *argnum = count;
00595             return TRUE;
00596         }
00597     }
00598     return FALSE;
00599 }
00600 
00601 /* return value is for success or failure */
00602 static gboolean
00603 get_size_and_length(TreeState *state, IDL_tree type, 
00604                     int16 *size_is_argnum, int16 *length_is_argnum,
00605                     gboolean *has_size_is, gboolean *has_length_is)
00606 {
00607     *has_size_is = FALSE;
00608     *has_length_is = FALSE;
00609 
00610     if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
00611         IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
00612         const char *size_is;
00613         const char *length_is;
00614 
00615         /* only if size_is is found does any of this matter */
00616         size_is = IDL_tree_property_get(sd, "size_is");
00617         if (!size_is)
00618             return TRUE;
00619 
00620         if (!find_arg_with_name(state, size_is, size_is_argnum)) {
00621             IDL_tree_error(state->tree, "can't find matching argument for "
00622                            "[size_is(%s)]\n", size_is);
00623             return FALSE;
00624         }
00625         *has_size_is = TRUE;
00626 
00627         /* length_is is optional */
00628         length_is = IDL_tree_property_get(sd, "length_is");
00629         if (length_is) {
00630             *has_length_is = TRUE;
00631             if (!find_arg_with_name(state, length_is, length_is_argnum)) {
00632                 IDL_tree_error(state->tree, "can't find matching argument for "
00633                                "[length_is(%s)]\n", length_is);
00634                 return FALSE;
00635             }
00636         }
00637     }
00638     return TRUE;
00639 }
00640 
00641 static gboolean
00642 fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type)
00643 {
00644     IDL_tree up;
00645     int16 size_is_argnum;
00646     int16 length_is_argnum;
00647     gboolean has_size_is;
00648     gboolean has_length_is;
00649     gboolean is_array = FALSE;
00650 
00651     if (type) {
00652 
00653         /* deal with array */
00654 
00655         if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
00656             IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
00657             if (IDL_tree_property_get(sd, "array")) {
00658 
00659                 is_array = TRUE;
00660 
00661                 /* size_is is required! */
00662                 if (!get_size_and_length(state, type, 
00663                                          &size_is_argnum, &length_is_argnum,
00664                                          &has_size_is, &has_length_is)) {
00665                     /* error was reported by helper function */
00666                     return FALSE;
00667                 }
00668 
00669                 if (!has_size_is) {
00670                    IDL_tree_error(state->tree, "[array] requires [size_is()]\n");
00671                     return FALSE;
00672                 }
00673 
00674                 td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
00675                 td->argnum = size_is_argnum;
00676 
00677                 if (has_length_is)
00678                     td->argnum2 = length_is_argnum;
00679                 else
00680                     td->argnum2 = size_is_argnum;
00681 
00682                 /* 
00683                 * XXX - NOTE - this will be broken for multidimensional 
00684                 * arrays because of the realloc XPT_InterfaceDescriptorAddTypes
00685                 * uses. The underlying 'td' can change as we recurse in to get
00686                 * additional dimensions. Luckily, we don't yet support more
00687                 * than on dimension in the arrays
00688                 */
00689                 /* setup the additional_type */                
00690                 if (!XPT_InterfaceDescriptorAddTypes(ARENA(state), 
00691                                                      CURRENT(state), 1)) {
00692                     g_error("out of memory\n");
00693                     return FALSE;
00694                 }
00695                 td->type.additional_type = NEXT_TYPE(state);
00696                 td = &CURRENT(state)->additional_types[NEXT_TYPE(state)];
00697                 NEXT_TYPE(state)++ ;
00698             }
00699         }
00700 
00701 handle_typedef:
00702         switch (IDL_NODE_TYPE(type)) {
00703           case IDLN_TYPE_INTEGER: {
00704               gboolean sign = IDL_TYPE_INTEGER(type).f_signed;
00705               switch(IDL_TYPE_INTEGER(type).f_type) {
00706                 case IDL_INTEGER_TYPE_SHORT:
00707                   td->prefix.flags = sign ? TD_INT16 : TD_UINT16;
00708                   break;
00709                 case IDL_INTEGER_TYPE_LONG:
00710                   td->prefix.flags = sign ? TD_INT32 : TD_UINT32;
00711                   break;
00712                 case IDL_INTEGER_TYPE_LONGLONG:
00713                   td->prefix.flags = sign ? TD_INT64 : TD_UINT64;
00714                   break;
00715               }
00716               break;
00717           }
00718           case IDLN_TYPE_CHAR:
00719             td->prefix.flags = TD_CHAR;
00720             break;
00721           case IDLN_TYPE_WIDE_CHAR:
00722             td->prefix.flags = TD_WCHAR;
00723             break;
00724           case IDLN_TYPE_STRING:
00725             if (is_array) {
00726                 td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
00727             } else {
00728                 if (!get_size_and_length(state, type, 
00729                                          &size_is_argnum, &length_is_argnum,
00730                                          &has_size_is, &has_length_is)) {
00731                     /* error was reported by helper function */
00732                     return FALSE;
00733                 }
00734                 if (has_size_is) {
00735                     td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER;
00736                     td->argnum = size_is_argnum;
00737                     if (has_length_is)
00738                         td->argnum2 = length_is_argnum;
00739                     else
00740                         td->argnum2 = size_is_argnum;
00741                 } else {
00742                     td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
00743                 }
00744             }
00745             break;
00746           case IDLN_TYPE_WIDE_STRING:
00747             if (is_array) {
00748                 td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
00749             } else {
00750                 if (!get_size_and_length(state, type, 
00751                                          &size_is_argnum, &length_is_argnum,
00752                                          &has_size_is, &has_length_is)) {
00753                     /* error was reported by helper function */
00754                     return FALSE;
00755                 }
00756                 if (has_size_is) {
00757                     td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER;
00758                     td->argnum = size_is_argnum;
00759                     if (has_length_is)
00760                         td->argnum2 = length_is_argnum;
00761                     else
00762                         td->argnum2 = size_is_argnum;
00763                 } else {
00764                     td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
00765                 }
00766             }
00767             break;
00768           case IDLN_TYPE_BOOLEAN:
00769             td->prefix.flags = TD_BOOL;
00770             break;
00771           case IDLN_TYPE_OCTET:
00772             td->prefix.flags = TD_UINT8;
00773             break;
00774           case IDLN_TYPE_FLOAT:
00775             switch (IDL_TYPE_FLOAT (type).f_type) {
00776               case IDL_FLOAT_TYPE_FLOAT:
00777                 td->prefix.flags = TD_FLOAT;
00778                 break;
00779               case IDL_FLOAT_TYPE_DOUBLE:
00780                 td->prefix.flags = TD_DOUBLE;
00781                 break;
00782               /* XXX 'long double' just ignored, or what? */
00783               default: break;
00784             }
00785             break;
00786           case IDLN_IDENT:
00787             if (!(up = IDL_NODE_UP(type))) {
00788                 IDL_tree_error(state->tree,
00789                                "ERROR: orphan ident %s in param list\n",
00790                                IDL_IDENT(type).str);
00791                 return FALSE;
00792             }
00793             switch (IDL_NODE_TYPE(up)) {
00794                 /* This whole section is abominably ugly */
00795               case IDLN_FORWARD_DCL:
00796               case IDLN_INTERFACE: {
00797                 XPTInterfaceDirectoryEntry *ide, *ides;
00798                 uint16 num_ifaces;
00799                 char *className;
00800                 const char *iid_is;
00801 handle_iid_is:
00802                 ides = HEADER(state)->interface_directory;
00803                 num_ifaces = HEADER(state)->num_interfaces;
00804                 /* might get here via the goto, so re-check type */
00805                 if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
00806                     className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
00807                 else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
00808                     className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
00809                 else
00810                     className = IDL_IDENT(IDL_NATIVE(up).ident).str;
00811                 iid_is = NULL;
00812 
00813                 if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
00814                     iid_is =
00815                         IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
00816                                               "iid_is");
00817                 }
00818                 if (iid_is) {
00819                     int16 argnum;
00820                     if (!find_arg_with_name(state, iid_is, &argnum)) {
00821                         IDL_tree_error(state->tree,
00822                                        "can't find matching argument for "
00823                                        "[iid_is(%s)]\n", iid_is);
00824                         return FALSE;
00825                     }
00826                     td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER;
00827                     td->argnum = argnum;
00828                 } else {
00829                     td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
00830                     ide = FindInterfaceByName(ides, num_ifaces, className);
00831                     if (!ide || ide < ides || ide > ides + num_ifaces) {
00832                         IDL_tree_error(state->tree,
00833                                        "unknown iface %s in param\n",
00834                                        className);
00835                         return FALSE;
00836                     }
00837                     td->type.iface = ide - ides + 1;
00838 #ifdef DEBUG_shaver_index
00839                     fprintf(stderr, "DBG: index %d for %s\n",
00840                             td->type.iface, className);
00841 #endif
00842                 }
00843                 break;
00844               }
00845               case IDLN_NATIVE: {
00846                   char *ident;
00847 
00848                   /* jband - adding goto for iid_is when type is native */
00849                   if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
00850                       IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
00851                                               "iid_is"))
00852                       goto handle_iid_is;
00853 
00854                   ident = IDL_IDENT(type).str;
00855                   if (IDL_tree_property_get(type, "nsid")) {
00856                       td->prefix.flags = TD_PNSIID;
00857                       if (IDL_tree_property_get(type, "ref"))
00858                           td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE;
00859                       else if (IDL_tree_property_get(type,"ptr"))
00860                           td->prefix.flags |= XPT_TDP_POINTER;
00861                   } else if (IDL_tree_property_get(type, "domstring")) {
00862                       td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
00863                       if (IDL_tree_property_get(type, "ref"))
00864                           td->prefix.flags |= XPT_TDP_REFERENCE;
00865                   } else if (IDL_tree_property_get(type, "astring")) {
00866                       td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER;
00867                       if (IDL_tree_property_get(type, "ref"))
00868                           td->prefix.flags |= XPT_TDP_REFERENCE;
00869                   } else if (IDL_tree_property_get(type, "utf8string")) {
00870                       td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER;
00871                       if (IDL_tree_property_get(type, "ref"))
00872                           td->prefix.flags |= XPT_TDP_REFERENCE;
00873                   } else if (IDL_tree_property_get(type, "cstring")) {
00874                       td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER;
00875                       if (IDL_tree_property_get(type, "ref"))
00876                           td->prefix.flags |= XPT_TDP_REFERENCE;
00877                   } else {
00878                       td->prefix.flags = TD_VOID | XPT_TDP_POINTER;
00879                   }
00880                   break;
00881                 }
00882               default:
00883                 if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
00884                     /* restart with the underlying type */
00885                     IDL_tree new_type;
00886                     new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
00887 #ifdef DEBUG_shaver_misc
00888                     fprintf(stderr, "following %s typedef to %s\n",
00889                             IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type));
00890 #endif
00891                     /* 
00892                     *  Do a nice messy goto rather than recursion so that
00893                     *  we can avoid screwing up the *array* information.
00894                     */
00895 /*                    return fill_td_from_type(state, td, new_type); */
00896                     if (new_type) {
00897                         type = new_type;
00898                         goto handle_typedef;
00899                     } else {
00900                         /* do what we would do in recursion if !type */
00901                         td->prefix.flags = TD_VOID;
00902                         return TRUE;
00903                     }
00904                 }
00905                 IDL_tree_error(state->tree,
00906                                "can't handle %s ident in param list\n",
00907 #ifdef DEBUG_shaver
00908                                /* XXX is this safe to use on Win now? */
00909                                IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00910 #else
00911                                "that type of"
00912 #endif
00913                                );
00914 #ifdef DEBUG_shaver
00915                 XPT_ASSERT(0);
00916 #endif
00917                 return FALSE;
00918             }
00919             break;
00920           default:
00921             IDL_tree_error(state->tree, "can't handle %s in param list\n",
00922 #ifdef DEBUG_shaver
00923                            /* XXX is this safe to use on Win now? */
00924                            IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00925 #else
00926                         "that type"
00927 #endif
00928             );
00929             return FALSE;
00930         }
00931     } else {
00932         td->prefix.flags = TD_VOID;
00933     }
00934 
00935     return TRUE;
00936 }
00937 
00938 static gboolean
00939 fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
00940                   IDL_tree type)
00941 {
00942     pd->flags = flags;
00943     return fill_td_from_type(state, &pd->type, type);
00944 }
00945 
00946 static gboolean
00947 fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
00948 {
00949     uint8 flags = 0;
00950     gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec);
00951 
00952     switch (IDL_PARAM_DCL(tree).attr) {
00953       case IDL_PARAM_IN:
00954         flags = XPT_PD_IN;
00955         break;
00956       case IDL_PARAM_OUT:
00957         flags = XPT_PD_OUT;
00958         break;
00959       case IDL_PARAM_INOUT:
00960         flags = XPT_PD_IN | XPT_PD_OUT;
00961         break;
00962     }
00963 
00964     if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
00965                               "retval")) {
00966         if (flags != XPT_PD_OUT) {
00967             IDL_tree_error(tree, "can't have [retval] with in%s param "
00968                            "(only out)\n",
00969                            flags & XPT_PD_OUT ? "out" : "");
00970             return FALSE;
00971         }
00972         flags |= XPT_PD_RETVAL;
00973     }
00974 
00975     if (is_dipper_type && (flags & XPT_PD_OUT)) {
00976         flags &= ~XPT_PD_OUT; 
00977         flags |= XPT_PD_IN | XPT_PD_DIPPER;
00978     }
00979 
00980     if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
00981                               "shared")) {
00982         if (flags & XPT_PD_IN) {
00983             IDL_tree_error(tree, "can't have [shared] with in%s param "
00984                            "(only out)\n",
00985                            flags & XPT_PD_OUT ? "out" : "");
00986             return FALSE;
00987         }
00988         flags |= XPT_PD_SHARED;
00989     }
00990 
00991     /* stick param where we can see it later */
00992     state->tree = tree;
00993     return fill_pd_from_type(state, pd, flags,
00994                              IDL_PARAM_DCL(tree).param_type_spec);
00995 }
00996 
00997 /* XXXshaver common with xpidl_header.c */
00998 #define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
00999 #define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
01000 #define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
01001 
01002 static gboolean
01003 fill_pd_as_nsresult(XPTParamDescriptor *pd)
01004 {
01005     pd->type.prefix.flags = TD_UINT32; /* TD_NSRESULT */
01006     return TRUE;
01007 }
01008 
01009 static gboolean
01010 typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth,
01011                       gboolean getter, gboolean hidden)
01012 {
01013     uint8 methflags = 0;
01014     uint8 pdflags = 0;
01015 
01016     methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER;
01017     methflags |= hidden ? XPT_MD_HIDDEN : 0;
01018     if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags,
01019                                   ATTR_IDENT(state->tree).str, 1))
01020         return FALSE;
01021 
01022     if (getter) {
01023         if (DIPPER_TYPE(ATTR_TYPE_DECL(state->tree))) {
01024             pdflags |= (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER);
01025         } else {
01026             pdflags |= (XPT_PD_RETVAL | XPT_PD_OUT);
01027         }
01028     } else {
01029         pdflags |= XPT_PD_IN;
01030     }
01031 
01032     if (!fill_pd_from_type(state, meth->params, pdflags,
01033                            ATTR_TYPE_DECL(state->tree)))
01034         return FALSE;
01035 
01036     fill_pd_as_nsresult(meth->result);
01037     NEXT_METH(state)++;
01038     return TRUE;
01039 }
01040 
01041 static gboolean
01042 typelib_attr_dcl(TreeState *state)
01043 {
01044     XPTInterfaceDescriptor *id = CURRENT(state);
01045     XPTMethodDescriptor *meth;
01046     gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
01047 
01048     /* XXX this only handles the first ident; elsewhere too... */
01049     IDL_tree ident =
01050         IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).data;
01051 
01052     /* If it's marked [noscript], mark it as hidden in the typelib. */
01053     gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL);
01054 
01055     if (!verify_attribute_declaration(state->tree))
01056         return FALSE;
01057 
01058     if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 
01059                                            (PRUint16) (read_only ? 1 : 2)))
01060         return FALSE;
01061 
01062     meth = &id->method_descriptors[NEXT_METH(state)];
01063 
01064     return typelib_attr_accessor(state, meth, TRUE, hidden) &&
01065         (read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden));
01066 }
01067 
01068 static gboolean
01069 typelib_op_dcl(TreeState *state)
01070 {
01071     XPTInterfaceDescriptor *id = CURRENT(state);
01072     XPTMethodDescriptor *meth;
01073     struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
01074     IDL_tree iter;
01075     uint16 num_args = 0;
01076     uint8 op_flags = 0;
01077     gboolean op_notxpcom = (IDL_tree_property_get(op->ident, "notxpcom")
01078                             != NULL);
01079     gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
01080                             != NULL);
01081 
01082     if (!verify_method_declaration(state->tree))
01083         return FALSE;
01084 
01085     if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 1))
01086         return FALSE;
01087 
01088     meth = &id->method_descriptors[NEXT_METH(state)];
01089 
01090     for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
01091         num_args++;             /* count params */
01092     if (op->op_type_spec && !op_notxpcom)
01093         num_args++;             /* fake param for _retval */
01094 
01095     if (op_noscript)
01096         op_flags |= XPT_MD_HIDDEN;
01097     if (op_notxpcom)
01098         op_flags |= XPT_MD_NOTXPCOM;
01099 
01100     /* XXXshaver constructor? */
01101 
01102 #ifdef DEBUG_shaver_method
01103     fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
01104             IDL_IDENT(op->ident).str, num_args);
01105 #endif
01106     if (!XPT_FillMethodDescriptor(ARENA(state), meth, op_flags, 
01107                                   IDL_IDENT(op->ident).str,
01108                                   (uint8) num_args))
01109         return FALSE;
01110 
01111     for (num_args = 0, iter = op->parameter_dcls; iter;
01112          iter = IDL_LIST(iter).next, num_args++) {
01113         XPTParamDescriptor *pd = &meth->params[num_args];
01114         if (!fill_pd_from_param(state, pd, IDL_LIST(iter).data))
01115             return FALSE;
01116     }
01117 
01118     /* stick retval param where we can see it later */
01119     state->tree = op->op_type_spec;
01120 
01121     /* XXX unless [notxpcom] */
01122     if (!op_notxpcom) {
01123         if (op->op_type_spec) {
01124             uint8 pdflags = DIPPER_TYPE(op->op_type_spec) ?
01125                                 (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER) :
01126                                 (XPT_PD_RETVAL | XPT_PD_OUT);
01127     
01128             if (!fill_pd_from_type(state, &meth->params[num_args],
01129                                    pdflags, op->op_type_spec))
01130                 return FALSE;
01131         }
01132 
01133         if (!fill_pd_as_nsresult(meth->result))
01134             return FALSE;
01135     } else {
01136 #ifdef DEBUG_shaver_notxpcom
01137         fprintf(stderr, "%s is notxpcom\n", IDL_IDENT(op->ident).str);
01138 #endif
01139         if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
01140                                op->op_type_spec))
01141             return FALSE;
01142     }
01143     NEXT_METH(state)++;
01144     return TRUE;
01145 }
01146 
01147 static gboolean
01148 typelib_const_dcl(TreeState *state)
01149 {
01150     struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
01151     const char *name = IDL_IDENT(dcl->ident).str;
01152     gboolean is_long;
01153     gboolean sign;
01154     IDL_tree real_type;
01155     XPTInterfaceDescriptor *id;
01156     XPTConstDescriptor *cd;
01157     IDL_longlong_t value;
01158 
01159     if (!verify_const_declaration(state->tree))
01160         return FALSE;
01161 
01162     /* Could be a typedef; try to map it to the real type. */
01163     real_type = find_underlying_type(dcl->const_type);
01164     real_type = real_type ? real_type : dcl->const_type;
01165     is_long = (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG);
01166 
01167     id = CURRENT(state);
01168     if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1))
01169         return FALSE;
01170     cd = &id->const_descriptors[NEXT_CONST(state)];
01171     
01172     cd->name = IDL_IDENT(dcl->ident).str;
01173 #ifdef DEBUG_shaver_const
01174     fprintf(stderr, "DBG: adding const %s\n", cd->name);
01175 #endif
01176     if (!fill_td_from_type(state, &cd->type, dcl->const_type))
01177         return FALSE;
01178     
01179     value = IDL_INTEGER(dcl->const_exp).value;
01180     sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
01181     if (is_long) {
01182         if (sign)
01183             cd->value.i32 = value;
01184         else
01185             cd->value.ui32 = value;
01186     } else {
01187         if (sign)
01188             cd->value.i16 = value;
01189         else
01190             cd->value.ui16 = value;
01191     }
01192     NEXT_CONST(state)++;
01193     return TRUE;
01194 }
01195 
01196 static gboolean
01197 typelib_enum(TreeState *state)
01198 {
01199     XPIDL_WARNING((state->tree, IDL_WARNING1,
01200                    "enums not supported, enum \'%s\' ignored",
01201                    IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
01202     return TRUE;
01203 }
01204 
01205 backend *
01206 xpidl_typelib_dispatch(void)
01207 {
01208     static backend result;
01209     static nodeHandler table[IDLN_LAST];
01210     static gboolean initialized = FALSE;
01211 
01212     result.emit_prolog = typelib_prolog;
01213     result.emit_epilog = typelib_epilog;
01214 
01215     if (!initialized) {
01216         /* Initialize non-NULL elements */
01217         table[IDLN_LIST] = typelib_list;
01218         table[IDLN_ATTR_DCL] = typelib_attr_dcl;
01219         table[IDLN_OP_DCL] = typelib_op_dcl;
01220         table[IDLN_INTERFACE] = typelib_interface;
01221         table[IDLN_CONST_DCL] = typelib_const_dcl;
01222         table[IDLN_TYPE_ENUM] = typelib_enum;
01223         table[IDLN_NATIVE] = check_native;
01224         initialized = TRUE;
01225     }
01226 
01227     result.dispatch_table = table;
01228     return &result;
01229 }
01230 
01231 
01232