VirtualBox

Changeset 108305 in vbox


Ignore:
Timestamp:
Feb 20, 2025 8:09:36 AM (2 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167649
Message:

libs/xpcom18a4/xpcom/xpidl-new: Write header files for parsed IDL files, bugref:10321

Location:
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl.h

    r108304 r108305  
    7979    /** Node for the list of inputs. */
    8080    RTLISTNODE          NdInput;
     81    /** Node for the list of include. */
     82    RTLISTNODE          NdInclude;
    8183    /** The list of includes this input generated. */
    8284    RTLISTANCHOR        LstIncludes;
     
    109111    kXpidlNdType_Attribute,
    110112    kXpidlNdType_Method,
    111     kXpidlNdType_Parameter
     113    kXpidlNdType_Parameter,
     114    kXpidlNdType_Const
    112115} XPIDLNDTYPE;
    113116
     
    119122{
    120123    kXpidlType_Invalid = 0,
     124    kXpidlType_Void,
    121125    kXpidlType_Boolean,
    122126    kXpidlType_Octet,
     
    227231            XPIDLDIRECTION enmDir;
    228232        } Param;
     233        struct
     234        {
     235            PCXPIDLNODE pNdTypeSpec;
     236            const char  *pszName;
     237            uint64_t    u64Const; /* Only allowing numbers for now. */
     238        } Const;
    229239    } u;
    230240    /** Number of entries in the attribute array. */
     
    269279extern PRUint8  minor_version;
    270280
    271 typedef struct TreeState TreeState;
    272 
    273 /*
    274  * A function to handle an IDL_tree type.
    275  */
    276 typedef bool (*nodeHandler)(TreeState *);
    277 
    278 /*
    279  * Struct containing functions to define the behavior of a given output mode.
    280  */
    281 typedef struct backend {
    282     nodeHandler *dispatch_table; /* nodeHandlers table, indexed by node type. */
    283     nodeHandler emit_prolog;     /* called at beginning of output generation. */
    284     nodeHandler emit_epilog;     /* called at end. */
    285 } backend;
    286 
    287 /* Function that produces a struct of output-generation functions */
    288 typedef backend *(*backendFactory)();
    289 
    290 extern backend *xpidl_header_dispatch(void);
    291 extern backend *xpidl_typelib_dispatch(void);
     281
     282/**
     283 * Dispatch callback.
     284 *
     285 * @returns IPRT status code.
     286 * @param   pFile       The file to output to.
     287 * @param   pInput      The original input file to generate for.
     288 * @param   pParse      The parsing state.
     289 */
     290typedef DECLCALLBACKTYPE(int, FNXPIDLDISPATCH,(FILE *pFile, PCXPIDLINPUT pInput, PCXPIDLPARSE pParse));
     291/** Pointer to a dispatch callback. */
     292typedef FNXPIDLDISPATCH *PFNXPIDLDISPATCH;
     293
     294
     295DECL_HIDDEN_CALLBACK(int) xpidl_header_dispatch(FILE *pFile, PCXPIDLINPUT pInput, PCXPIDLPARSE pParse);
     296DECL_HIDDEN_CALLBACK(int) xpidl_typelib_dispatch(FILE *pFile, PCXPIDLINPUT pInput, PCXPIDLPARSE pParse);
    292297
    293298typedef struct ModeData {
     
    295300    char               *modeInfo;
    296301    char               *suffix;
    297     backendFactory     factory;
     302    PFNXPIDLDISPATCH    dispatch;
    298303} ModeData;
    299304
    300 
    301 struct TreeState {
    302     FILE             *file;
    303     /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */
    304     char             *basename;
    305     RTLISTANCHOR     *base_includes;
    306     nodeHandler      *dispatch;
    307     void             *priv;     /* mode-private data */
    308 };
    309305
    310306/*
     
    332328xpidl_basename(const char * path);
    333329
    334 /*
    335  * Process an XPIDL node and its kids, if any.
    336  */
    337 bool
    338 xpidl_process_node(TreeState *state);
    339 
    340 /*
    341  * Write a newline folllowed by an indented, one-line comment containing IDL
    342  * source decompiled from state->tree.
    343  */
    344 void
    345 xpidl_write_comment(TreeState *state, int indent);
    346 
    347 
    348330
    349331/*
     
    371353
    372354
     355DECLHIDDEN(PCXPIDLATTR) xpidlNodeAttrFind(PCXPIDLNODE pNd, const char *pszAttr);
     356
     357
     358/* Try to common a little node-handling stuff. */
     359
     360
     361DECLINLINE(bool) xpidlNdIsStringType(PCXPIDLNODE pNd)
     362{
     363    return    pNd->enmType == kXpidlNdType_BaseType
     364           && (   pNd->u.enmBaseType == kXpidlType_String
     365               || pNd->u.enmBaseType == kXpidlType_Wide_String);
     366}
     367
     368
     369/* is this node from an aggregate type (interface)? */
     370#define UP_IS_AGGREGATE(a_pNd) \
     371    (   a_pNd->pParent \
     372     && (   a_pNd->pParent->enmType == kXpidlNdType_Interface_Forward_Decl \
     373         || a_pNd->pParent->enmType == kXpidlNdType_Interface_Def))
     374
     375#define UP_IS_NATIVE(a_pNd) \
     376    (   a_pNd->pParent \
     377     && a_pNd->pParent->enmType == kXpidlNdType_Native)
     378
     379/* is this type output in the form "<foo> *"? */
     380#define STARRED_TYPE(a_pNd) (xpidlNdIsStringType(a_pNd) ||   \
     381                            (a_pNd->enmType == kXpidlNdType_Identifier &&     \
     382                             UP_IS_AGGREGATE(a_pNd)))
     383
     384#define DIPPER_TYPE(a_pNd)                                                     \
     385    (xpidlNodeAttrFind(a_pNd, "domstring")  ||                     \
     386     xpidlNodeAttrFind(a_pNd, "utf8string") ||                     \
     387     xpidlNodeAttrFind(a_pNd, "cstring")    ||                     \
     388     xpidlNodeAttrFind(a_pNd, "astring"))
     389
     390
     391/*
     392 * Verifies the interface declaration
     393 */
     394DECLHIDDEN(bool) verify_interface_declaration(PCXPIDLNODE pNd);
     395
    373396#if 0
    374 /* Try to common a little node-handling stuff. */
    375 
    376 /* is this node from an aggregate type (interface)? */
    377 #define UP_IS_AGGREGATE(node)                                                 \
    378     (IDL_NODE_UP(node) &&                                                     \
    379      (IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_INTERFACE ||                   \
    380       IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_FORWARD_DCL))
    381 
    382 #define UP_IS_NATIVE(node)                                                    \
    383     (IDL_NODE_UP(node) &&                                                     \
    384      IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_NATIVE)
    385 
    386 /* is this type output in the form "<foo> *"? */
    387 #define STARRED_TYPE(node) (IDL_NODE_TYPE(node) == IDLN_TYPE_STRING ||        \
    388                             IDL_NODE_TYPE(node) == IDLN_TYPE_WIDE_STRING ||   \
    389                             (IDL_NODE_TYPE(node) == IDLN_IDENT &&             \
    390                              UP_IS_AGGREGATE(node)))
    391 
    392 #define DIPPER_TYPE(node)                                                     \
    393     (NULL != IDL_tree_property_get(node, "domstring")  ||                     \
    394      NULL != IDL_tree_property_get(node, "utf8string") ||                     \
    395      NULL != IDL_tree_property_get(node, "cstring")    ||                     \
    396      NULL != IDL_tree_property_get(node, "astring"))
    397 
    398397/*
    399398 * Find the underlying type of an identifier typedef.  Returns NULL
     
    421420gboolean
    422421verify_method_declaration(IDL_tree method_tree);
    423 
    424 /*
    425  * Verifies the interface declaration
    426  */
    427 gboolean
    428 verify_interface_declaration(IDL_tree method_tree);
    429422
    430423/*
  • trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_header.c

    r108284 r108305  
    3939 * Generate XPCOM headers from XPIDL.
    4040 */
     41#include <iprt/assert.h>
     42#include <iprt/path.h>
    4143
    4244#include "xpidl.h"
    4345#include <ctype.h>
    4446
    45 #define AS_DECL 0
    46 #define AS_CALL 1
    47 #define AS_IMPL 2
    48 
    49 #if 0
    50 static bool write_method_signature(IDL_tree method_tree, FILE *outfile,
    51                                        int mode, const char *className);
    52 static bool write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
    53                                     bool getter,
    54                                     int mode, const char *className);
    55 
    56 static void
    57 write_indent(FILE *outfile) {
     47static void write_indent(FILE *outfile)
     48{
    5849    fputs("  ", outfile);
    5950}
    6051
    61 static bool
    62 header_prolog(TreeState *state)
    63 {
    64     char *define = xpidl_basename(state->basename);
    65     fprintf(state->file, "/*\n * DO NOT EDIT.  THIS FILE IS GENERATED FROM"
    66             " %s.idl\n */\n", state->basename);
    67     fprintf(state->file,
    68             "\n#ifndef __gen_%s_h__\n"
    69             "#define __gen_%s_h__\n",
    70             define, define);
    71     g_free(define);
    72     if (state->base_includes != NULL) {
    73         guint len = g_slist_length(state->base_includes);
    74         guint i;
    75 
    76         fputc('\n', state->file);
    77         for (i = 0; i < len; i++) {
    78             char *ident, *dot;
    79            
    80             ident = (char *)g_slist_nth_data(state->base_includes, i);
    81            
    82             /* suppress any trailing .extension */
    83            
    84             /* XXX use g_basename instead ? ? */
    85            
    86             dot = strrchr(ident, '.');
    87             if (dot != NULL)
    88                 *dot = '\0';
    89            
    90 
    91             /* begin include guard */           
    92             fprintf(state->file,
    93                     "\n#ifndef __gen_%s_h__\n",
    94                      ident);
    95 
    96             fprintf(state->file, "#include \"%s.h\"\n",
    97                     (char *)g_slist_nth_data(state->base_includes, i));
    98 
    99             fprintf(state->file, "#endif\n");
    100            
    101         }
    102         if (i > 0)
    103             fputc('\n', state->file);
    104     }
    105     /*
    106      * Support IDL files that don't include a root IDL file that defines
    107      * NS_NO_VTABLE.
    108      */
    109     fprintf(state->file,
    110             "/* For IDL files that don't want to include root IDL files. */\n"
    111             "#ifndef NS_NO_VTABLE\n"
    112             "#define NS_NO_VTABLE\n"
    113             "#endif\n");
    114    
    115     return TRUE;
    116 }
    117 
    118 static bool
    119 header_epilog(TreeState *state)
    120 {
    121     char *define = xpidl_basename(state->basename);
    122     fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
    123     g_free(define);
    124     return TRUE;
    125 }
    12652
    12753static void
     
    14167}
    14268
    143 static bool
    144 interface(TreeState *state)
    145 {
    146     IDL_tree iface = state->tree, iter, orig;
    147     char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
     69
     70static int xpidlHdrWriteIdlType(PCXPIDLNODE pNd, FILE *pFile)
     71{
     72    if (pNd->enmType == kXpidlNdType_BaseType)
     73    {
     74        switch (pNd->u.enmBaseType)
     75        {
     76            case kXpidlType_Void:
     77                fputs("void", pFile);
     78                break;
     79            case kXpidlType_Boolean:
     80                fputs("boolean", pFile);
     81                break;
     82            case kXpidlType_Octet:
     83                fputs("octet", pFile);
     84                break;
     85            case kXpidlType_Char:
     86                fputs("char", pFile);
     87                break;
     88            case kXpidlType_Wide_Char:
     89                fputs("wchar", pFile); /* wchar_t? */
     90                break;
     91            case kXpidlType_Short:
     92                fputs("short", pFile);
     93                break;
     94            case kXpidlType_Long:
     95                fputs("long", pFile);
     96                break;
     97            case kXpidlType_Long_Long:
     98                fputs("long long", pFile);
     99                break;
     100            case kXpidlType_Unsigned_Short:
     101                fputs("unsigned short", pFile);
     102                break;
     103            case kXpidlType_Unsigned_Long:
     104                fputs("unsigned long", pFile);
     105                break;
     106            case kXpidlType_Unsigned_Long_Long:
     107                fputs("unsigned long long", pFile);
     108                break;
     109            case kXpidlType_String:
     110                fputs("string", pFile);
     111                break;
     112            case kXpidlType_Wide_String:
     113                fputs("wstring", pFile);
     114                break;
     115            case kXpidlType_Double:
     116                fputs("double", pFile);
     117                break;
     118            case kXpidlType_Float:
     119                fputs("float", pFile);
     120                break;
     121            default:
     122                AssertReleaseFailed();
     123        }
     124    }
     125    else
     126    {
     127        Assert(pNd->enmType == kXpidlNdType_Identifier);
     128        fputs(pNd->u.pszIde, pFile);
     129    }
     130
     131    return VINF_SUCCESS;
     132}
     133
     134static int xpidlHdrWriteType(PCXPIDLNODE pNd, FILE *outfile)
     135{
     136    if (pNd->enmType == kXpidlNdType_BaseType)
     137    {
     138        switch (pNd->u.enmBaseType)
     139        {
     140            case kXpidlType_Void:
     141                fputs("void", outfile);
     142                break;
     143            case kXpidlType_Boolean:
     144                fputs("PRBool", outfile);
     145                break;
     146            case kXpidlType_Octet:
     147                fputs("PRUint8", outfile);
     148                break;
     149            case kXpidlType_Char:
     150                fputs("char", outfile);
     151                break;
     152            case kXpidlType_Wide_Char:
     153                fputs("PRUnichar", outfile); /* wchar_t? */
     154                break;
     155            case kXpidlType_Short:
     156                fputs("PRInt16", outfile);
     157                break;
     158            case kXpidlType_Long:
     159                fputs("PRInt32", outfile);
     160                break;
     161            case kXpidlType_Long_Long:
     162                fputs("PRInt64", outfile);
     163                break;
     164            case kXpidlType_Unsigned_Short:
     165                fputs("PRUInt16", outfile);
     166                break;
     167            case kXpidlType_Unsigned_Long:
     168                fputs("PRUInt32", outfile);
     169                break;
     170            case kXpidlType_Unsigned_Long_Long:
     171                fputs("PRUInt64", outfile);
     172                break;
     173            case kXpidlType_String:
     174                fputs("char *", outfile);
     175                break;
     176            case kXpidlType_Wide_String:
     177                fputs("PRUnichar *", outfile);
     178                break;
     179            case kXpidlType_Double:
     180                fputs("double", outfile);
     181                break;
     182            case kXpidlType_Float:
     183                fputs("float", outfile);
     184                break;
     185            default:
     186                AssertReleaseFailed();
     187        }
     188    }
     189    else
     190    {
     191        Assert(pNd->enmType == kXpidlNdType_Identifier);
     192        if (UP_IS_NATIVE(pNd))
     193        {
     194            if (   xpidlNodeAttrFind(pNd, "domstring")
     195                || xpidlNodeAttrFind(pNd, "astring"))
     196                fputs("nsAString", outfile);
     197            else if (xpidlNodeAttrFind(pNd, "utf8string"))
     198                fputs("nsACString", outfile);
     199            else if (xpidlNodeAttrFind(pNd, "cstring"))
     200                fputs("nsACString", outfile);
     201            else
     202                fputs(pNd->u.Native.pszNative, outfile);
     203
     204            if (xpidlNodeAttrFind(pNd, "ptr"))
     205                fputs(" *", outfile);
     206            else if (xpidlNodeAttrFind(pNd, "ref"))
     207                fputs(" &", outfile);
     208        }
     209        else
     210            fputs(pNd->u.pszIde, outfile);
     211
     212        if (UP_IS_AGGREGATE(pNd))
     213            fputs(" *", outfile);
     214    }
     215
     216    return VINF_SUCCESS;
     217}
     218
     219
     220/*
     221 * param generation:
     222 * in string foo        -->     nsString *foo
     223 * out string foo       -->     nsString **foo;
     224 * inout string foo     -->     nsString **foo;
     225 */
     226
     227/* If notype is true, just write the param name. */
     228static int write_param(PCXPIDLNODE pNd, FILE *pFile)
     229{
     230    PCXPIDLNODE pNdTypeSpec = pNd->u.Param.pNdTypeSpec;
     231    bool is_in = pNd->u.Param.enmDir == kXpidlDirection_In;
     232    /* in string, wstring, nsid, domstring, utf8string, cstring and
     233     * astring any explicitly marked [const] are const
     234     */
     235
     236    if (is_in &&
     237        (xpidlNdIsStringType(pNdTypeSpec) ||
     238//         IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
     239//                               "const") ||
     240         xpidlNodeAttrFind(pNdTypeSpec, "nsid") ||
     241         xpidlNodeAttrFind(pNdTypeSpec, "domstring")  ||
     242         xpidlNodeAttrFind(pNdTypeSpec, "utf8string") ||
     243         xpidlNodeAttrFind(pNdTypeSpec, "cstring")    ||
     244         xpidlNodeAttrFind(pNdTypeSpec, "astring"))) {
     245        fputs("const ", pFile);
     246    }
     247    else if (   pNd->u.Param.enmDir == kXpidlDirection_Out
     248             && xpidlNodeAttrFind(pNd, "shared")) {
     249        fputs("const ", pFile);
     250    }
     251
     252    int rc = xpidlHdrWriteType(pNdTypeSpec, pFile);
     253    if (RT_FAILURE(rc))
     254        return rc;
     255
     256    /* unless the type ended in a *, add a space */
     257    if (!STARRED_TYPE(pNdTypeSpec))
     258        fputc(' ', pFile);
     259
     260    /* out and inout params get a bonus '*' (unless this is type that has a
     261     * 'dipper' class that is passed in to receive 'out' data)
     262     */
     263    if (   !is_in
     264        && !DIPPER_TYPE(pNdTypeSpec))
     265        fputc('*', pFile);
     266
     267    /* arrays get a bonus * too */
     268    /* XXX Should this be a leading '*' or a trailing "[]" ?*/
     269    if (xpidlNodeAttrFind(pNd, "array"))
     270        fputc('*', pFile);
     271
     272    fputs(pNd->u.Param.pszName, pFile);
     273    return VINF_SUCCESS;
     274}
     275
     276
     277/*
     278 * Shared between the interface class declaration and the NS_DECL_IFOO macro
     279 * provided to aid declaration of implementation classes. 
     280 */
     281static int write_method_signature(PCXPIDLNODE pNd, FILE *pFile, const char *className)
     282{
     283    bool no_generated_args = true;
     284    bool op_notxpcom = (xpidlNodeAttrFind(pNd, "notxpcom") != NULL);
     285
     286    if (op_notxpcom) {
     287        fputs("NS_IMETHOD_(", pFile);
     288        int rc = xpidlHdrWriteType(pNd->u.Method.pNdTypeSpecRet, pFile);
     289        if (RT_FAILURE(rc))
     290            return rc;
     291        fputc(')', pFile);
     292    } else {
     293        fputs("NS_IMETHOD", pFile);
     294    }
     295    fputc(' ', pFile);
     296
     297    const char *pszName = pNd->u.Method.pszName;
     298    fprintf(pFile, "%c%s(", toupper(*pszName), pszName + 1);
     299
     300    PCXPIDLNODE pIt;
     301    RTListForEach(&pNd->u.Method.LstParams, pIt, XPIDLNODE, NdLst)
     302    {
     303        int rc = write_param(pIt, pFile);
     304        if (RT_FAILURE(rc))
     305            return rc;
     306
     307        if (!RTListNodeIsLast(&pNd->u.Method.LstParams, &pIt->NdLst))
     308            fputs(", ", pFile);
     309        no_generated_args = false;
     310    }
     311
     312#if 0
     313    /* make IDL return value into trailing out argument */
     314    if (op->op_type_spec && !op_notxpcom) {
     315        IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
     316                                                op->op_type_spec,
     317                                                IDL_ident_new("_retval"));
     318        if (!fake_param)
     319            return FALSE;
     320        if (!write_param(fake_param, pFile))
     321            return FALSE;
     322
     323#if 0
     324        if (op->f_varargs)
     325            fputs(", ", pFile);
     326#endif
     327        no_generated_args = false;
     328    }
     329#endif
     330
     331#if 0 /** @todo No varargs allowed. */
     332    /* varargs go last */
     333    if (op->f_varargs) {
     334        if (mode == AS_DECL || mode == AS_IMPL) {
     335            fputs("nsVarArgs *", pFile);
     336        }
     337        fputs("_varargs", pFile);
     338        no_generated_args = FALSE;
     339    }
     340#endif
     341
     342    /*
     343     * If generated method has no arguments, output 'void' to avoid C legacy
     344     * behavior of disabling type checking.
     345     */
     346    if (no_generated_args)
     347        fputs("void", pFile);
     348
     349    fputc(')', pFile);
     350    return VINF_SUCCESS;
     351}
     352
     353
     354static int xpidlHdrWriteMethod(PCXPIDLNODE pNd, FILE *pFile)
     355{
     356#if 0 /** @todo */
     357    /*
     358     * Verify that e.g. non-scriptable methods in [scriptable] interfaces
     359     * are declared so.  Do this in a separate verification pass?
     360     */
     361    if (!verify_method_declaration(state->tree))
     362        return FALSE;
     363#endif
     364
     365    write_indent(pFile);
     366    int rc = write_method_signature(pNd, pFile, NULL);
     367    if (RT_FAILURE(rc))
     368        return rc;
     369    fputs(" = 0;\n\n", pFile);
     370
     371    return VINF_SUCCESS;
     372}
     373
     374
     375static int xpidlHdrWriteAttrAccessor(PCXPIDLNODE pNd, FILE *pFile, bool getter)
     376{
     377    const char *pszName = pNd->u.Attribute.pszName;
     378
     379    fputs("NS_IMETHOD ", pFile);
     380    fprintf(pFile, "%cet%c%s(",
     381            getter ? 'G' : 'S',
     382            toupper(*pszName), pszName + 1);
     383    /* Setters for string, wstring, nsid, domstring, utf8string,
     384     * cstring and astring get const.
     385     */
     386    if (!getter &&
     387        (xpidlNdIsStringType(pNd->u.Attribute.pNdTypeSpec) ||
     388         xpidlNodeAttrFind(pNd, "nsid") ||
     389         xpidlNodeAttrFind(pNd, "domstring")  ||
     390         xpidlNodeAttrFind(pNd, "utf8string") ||
     391         xpidlNodeAttrFind(pNd, "cstring")    ||
     392         xpidlNodeAttrFind(pNd, "astring")))
     393        fputs("const ", pFile);
     394
     395    int rc = xpidlHdrWriteType(pNd->u.Attribute.pNdTypeSpec, pFile);
     396    if (RT_FAILURE(rc))
     397        return rc;
     398    fprintf(pFile, "%s%s",
     399            (STARRED_TYPE(pNd->u.Attribute.pNdTypeSpec) ? "" : " "),
     400            (getter && !DIPPER_TYPE(pNd->u.Attribute.pNdTypeSpec) ? "*" : ""));
     401    fprintf(pFile, "a%c%s)", toupper(pszName[0]), pszName + 1);
     402    return VINF_SUCCESS;
     403}
     404
     405static int xpidlHdrWriteAttribute(PCXPIDLNODE pNd, FILE *pFile)
     406{
     407#if 0 /** @todo */
     408    if (!verify_attribute_declaration(state->tree))
     409        return FALSE;
     410#endif
     411
     412    /* Write the attribute as a comment. */
     413    write_indent(pFile);
     414    if (pNd->u.Attribute.fReadonly)
     415        fputs("/* readonly attribute ", pFile);
     416    else
     417        fputs("/* attribute ", pFile);
     418    xpidlHdrWriteIdlType(pNd->u.Attribute.pNdTypeSpec, pFile);
     419    fprintf(pFile, " %s; */\n", pNd->u.Attribute.pszName);
     420
     421    write_indent(pFile);
     422    int rc = xpidlHdrWriteAttrAccessor(pNd, pFile, true);
     423    if (RT_FAILURE(rc))
     424        return rc;
     425    fputs(" = 0;\n", pFile);
     426
     427    if (!pNd->u.Attribute.fReadonly) {
     428        write_indent(pFile);
     429        rc = xpidlHdrWriteAttrAccessor(pNd, pFile, false);
     430        if (RT_FAILURE(rc))
     431            return rc;
     432        fputs(" = 0;\n", pFile);
     433    }
     434    fputc('\n', pFile);
     435
     436    return VINF_SUCCESS;
     437}
     438
     439
     440static int xpidlHdrWriteConst(PCXPIDLNODE pNd, FILE *pFile)
     441{
     442#if 0 /** @todo We only allow unsigned numbers for now. */
     443    if (!verify_const_declaration(pNd))
     444        return FALSE;
     445#endif
     446
     447    write_indent(pFile);
     448    fprintf(pFile, "enum { %s = ", pNd->u.Const.pszName);
     449    fprintf(pFile, "%lluU", pNd->u.Const.u64Const);
     450    fprintf(pFile, " };\n\n");
     451
     452    return VINF_SUCCESS;
     453}
     454
     455
     456static int xpidlHdrWriteInterface(PCXPIDLNODE pNd, FILE *pFile)
     457{
    148458    char *classNameUpper = NULL;
    149459    char *cp;
    150     bool ok = TRUE;
    151     bool keepvtable;
    152     const char *iid;
    153     const char *name_space;
    154460    struct nsID id;
    155461    char iid_parsed[UUID_LENGTH];
    156     GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
    157 
    158     if (!verify_interface_declaration(iface))
    159         return FALSE;
    160 
    161 #define FAIL    do {ok = FALSE; goto out;} while(0)
    162 
    163     fprintf(state->file,   "\n/* starting interface:    %s */\n",
    164             className);
    165 
    166     name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace");
    167     if (name_space) {
    168         fprintf(state->file, "/* namespace:             %s */\n",
    169                 name_space);
    170         fprintf(state->file, "/* fully qualified name:  %s.%s */\n",
    171                 name_space,className);
    172     }
    173 
    174     iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
    175     if (iid) {
     462    int rc = VINF_SUCCESS;
     463
     464    if (!verify_interface_declaration(pNd))
     465        return VERR_INVALID_PARAMETER;
     466
     467#define FAIL    do {rc = VERR_INVALID_PARAMETER; goto out;} while(0)
     468
     469    fprintf(pFile, "\n/* starting interface:    %s */\n", pNd->u.If.pszIfName);
     470
     471    AssertRelease(!xpidlNodeAttrFind(pNd, "namespace")); /* Not supported right now. */
     472
     473    PCXPIDLATTR pAttrIid = xpidlNodeAttrFind(pNd, "uuid");
     474    if (pAttrIid)
     475    {
     476        AssertPtr(pAttrIid->pszVal);
     477
    176478        /* Redundant, but a better error than 'cannot parse.' */
    177         if (strlen(iid) != 36) {
    178             IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid);
     479        if (strlen(pAttrIid->pszVal) != 36) {
     480            //IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid);
    179481            FAIL;
    180482        }
     
    184486         * uuid and normalize resulting .h files.
    185487         */
    186         if (!xpidl_parse_iid(&id, iid)) {
    187             IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
     488        if (!xpidl_parse_iid(&id, pAttrIid->pszVal)) {
     489            //IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
    188490            FAIL;
    189491        }
    190492        if (!xpidl_sprint_iid(&id, iid_parsed)) {
    191             IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
     493            //IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
    192494            FAIL;
    193495        }
    194496
    195497        /* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */
    196         fputs("#define ", state->file);
    197         write_classname_iid_define(state->file, className);
    198         fprintf(state->file, "_STR \"%s\"\n", iid_parsed);
    199         fputc('\n', state->file);
     498        fputs("#define ", pFile);
     499        write_classname_iid_define(pFile, pNd->u.If.pszIfName);
     500        fprintf(pFile, "_STR \"%s\"\n", iid_parsed);
     501        fputc('\n', pFile);
    200502
    201503        /* #define NS_ISUPPORTS_IID { {0x00000000 .... 0x46 }} */
    202         fprintf(state->file, "#define ");
    203         write_classname_iid_define(state->file, className);
    204         fprintf(state->file, " \\\n"
     504        fprintf(pFile, "#define ");
     505        write_classname_iid_define(pFile, pNd->u.If.pszIfName);
     506        fprintf(pFile, " \\\n"
    205507                "  {0x%.8x, 0x%.4x, 0x%.4x, \\\n"
    206508                "    { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, "
     
    209511                id.m3[0], id.m3[1], id.m3[2], id.m3[3],
    210512                id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
    211         fputc('\n', state->file);
     513        fputc('\n', pFile);
    212514    } else {
    213         IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
    214             className);
     515        //IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
     516        //    className);
    215517        FAIL;
    216518    }
    217 
    218     if (doc_comments != NULL)
    219         printlist(state->file, doc_comments);
    220519
    221520    /*
     
    227526     * the optimization.
    228527     */
    229     keepvtable = FALSE;
     528    bool keepvtable = false;
     529#if 0 /* We don't allow code fragments in interface definitions. */
    230530    for (iter = IDL_INTERFACE(state->tree).body;
    231531         iter != NULL;
     
    236536            keepvtable = TRUE;
    237537    }
     538#endif
     539
     540    /* The interface declaration itself. */
     541    fprintf(pFile,
     542            "class %s%s",
     543            (keepvtable ? "" : "NS_NO_VTABLE "), pNd->u.If.pszIfName);
    238544   
    239     /* The interface declaration itself. */
    240     fprintf(state->file,
    241             "class %s%s",
    242             (keepvtable ? "" : "NS_NO_VTABLE "), className);
    243    
    244     if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
    245         fputs(" : ", state->file);
    246         if (IDL_LIST(iter).next != NULL) {
    247             IDL_tree_error(iter,
    248                            "multiple inheritance is not supported by xpidl");
    249             FAIL;
    250         }
    251         fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str);
     545    if (pNd->u.If.pszIfInherit) {
     546        fputs(" : ", pFile);
     547        fprintf(pFile, "public %s", pNd->u.If.pszIfInherit);
    252548    }
    253549    fputs(" {\n"
    254           " public: \n\n", state->file);
    255 
    256     fputs("  NS_DEFINE_STATIC_IID_ACCESSOR(", state->file);
    257     write_classname_iid_define(state->file, className);
    258     fputs(")\n\n", state->file);
    259 
    260     orig = state->tree; /* It would be nice to remove this state-twiddling. */
    261 
    262     state->tree = IDL_INTERFACE(iface).body;
    263 
    264     if (state->tree && !xpidl_process_node(state))
    265         FAIL;
    266 
    267     fputs("};\n", state->file);
    268     fputc('\n', state->file);
    269 
     550          " public: \n\n", pFile);
     551
     552    fputs("  NS_DEFINE_STATIC_IID_ACCESSOR(", pFile);
     553    write_classname_iid_define(pFile, pNd->u.If.pszIfName);
     554    fputs(")\n\n", pFile);
     555
     556    PCXPIDLNODE pIt;
     557    RTListForEach(&pNd->u.If.LstBody, pIt, XPIDLNODE, NdLst)
     558    {
     559        switch (pIt->enmType)
     560        {
     561            case kXpidlNdType_Const:
     562                rc = xpidlHdrWriteConst(pIt, pFile);
     563                if (RT_FAILURE(rc))
     564                    return rc;
     565                break;
     566            case kXpidlNdType_Attribute:
     567                rc = xpidlHdrWriteAttribute(pIt, pFile);
     568                if (RT_FAILURE(rc))
     569                    return rc;
     570                break;
     571            case kXpidlNdType_Method:
     572                rc = xpidlHdrWriteMethod(pIt, pFile);
     573                if (RT_FAILURE(rc))
     574                    return rc;
     575                break;
     576            default:
     577                FAIL;
     578        }
     579    }
     580
     581    fputs("};\n", pFile);
     582    fputc('\n', pFile);
     583
     584#if 0
    270585    /*
    271586     * #define NS_DECL_NSIFOO - create method prototypes that can be used in
     
    479794        }
    480795    }
    481     fputc('\n', state->file);
     796#endif
     797    fputc('\n', pFile);
    482798
    483799#undef FAIL
     
    486802    if (classNameUpper)
    487803        free(classNameUpper);
    488     return ok;
    489 }
    490 
    491 static bool
    492 list(TreeState *state)
    493 {
    494     IDL_tree iter;
    495     for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
    496         state->tree = IDL_LIST(iter).data;
    497         if (!xpidl_process_node(state))
    498             return FALSE;
    499     }
    500     return TRUE;
    501 }
    502 
    503 static bool
    504 write_type(IDL_tree type_tree, bool is_out, FILE *outfile)
    505 {
    506     if (!type_tree) {
    507         fputs("void", outfile);
    508         return TRUE;
    509     }
    510 
    511     switch (IDL_NODE_TYPE(type_tree)) {
    512       case IDLN_TYPE_INTEGER: {
    513         bool sign = IDL_TYPE_INTEGER(type_tree).f_signed;
    514         switch (IDL_TYPE_INTEGER(type_tree).f_type) {
    515           case IDL_INTEGER_TYPE_SHORT:
    516             fputs(sign ? "PRInt16" : "PRUint16", outfile);
    517             break;
    518           case IDL_INTEGER_TYPE_LONG:
    519             fputs(sign ? "PRInt32" : "PRUint32", outfile);
    520             break;
    521           case IDL_INTEGER_TYPE_LONGLONG:
    522             fputs(sign ? "PRInt64" : "PRUint64", outfile);
    523             break;
    524           default:
    525             g_error("Unknown integer type %d\n",
    526                     IDL_TYPE_INTEGER(type_tree).f_type);
    527             return FALSE;
    528         }
    529         break;
    530       }
    531       case IDLN_TYPE_CHAR:
    532         fputs("char", outfile);
    533         break;
    534       case IDLN_TYPE_WIDE_CHAR:
    535         fputs("PRUnichar", outfile); /* wchar_t? */
    536         break;
    537       case IDLN_TYPE_WIDE_STRING:
    538         fputs("PRUnichar *", outfile);
    539         break;
    540       case IDLN_TYPE_STRING:
    541         fputs("char *", outfile);
    542         break;
    543       case IDLN_TYPE_BOOLEAN:
    544         fputs("PRBool", outfile);
    545         break;
    546       case IDLN_TYPE_OCTET:
    547         fputs("PRUint8", outfile);
    548         break;
    549       case IDLN_TYPE_FLOAT:
    550         switch (IDL_TYPE_FLOAT(type_tree).f_type) {
    551           case IDL_FLOAT_TYPE_FLOAT:
    552             fputs("float", outfile);
    553             break;
    554           case IDL_FLOAT_TYPE_DOUBLE:
    555             fputs("double", outfile);
    556             break;
    557           /* XXX 'long double' just ignored, or what? */
    558           default:
    559             fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
    560             break;
    561         }
    562         break;
    563       case IDLN_IDENT:
    564         if (UP_IS_NATIVE(type_tree)) {
    565             if (IDL_tree_property_get(type_tree, "domstring") ||
    566                 IDL_tree_property_get(type_tree, "astring")) {
    567                 fputs("nsAString", outfile);
    568             } else if (IDL_tree_property_get(type_tree, "utf8string")) {
    569                 fputs("nsACString", outfile);
    570             } else if (IDL_tree_property_get(type_tree, "cstring")) {
    571                 fputs("nsACString", outfile);
    572             } else {
    573                 fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
     804    return rc;
     805}
     806
     807
     808DECL_HIDDEN_CALLBACK(int) xpidl_header_dispatch(FILE *pFile, PCXPIDLINPUT pInput, PCXPIDLPARSE pParse)
     809{
     810    char *define = RTPathFilename(pInput->pszBasename);
     811    fprintf(pFile, "/*\n * DO NOT EDIT.  THIS FILE IS GENERATED FROM"
     812            " %s.idl\n */\n", pInput->pszBasename);
     813    fprintf(pFile,
     814            "\n#ifndef __gen_%s_h__\n"
     815            "#define __gen_%s_h__\n",
     816            define, define);
     817
     818    if (!RTListIsEmpty(&pInput->LstIncludes))
     819    {
     820        fputc('\n', pFile);
     821        PCXPIDLINPUT pIt;
     822        RTListForEach(&pInput->LstIncludes, pIt, XPIDLINPUT, NdInclude)
     823        {
     824            char *dot = strrchr(pIt->pszBasename, '.');
     825            if (dot != NULL)
     826                *dot = '\0';
     827           
     828
     829            /* begin include guard */           
     830            fprintf(pFile,
     831                    "\n#ifndef __gen_%s_h__\n",
     832                     pIt->pszBasename);
     833
     834            fprintf(pFile, "#include \"%s.h\"\n", pIt->pszBasename);
     835
     836            fprintf(pFile, "#endif\n");
     837        }
     838
     839        fputc('\n', pFile);
     840    }
     841    /*
     842     * Support IDL files that don't include a root IDL file that defines
     843     * NS_NO_VTABLE.
     844     */
     845    fprintf(pFile,
     846            "/* For IDL files that don't want to include root IDL files. */\n"
     847            "#ifndef NS_NO_VTABLE\n"
     848            "#define NS_NO_VTABLE\n"
     849            "#endif\n");
     850   
     851    PCXPIDLNODE pNd;
     852    RTListForEach(&pParse->LstNodes, pNd, XPIDLNODE, NdLst)
     853    {
     854        /* Only output nodes from the first level input and not for any includes. */
     855        if (pNd->pInput != pInput)
     856            continue;
     857
     858        int rc = VINF_SUCCESS;
     859        switch (pNd->enmType)
     860        {
     861            case kXpidlNdType_RawBlock:
     862            {
     863                fprintf(pFile, "%.*s", (int)pNd->u.RawBlock.cchRaw, pNd->u.RawBlock.pszRaw);
     864                break;
    574865            }
    575             if (IDL_tree_property_get(type_tree, "ptr")) {
    576                 fputs(" *", outfile);
    577             } else if (IDL_tree_property_get(type_tree, "ref")) {
    578                 fputs(" &", outfile);
     866            case kXpidlNdType_Interface_Forward_Decl:
     867            {
     868                fprintf(pFile, "class %s; /* forward declaration */\n\n", pNd->u.pszIfFwdName);
     869                break;
    579870            }
    580         } else {
    581             fputs(IDL_IDENT(type_tree).str, outfile);
    582         }
    583         if (UP_IS_AGGREGATE(type_tree))
    584             fputs(" *", outfile);
    585         break;
    586       default:
    587         fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
    588         break;
    589     }
    590     return TRUE;
    591 }
    592 
    593 /*
    594  * An attribute declaration looks like:
    595  *
    596  * [ IDL_ATTR_DCL]
    597  *   - param_type_spec [IDL_TYPE_* or NULL for void]
    598  *   - simple_declarations [IDL_LIST]
    599  *     - data [IDL_IDENT]
    600  *     - next [IDL_LIST or NULL if no more idents]
    601  *       - data [IDL_IDENT]
    602  */
    603 
    604 #define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
    605 #define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
    606 #define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
    607 
    608 /*
    609  *  AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
    610  *  AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
    611  *  AS_CALL writes 'foo(bar, sil)'
    612  */
    613 static bool
    614 write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
    615                     bool getter, int mode, const char *className)
    616 {
    617     char *attrname = ATTR_IDENT(attr_tree).str;
    618 
    619     if (mode == AS_DECL) {
    620         fputs("NS_IMETHOD ", outfile);
    621     } else if (mode == AS_IMPL) {
    622         fprintf(outfile, "NS_IMETHODIMP %s::", className);
    623     }
    624     fprintf(outfile, "%cet%c%s(",
    625             getter ? 'G' : 'S',
    626             toupper(*attrname), attrname + 1);
    627     if (mode == AS_DECL || mode == AS_IMPL) {
    628         /* Setters for string, wstring, nsid, domstring, utf8string,
    629          * cstring and astring get const.
    630          */
    631         if (!getter &&
    632             (IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_STRING ||
    633              IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_WIDE_STRING ||
    634              IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "nsid") ||
    635              IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "domstring")  ||
    636              IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "utf8string") ||
    637              IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "cstring")    ||
    638              IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "astring")))
    639         {
    640             fputs("const ", outfile);
    641         }
    642 
    643         if (!write_type(ATTR_TYPE_DECL(attr_tree), getter, outfile))
    644             return FALSE;
    645         fprintf(outfile, "%s%s",
    646                 (STARRED_TYPE(attr_tree) ? "" : " "),
    647                 (getter && !DIPPER_TYPE(ATTR_TYPE_DECL(attr_tree)))? "*" : "");
    648     }
    649     fprintf(outfile, "a%c%s)", toupper(attrname[0]), attrname + 1);
    650     return TRUE;
    651 }
    652 
    653 static bool
    654 attr_dcl(TreeState *state)
    655 {
    656     GSList *doc_comments;
    657 
    658     if (!verify_attribute_declaration(state->tree))
    659         return FALSE;
    660 
    661     doc_comments =
    662         IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
    663                            (state->tree).simple_declarations).data).comments;
    664 
    665     if (doc_comments != NULL) {
    666         write_indent(state->file);
    667         printlist(state->file, doc_comments);
    668     }
    669 
    670     /*
    671      * XXX lists of attributes with the same type, e.g.
    672      * attribute string foo, bar sil;
    673      * are legal IDL... but we don't do anything with 'em.
    674      */
    675     if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) {
    676         XPIDL_WARNING((state->tree, IDL_WARNING1,
    677                        "multiple attributes in a single declaration aren't "
    678                        "currently supported by xpidl"));
    679     }
    680 
    681     xpidl_write_comment(state, 2);
    682 
    683     write_indent(state->file);
    684     if (!write_attr_accessor(state->tree, state->file, TRUE, AS_DECL, NULL))
    685         return FALSE;
    686     fputs(" = 0;\n", state->file);
    687 
    688     if (!IDL_ATTR_DCL(state->tree).f_readonly) {
    689         write_indent(state->file);
    690         if (!write_attr_accessor(state->tree, state->file, FALSE, AS_DECL, NULL))
    691             return FALSE;
    692         fputs(" = 0;\n", state->file);
    693     }
    694     fputc('\n', state->file);
    695 
    696     return TRUE;
    697 }
    698 
    699 static bool
    700 do_enum(TreeState *state)
    701 {
    702     IDL_tree_error(state->tree, "enums not supported, "
    703                    "see http://bugzilla.mozilla.org/show_bug.cgi?id=8781");
    704     return FALSE;
    705 }
    706 
    707 static bool
    708 do_const_dcl(TreeState *state)
    709 {
    710     struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
    711     const char *name = IDL_IDENT(dcl->ident).str;
    712     bool is_signed;
    713     GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
    714     IDL_tree real_type;
    715     const char *const_format;
    716 
    717     if (!verify_const_declaration(state->tree))
    718         return FALSE;
    719 
    720     if (doc_comments != NULL) {
    721         write_indent(state->file);
    722         printlist(state->file, doc_comments);
    723     }
    724 
    725     /* Could be a typedef; try to map it to the real type. */
    726     real_type = find_underlying_type(dcl->const_type);
    727     real_type = real_type ? real_type : dcl->const_type;
    728     is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
    729 
    730     const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "uU";
    731     write_indent(state->file);
    732     fprintf(state->file, "enum { %s = ", name);
    733     fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
    734     fprintf(state->file, " };\n\n");
    735 
    736     return TRUE;
    737 }
    738 
    739 static bool
    740 do_typedef(TreeState *state)
    741 {
    742     IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
    743     IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
    744     IDL_tree complex;
    745     GSList *doc_comments;
    746 
    747     if (IDL_NODE_TYPE(type) == IDLN_TYPE_SEQUENCE) {
    748         XPIDL_WARNING((state->tree, IDL_WARNING1,
    749                        "sequences not supported, ignored"));
    750     } else {
    751         if (IDL_NODE_TYPE(complex = IDL_LIST(dcls).data) == IDLN_TYPE_ARRAY) {
    752             IDL_tree dim = IDL_TYPE_ARRAY(complex).size_list;
    753             doc_comments = IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).comments;
    754 
    755             if (doc_comments != NULL)
    756                 printlist(state->file, doc_comments);
    757 
    758             fputs("typedef ", state->file);
    759             if (!write_type(type, FALSE, state->file))
    760                 return FALSE;
    761             fputs(" ", state->file);
    762 
    763             fprintf(state->file, "%s",
    764                     IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).str);
    765             do {
    766                 fputc('[', state->file);
    767                 if (IDL_LIST(dim).data) {
    768                     fprintf(state->file, "%ld",
    769                             (long)IDL_INTEGER(IDL_LIST(dim).data).value);
    770                 }
    771                 fputc(']', state->file);
    772             } while ((dim = IDL_LIST(dim).next) != NULL);
    773         } else {
    774             doc_comments = IDL_IDENT(IDL_LIST(dcls).data).comments;
    775 
    776             if (doc_comments != NULL)
    777                 printlist(state->file, doc_comments);
    778 
    779             fputs("typedef ", state->file);
    780             if (!write_type(type, FALSE, state->file))
    781                 return FALSE;
    782             fputs(" ", state->file);
    783             fputs(IDL_IDENT(IDL_LIST(dcls).data).str, state->file);
    784         }
    785         fputs(";\n\n", state->file);
    786     }
    787     return TRUE;
    788 }
    789 
    790 /*
    791  * param generation:
    792  * in string foo        -->     nsString *foo
    793  * out string foo       -->     nsString **foo;
    794  * inout string foo     -->     nsString **foo;
    795  */
    796 
    797 /* If notype is true, just write the param name. */
    798 static bool
    799 write_param(IDL_tree param_tree, FILE *outfile)
    800 {
    801     IDL_tree param_type_spec = IDL_PARAM_DCL(param_tree).param_type_spec;
    802     bool is_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN;
    803     /* in string, wstring, nsid, domstring, utf8string, cstring and
    804      * astring any explicitly marked [const] are const
    805      */
    806 
    807     if (is_in &&
    808         (IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_STRING ||
    809          IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_WIDE_STRING ||
    810          IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
    811                                "const") ||
    812          IDL_tree_property_get(param_type_spec, "nsid") ||
    813          IDL_tree_property_get(param_type_spec, "domstring")  ||
    814          IDL_tree_property_get(param_type_spec, "utf8string") ||
    815          IDL_tree_property_get(param_type_spec, "cstring")    ||
    816          IDL_tree_property_get(param_type_spec, "astring"))) {
    817         fputs("const ", outfile);
    818     }
    819     else if (IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_OUT &&
    820              IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
    821                                    "shared")) {
    822         fputs("const ", outfile);
    823     }
    824 
    825     if (!write_type(param_type_spec, !is_in, outfile))
    826         return FALSE;
    827 
    828     /* unless the type ended in a *, add a space */
    829     if (!STARRED_TYPE(param_type_spec))
    830         fputc(' ', outfile);
    831 
    832     /* out and inout params get a bonus '*' (unless this is type that has a
    833      * 'dipper' class that is passed in to receive 'out' data)
    834      */
    835     if (IDL_PARAM_DCL(param_tree).attr != IDL_PARAM_IN &&
    836         !DIPPER_TYPE(param_type_spec)) {
    837         fputc('*', outfile);
    838     }
    839     /* arrays get a bonus * too */
    840     /* XXX Should this be a leading '*' or a trailing "[]" ?*/
    841     if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
    842                               "array"))
    843         fputc('*', outfile);
    844 
    845     fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile);
    846 
    847     return TRUE;
    848 }
    849 
    850 /*
    851  * A forward declaration, usually an interface.
    852  */
    853 static bool
    854 forward_dcl(TreeState *state)
    855 {
    856     IDL_tree iface = state->tree;
    857     const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
    858 
    859     if (!className)
    860         return FALSE;
    861 
    862     fprintf(state->file, "class %s; /* forward declaration */\n\n", className);
    863     return TRUE;
    864 }
    865 
    866 /*
    867  * Shared between the interface class declaration and the NS_DECL_IFOO macro
    868  * provided to aid declaration of implementation classes. 
    869  * mode...
    870  *  AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
    871  *  AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
    872  *  AS_CALL writes 'foo(bar, sil)'
    873  */
    874 static bool
    875 write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
    876                        const char *className)
    877 {
    878     struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
    879     bool no_generated_args = TRUE;
    880     bool op_notxpcom =
    881         (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
    882     const char *name;
    883     IDL_tree iter;
    884 
    885     if (mode == AS_DECL) {
    886         if (op_notxpcom) {
    887             fputs("NS_IMETHOD_(", outfile);
    888             if (!write_type(op->op_type_spec, FALSE, outfile))
    889                 return FALSE;
    890             fputc(')', outfile);
    891         } else {
    892             fputs("NS_IMETHOD", outfile);
    893         }
    894         fputc(' ', outfile);
    895     }
    896     else if (mode == AS_IMPL) {
    897         if (op_notxpcom) {
    898             fputs("NS_IMETHODIMP_(", outfile);
    899             if (!write_type(op->op_type_spec, FALSE, outfile))
    900                 return FALSE;
    901             fputc(')', outfile);
    902         } else {
    903             fputs("NS_IMETHODIMP", outfile);
    904         }
    905         fputc(' ', outfile);
    906     }
    907     name = IDL_IDENT(op->ident).str;
    908     if (mode == AS_IMPL) {
    909         fprintf(outfile, "%s::%c%s(", className, toupper(*name), name + 1);
    910     } else {
    911         fprintf(outfile, "%c%s(", toupper(*name), name + 1);
    912     }
    913     for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
    914         if (mode == AS_DECL || mode == AS_IMPL) {
    915             if (!write_param(IDL_LIST(iter).data, outfile))
    916                 return FALSE;
    917         } else {
    918             fputs(IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(iter).data)
    919                             .simple_declarator).str,
    920                   outfile);
    921         }
    922         if ((IDL_LIST(iter).next ||
    923              (!op_notxpcom && op->op_type_spec) || op->f_varargs))
    924             fputs(", ", outfile);
    925         no_generated_args = FALSE;
    926     }
    927 
    928     /* make IDL return value into trailing out argument */
    929     if (op->op_type_spec && !op_notxpcom) {
    930         IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
    931                                                 op->op_type_spec,
    932                                                 IDL_ident_new("_retval"));
    933         if (!fake_param)
    934             return FALSE;
    935         if (mode == AS_DECL || mode == AS_IMPL) {
    936             if (!write_param(fake_param, outfile))
    937                 return FALSE;
    938         } else {
    939             fputs("_retval", outfile);
    940         }
    941         if (op->f_varargs)
    942             fputs(", ", outfile);
    943         no_generated_args = FALSE;
    944     }
    945 
    946     /* varargs go last */
    947     if (op->f_varargs) {
    948         if (mode == AS_DECL || mode == AS_IMPL) {
    949             fputs("nsVarArgs *", outfile);
    950         }
    951         fputs("_varargs", outfile);
    952         no_generated_args = FALSE;
    953     }
    954 
    955     /*
    956      * If generated method has no arguments, output 'void' to avoid C legacy
    957      * behavior of disabling type checking.
    958      */
    959     if (no_generated_args && mode == AS_DECL) {
    960         fputs("void", outfile);
    961     }
    962 
    963     fputc(')', outfile);
    964 
    965     return TRUE;
    966 }
    967 
    968 /*
    969  * A method is an `operation', therefore a method decl is an `op dcl'.
    970  * I blame Elliot.
    971  */
    972 static bool
    973 op_dcl(TreeState *state)
    974 {
    975     GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments;
    976 
    977     /*
    978      * Verify that e.g. non-scriptable methods in [scriptable] interfaces
    979      * are declared so.  Do this in a separate verification pass?
    980      */
    981     if (!verify_method_declaration(state->tree))
    982         return FALSE;
    983 
    984     if (doc_comments != NULL) {
    985         write_indent(state->file);
    986         printlist(state->file, doc_comments);
    987     }
    988     xpidl_write_comment(state, 2);
    989 
    990     write_indent(state->file);
    991     if (!write_method_signature(state->tree, state->file, AS_DECL, NULL))
    992         return FALSE;
    993     fputs(" = 0;\n\n", state->file);
    994 
    995     return TRUE;
    996 }
    997 
    998 static void
    999 write_codefrag_line(gpointer data, gpointer user_data)
    1000 {
    1001     TreeState *state = (TreeState *)user_data;
    1002     const char *line = (const char *)data;
    1003     fputs(line, state->file);
    1004     fputc('\n', state->file);
    1005 }
    1006 
    1007 static bool
    1008 codefrag(TreeState *state)
    1009 {
    1010     const char *desc = IDL_CODEFRAG(state->tree).desc;
    1011     GSList *lines = IDL_CODEFRAG(state->tree).lines;
    1012 
    1013     if (strcmp(desc, "C++") && /* libIDL bug? */ strcmp(desc, "C++\r")) {
    1014         XPIDL_WARNING((state->tree, IDL_WARNING1,
    1015                        "ignoring '%%{%s' escape. "
    1016                        "(Use '%%{C++' to escape verbatim C++ code.)", desc));
    1017 
    1018         return TRUE;
    1019     }
    1020 
    1021     /*
    1022      * Emit #file directive to point debuggers back to the original .idl file
    1023      * for the duration of the code fragment.  We look at internal IDL node
    1024      * properties _file, _line to do this; hopefully they won't change.
    1025      *
    1026      * _line seems to refer to the line immediately after the closing %}, so
    1027      * we backtrack to get the proper line for the beginning of the block.
    1028      */
    1029     g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
    1030 
    1031     return TRUE;
    1032 }
    1033 #endif
    1034 
    1035 backend *
    1036 xpidl_header_dispatch(void)
    1037 {
    1038     static backend result;
    1039     static nodeHandler table[10 /*IDLN_LAST*/];
    1040     static bool initialized = false;
    1041    
    1042     result.emit_prolog = NULL; //header_prolog;
    1043     result.emit_epilog = NULL; //header_epilog;
    1044 
    1045 #if 0
    1046     if (!initialized) {
    1047         table[IDLN_LIST] = NULL; //list;
    1048         table[IDLN_ATTR_DCL] = NULL; //attr_dcl;
    1049         table[IDLN_OP_DCL] = NULL; //op_dcl;
    1050         table[IDLN_FORWARD_DCL] = NULL; //forward_dcl;
    1051         table[IDLN_TYPE_ENUM] = NULL; //do_enum;
    1052         table[IDLN_INTERFACE] = NULL; //interface;
    1053         table[IDLN_CODEFRAG] = NULL; //codefrag;
    1054         table[IDLN_TYPE_DCL] = NULL; //do_typedef;
    1055         table[IDLN_CONST_DCL] = NULL; //do_const_dcl;
    1056         table[IDLN_NATIVE]    = NULL; //check_native;
    1057         initialized = true;
    1058     }
    1059 #endif
    1060 
    1061     result.dispatch_table = table;
    1062     return &result;
    1063 }
     871            case kXpidlNdType_Interface_Def:
     872            {
     873                rc = xpidlHdrWriteInterface(pNd, pFile);
     874                break;
     875            }
     876            case kXpidlNdType_Typedef:
     877            {
     878                fprintf(pFile, "typedef ");
     879                rc = xpidlHdrWriteType(pNd->u.Typedef.pNodeTypeSpec, pFile);
     880                if (RT_SUCCESS(rc))
     881                    fprintf(pFile, " %s;\n\n", pNd->u.Typedef.pszName);
     882                break;
     883            }
     884            default: /* Ignore */
     885                break;
     886        }
     887        if (RT_FAILURE(rc))
     888            return rc;
     889    }
     890
     891    fprintf(pFile, "\n#endif /* __gen_%s_h__ */\n", define);
     892    return VINF_SUCCESS;
     893}
  • trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_idl.c

    r108304 r108305  
    4141    kXpidlKeyword_Include,
    4242    kXpidlKeyword_Typedef,
     43    kXpidlKeyword_Void,
    4344    kXpidlKeyword_Char,
    4445    kXpidlKeyword_Wide_Char,
     
    5960    kXpidlKeyword_Out,
    6061    kXpidlKeyword_InOut,
     62    kXpidlKeyword_Const,
    6163    kXpidlKeyword_32Bit_Hack = 0x7fffffff
    6264} XPIDLKEYWORD;
     
    9496    { RT_STR_TUPLE("#include"),                 RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Include     },
    9597
     98    { RT_STR_TUPLE("void"),                     RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Void        },
    9699    { RT_STR_TUPLE("char"),                     RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Char        },
    97100    { RT_STR_TUPLE("long"),                     RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Long        },
     
    114117    { RT_STR_TUPLE("inout"),                    RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_InOut       },
    115118    { RT_STR_TUPLE("out"),                      RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Out         },
    116 
    117     { RT_STR_TUPLE("const"),                    RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  0 },
     119    { RT_STR_TUPLE("const"),                    RTSCRIPTLEXTOKTYPE_KEYWORD,    true,  kXpidlKeyword_Const       },
    118120
    119121    { RT_STR_TUPLE(","),                        RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ',' },
     
    244246
    245247
     248static int xpidlParseSkipComments(PXPIDLPARSE pThis, PXPIDLINPUT pInput)
     249{
     250    for (;;)
     251    {
     252        PCRTSCRIPTLEXTOKEN pTok;
     253        int rc = RTScriptLexQueryToken(pInput->hIdlLex, &pTok);
     254        if (RT_FAILURE(rc))
     255            return xpidlParseError(pThis, pInput, pTok, rc, "Lexer: Failed to query string literal token with %Rrc", rc);
     256
     257        if (   pTok->enmType != RTSCRIPTLEXTOKTYPE_COMMENT_SINGLE_LINE
     258            && pTok->enmType != RTSCRIPTLEXTOKTYPE_COMMENT_MULTI_LINE)
     259            return VINF_SUCCESS;
     260
     261        /* Make sure we don't miss any %{C++ %} blocks. */
     262        if (!strncmp(pTok->Type.Comment.pszComment, RT_STR_TUPLE("%{C++")))
     263            return xpidlParseError(pThis, pInput, pTok, VERR_INVALID_PARAMETER, "Parser: Encountered unexpected raw code block comment");
     264
     265        RTScriptLexConsumeToken(pInput->hIdlLex);
     266    }
     267
     268    return VINF_SUCCESS;
     269}
     270
     271
    246272static int xpidlLexerConsumeIfStringLit(PXPIDLPARSE pThis, PXPIDLINPUT pInput, const char **ppszStrLit)
    247273{
     
    372398
    373399
     400static int xpidlLexerConsumeIfNatural(PXPIDLPARSE pThis, PXPIDLINPUT pInput, uint64_t *pu64, bool *pfConsumed)
     401{
     402    PCRTSCRIPTLEXTOKEN pTok;
     403    int rc = RTScriptLexQueryToken(pInput->hIdlLex, &pTok);
     404    if (RT_FAILURE(rc))
     405        return xpidlParseError(pThis, pInput, NULL, rc, "Lexer: Failed to query punctuator token with %Rrc", rc);
     406
     407    if (   pTok->enmType == RTSCRIPTLEXTOKTYPE_NUMBER
     408        && pTok->Type.Number.enmType == RTSCRIPTLEXTOKNUMTYPE_NATURAL)
     409    {
     410        *pfConsumed = true;
     411        *pu64 = pTok->Type.Number.Type.u64;
     412        RTScriptLexConsumeToken(pInput->hIdlLex);
     413        return VINF_SUCCESS;
     414    }
     415
     416    *pfConsumed = false;
     417    return VINF_SUCCESS;
     418}
     419
     420/* Some parser helper macros. */
    374421#define XPIDL_PARSE_STRING_LIT(a_pszStrLit) \
    375422    const char *a_pszStrLit = NULL; \
     
    383430
    384431
    385 /* Some parser helper macros. */
     432#define XPIDL_PARSE_KEYWORD(a_enmKeyword, a_pszKeyword) \
     433    do { \
     434        bool fConsumed2 = false; \
     435        int rc2 = xpidlLexerConsumeIfKeyword(pThis, pInput, a_enmKeyword, &fConsumed2); \
     436        if (RT_FAILURE(rc2)) \
     437            return rc2; \
     438        if (!fConsumed2) \
     439            return xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Parser: Expected keyword '%s'", a_pszKeyword); \
     440    } while(0)
     441
     442
    386443#define XPIDL_PARSE_OPTIONAL_KEYWORD(a_fConsumed, a_enmKeyword) \
    387444    bool a_fConsumed = false; \
     
    466523
    467524
     525#define XPIDL_PARSE_NATURAL(a_u64) \
     526    uint64_t a_u64 = 0; \
     527    do { \
     528        bool fConsumed2 = false; \
     529        int rc2 = xpidlLexerConsumeIfNatural(pThis, pInput, &a_u64, &fConsumed2); \
     530        if (RT_FAILURE(rc2)) \
     531            return rc2; \
     532        if (!fConsumed2) \
     533            return xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Parser: Expected a natural number"); \
     534    } while(0)
     535
     536
    468537static PXPIDLINPUT xpidlInputCreate(const char *pszFilename, PRTLISTANCHOR pLstIncludePaths)
    469538{
     
    483552    pInput->hIdlLex     = hIdlLex;
    484553    pInput->pszFilename = xpidl_strdup(pszFilename);
     554    pInput->pszBasename = RTPathFilename(pInput->pszFilename);
    485555    return pInput;
    486556}
     
    496566        pNode->pInput  = pInput;
    497567        pNode->enmType = enmType;
     568        pNode->cAttrs  = cAttrs;
    498569        switch (enmType)
    499570        {
     
    555626            break;
    556627    }
     628    *pcAttrs = cAttrs;
    557629    g_fParsingAttributes = false;
    558630
     
    567639    static const XPIDLKEYWORD g_aenmTypeKeywordsStart[] =
    568640    {
     641        kXpidlKeyword_Void,
    569642        kXpidlKeyword_Char,
    570643        kXpidlKeyword_Wide_Char,
     
    590663        switch (enmType)
    591664        {
     665            case kXpidlKeyword_Void:
     666                enmBaseType = kXpidlType_Void;
     667                break;
    592668            case kXpidlKeyword_Char:
    593669                enmBaseType = kXpidlType_Char;
     
    694770
    695771
     772static int xpidlParseConst(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PXPIDLNODE pNdIf)
     773{
     774    int rc;
     775    PXPIDLNODE pNdConst = xpidlNodeCreate(pThis, pNdIf, pInput, kXpidlNdType_Const);
     776    if (pNdConst)
     777    {
     778        RTListAppend(&pNdIf->u.If.LstBody, &pNdConst->NdLst);
     779
     780        PXPIDLNODE pNdTypeSpec = NULL;
     781        int rc = xpidlParseTypeSpec(pThis, pInput, &pNdTypeSpec);
     782        if (RT_FAILURE(rc))
     783            return rc;
     784        pNdConst->u.Const.pNdTypeSpec = pNdTypeSpec;
     785
     786        XPIDL_PARSE_IDENTIFIER(pszName); /* The parameter name is always required. */
     787        pNdConst->u.Const.pszName = pszName;
     788
     789        XPIDL_PARSE_PUNCTUATOR('=');
     790        XPIDL_PARSE_NATURAL(u64);
     791        pNdConst->u.Const.u64Const = u64;
     792    }
     793    else
     794        rc = VERR_NO_MEMORY;
     795
     796    return rc;
     797}
     798
     799
     800static int xpidlParseAttribute(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PXPIDLNODE pNdIf, bool fReadonly)
     801{
     802    int rc;
     803    PXPIDLNODE pNdConst = xpidlNodeCreate(pThis, pNdIf, pInput, kXpidlNdType_Attribute);
     804    if (pNdConst)
     805    {
     806        RTListAppend(&pNdIf->u.If.LstBody, &pNdConst->NdLst);
     807
     808        PXPIDLNODE pNdTypeSpec = NULL;
     809        int rc = xpidlParseTypeSpec(pThis, pInput, &pNdTypeSpec);
     810        if (RT_FAILURE(rc))
     811            return rc;
     812        pNdConst->u.Attribute.pNdTypeSpec = pNdTypeSpec;
     813
     814        XPIDL_PARSE_IDENTIFIER(pszName); /* The parameter name is always required. */
     815        pNdConst->u.Attribute.pszName = pszName;
     816        pNdConst->u.Attribute.fReadonly = fReadonly;
     817    }
     818    else
     819        rc = VERR_NO_MEMORY;
     820
     821    return rc;
     822}
     823
     824
    696825static int xpidlParseMethodParameters(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PXPIDLNODE pNdMethod)
    697826{
     
    768897    for (;;)
    769898    {
     899        int rc = xpidlParseSkipComments(pThis, pInput);
     900        if (RT_FAILURE(rc))
     901            return rc;
     902
    770903        /* A closing '}' means we reached the end of the interface body. */
    771904        bool fConsumed = false;
     
    778911         *     readonly attribute <type spec> <name>;
    779912         *     attribute <type spec> <name>;
     913         *     const <type spec> <name> = <value>;
    780914         *     <type spec> <name> (...);
    781915         */
    782         static const XPIDLKEYWORD g_aenmAttributesKeywords[] =
     916        static const XPIDLKEYWORD g_aenmBodyKeywords[] =
    783917        {
    784918            kXpidlKeyword_Readonly,
    785919            kXpidlKeyword_Attribute,
     920            kXpidlKeyword_Const,
    786921            kXpidlKeyword_Invalid
    787922        };
    788923
    789         XPIDL_PARSE_OPTIONAL_KEYWORD_LIST(enmAttr, g_aenmAttributesKeywords, kXpidlKeyword_Invalid);
    790         if (enmAttr != kXpidlKeyword_Invalid)
    791         {
    792             AssertFailed();
     924        XPIDL_PARSE_OPTIONAL_KEYWORD_LIST(enmStart, g_aenmBodyKeywords, kXpidlKeyword_Invalid);
     925        if (enmStart != kXpidlKeyword_Invalid)
     926        {
     927            if (enmStart == kXpidlKeyword_Const)
     928                rc = xpidlParseConst(pThis, pInput, pNdIf);
     929            else if (enmStart == kXpidlKeyword_Readonly)
     930            {
     931                XPIDL_PARSE_KEYWORD(kXpidlKeyword_Attribute, "attribute");
     932                rc = xpidlParseAttribute(pThis, pInput, pNdIf, true /*fReadonly*/);
     933            }
     934            else
     935            {
     936                Assert(enmStart == kXpidlKeyword_Attribute);
     937                rc = xpidlParseAttribute(pThis, pInput, pNdIf, false /*fReadonly*/);
     938            }
    793939        }
    794940        else
    795941        {
    796942            /* We need to parse a type spec. */
    797             int rc = VINF_SUCCESS;
    798943            PXPIDLNODE pNdRetType = NULL;
    799944            XPIDLATTR aAttrs[32];
     
    836981                return VERR_NO_MEMORY;
    837982        }
     983        if (RT_FAILURE(rc))
     984            return rc;
    838985
    839986        XPIDL_PARSE_PUNCTUATOR(';');
     
    8601007    {
    8611008        const char *pszIfInherit = NULL;
    862 
    8631009        XPIDL_PARSE_OPTIONAL_PUNCTUATOR(fConsumed, ':');
    8641010        if (fConsumed)
     
    8661012        XPIDL_PARSE_PUNCTUATOR('{');
    8671013        /* Now for the fun part, parsing the body of the interface. */
    868         PXPIDLNODE pNode = xpidlNodeCreate(pThis, pParent, pInput, kXpidlNdType_Interface_Def);
     1014        PXPIDLNODE pNode = xpidlNodeCreateWithAttrs(pThis, pParent, pInput, kXpidlNdType_Interface_Def,
     1015                                                    &pThis->aAttrs[0], pThis->cAttrs);
    8691016        if (pNode)
    8701017        {
     1018            pThis->cAttrs = 0;
     1019
    8711020            pNode->u.If.pszIfName    = pszName;
    8721021            pNode->u.If.pszIfInherit = pszIfInherit;
     
    9061055        {
    9071056            XPIDL_PARSE_STRING_LIT(pszFilename);
    908             PXPIDLINPUT pInput = xpidlInputCreate(pszFilename, pLstIncludePaths);
    909             if (!pInput)
     1057            PXPIDLINPUT pInputNew = xpidlInputCreate(pszFilename, pLstIncludePaths);
     1058            if (!pInputNew)
    9101059                return xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Failed opening include file '%s'",
    9111060                                       pszFilename);
    9121061
    913             RTListAppend(&pThis->LstInputs, &pInput->NdInput);
    914             rc = xpidlParseIdl(pThis, pInput, pLstIncludePaths);
     1062            RTListAppend(&pInput->LstIncludes, &pInputNew->NdInclude);
     1063            RTListAppend(&pThis->LstInputs, &pInputNew->NdInput);
     1064            rc = xpidlParseIdl(pThis, pInputNew, pLstIncludePaths);
    9151065            break;
    9161066        }
     
    10701220    if (RT_SUCCESS(rc))
    10711221    {
    1072         /** @todo Output. */
     1222        char *tmp, *outname, *real_outname = NULL;
     1223
     1224        pInput->pszBasename = xpidl_strdup(filename);
     1225
     1226        /* if basename has an .extension, truncate it. */
     1227        tmp = strrchr(pInput->pszBasename, '.');
     1228        if (tmp)
     1229            *tmp = '\0';
     1230
     1231        if (!file_basename)
     1232            outname = xpidl_strdup(pInput->pszBasename);
     1233        else
     1234            outname = xpidl_strdup(file_basename);
     1235
     1236        FILE *pFile = NULL;
     1237        if (strcmp(outname, "-"))
     1238        {
     1239            const char *fopen_mode;
     1240            char *out_basename;
     1241
     1242            /* explicit_output_filename can't be true without a filename */
     1243            if (explicit_output_filename) {
     1244                real_outname = xpidl_strdup(outname);
     1245            } else {
     1246
     1247                if (!file_basename) {
     1248                    out_basename = RTPathFilename(outname);
     1249                } else {
     1250                    out_basename = outname;
     1251                }
     1252
     1253                rc = RTStrAPrintf(&real_outname, "%s.%s", out_basename, mode->suffix);
     1254                if (RT_FAILURE(rc))
     1255                    return rc;
     1256
     1257                if (out_basename != outname)
     1258                    free(out_basename);
     1259            }
     1260
     1261            /* Use binary write for typelib mode */
     1262            fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
     1263            pFile = fopen(real_outname, fopen_mode);
     1264            if (!pFile) {
     1265                perror("error opening output file");
     1266                free(outname);
     1267                return VERR_INVALID_PARAMETER;
     1268            }
     1269        }
     1270        else
     1271            pFile = stdout;
     1272
     1273        rc = mode->dispatch(pFile, pInput, &ParseState);
     1274
     1275        if (pFile != stdout)
     1276            fclose(pFile);
     1277        free(outname);
    10731278    }
    10741279    else
  • trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_util.c

    r108284 r108305  
    772772    return FALSE;
    773773}
    774 
    775 /*
    776  * Print a GSList as char strings to a file.
    777  */
    778 void
    779 printlist(FILE *outfile, GSList *slist)
    780 {
    781     guint i;
    782     guint len = g_slist_length(slist);
    783 
    784     for(i = 0; i < len; i++) {
    785         fprintf(outfile,
    786                 "%s\n", (char *)g_slist_nth_data(slist, i));
    787     }
    788 }
    789 
    790 void
    791 xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
    792 {
    793     IDL_tree_func_data tfd;
    794 
    795     while (p) {
    796         struct _IDL_LIST *list = &IDL_LIST(p);
    797         tfd.tree = list->data;
    798         if (!foreach(&tfd, user_data))
    799             return;
    800         p = list->next;
    801     }
    802 }
     774#endif
    803775
    804776/*
    805777 * Verify that the interface declaration is correct
    806778 */
    807 gboolean
    808 verify_interface_declaration(IDL_tree interface_tree)
    809 {
    810     IDL_tree iter;
     779DECLHIDDEN(bool) verify_interface_declaration(PCXPIDLNODE pNd)
     780{
    811781    /*
    812782     * If we have the scriptable attribute then make sure all of our direct
     
    814784     * NOTE: We don't recurse since all interfaces will fall through here
    815785     */
    816     if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
    817         "scriptable")) {
     786    if (xpidlNodeAttrFind(pNd,  "scriptable"))
     787    {
     788#if 0
    818789        for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter;
    819790            iter = IDL_LIST(iter).next) {
     
    826797            }
    827798        }
    828     }
    829     return TRUE;
    830 }
    831 
    832 /*
    833  * Return a pointer to the start of the base filename of path
    834  */
    835 char *
    836 xpidl_basename(const char * path)
    837 {
    838     char * result = g_path_get_basename(path);
    839     /*
    840      *If this is windows then we'll handle either / or \ as a separator
    841      * g_basename only handles \ for windows
    842      */
    843 #if defined(XP_WIN32)
    844 # error adapt regarding g_basename() vs. g_path_get_basename()!
    845     const char * slash = strrchr(path, '/');
    846     /* If we found a slash and its after the current default OS separator */
    847     if (slash != NULL && (slash > result))
    848         result = slash + 1;
    849799#endif
    850     return result;
    851 }
    852 #endif
     800    }
     801    return true;
     802}
     803
     804
     805DECLHIDDEN(PCXPIDLATTR) xpidlNodeAttrFind(PCXPIDLNODE pNd, const char *pszAttr)
     806{
     807    for (uint32_t i = 0; i < pNd->cAttrs; i++)
     808    {
     809        if (!strcmp(pNd->aAttrs[i].pszName, pszAttr))
     810            return &pNd->aAttrs[i];
     811    }
     812
     813    return NULL;
     814}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette