Exemple #1
0
static gboolean
header_epilog(TreeState *state)
{
    const char *define = xpidl_basename(state->basename);
    fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
    return TRUE;
}
static gboolean
header_prolog(TreeState *state)
{
    char *define = xpidl_basename(state->basename);
    fprintf(state->file, "/*\n * DO NOT EDIT.  THIS FILE IS GENERATED FROM"
            " %s.idl\n */\n", state->basename);
    fprintf(state->file,
            "\n#ifndef __gen_%s_h__\n"
            "#define __gen_%s_h__\n",
            define, define);
    g_free(define);
    if (state->base_includes != NULL) {
        guint len = g_slist_length(state->base_includes);
        guint i;

        fputc('\n', state->file);
        for (i = 0; i < len; i++) {
            char *ident, *dot;
            
            ident = (char *)g_slist_nth_data(state->base_includes, i);
            
            /* suppress any trailing .extension */
            
            /* XXX use g_basename instead ? ? */
            
            dot = strrchr(ident, '.');
            if (dot != NULL)
                *dot = '\0';
            

            /* begin include guard */            
            fprintf(state->file,
                    "\n#ifndef __gen_%s_h__\n",
                     ident);

            fprintf(state->file, "#include \"%s.h\"\n",
                    (char *)g_slist_nth_data(state->base_includes, i));

            fprintf(state->file, "#endif\n");
            
        }
        if (i > 0)
            fputc('\n', state->file);
    }
    /*
     * Support IDL files that don't include a root IDL file that defines
     * NS_NO_VTABLE.
     */
    fprintf(state->file,
            "/* For IDL files that don't want to include root IDL files. */\n"
            "#ifndef NS_NO_VTABLE\n"
            "#define NS_NO_VTABLE\n"
            "#endif\n");
    
    return TRUE;
}
int
xpidl_process_idl(char *filename, IncludePathEntry *include_path,
                  char *file_basename, char* package, ModeData *mode)
{
    char *tmp, *outname, *real_outname = NULL;
    IDL_tree top;
    TreeState state;
    int rv;
    input_callback_state callback_state;
    gboolean ok = TRUE;
    backend *emitter;

    memset(&state, 0, sizeof(state));

    callback_state.input_stack = NULL;
    callback_state.base_includes = NULL;
    callback_state.include_path = include_path;
    callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal);

    if (!callback_state.already_included) {
        fprintf(stderr, "failed to create hashtable.  out of memory?\n");
        return 0;
    }

    state.basename = xpidl_strdup(filename);
    if (package)
      state.package = xpidl_strdup(package);

    /* if basename has an .extension, truncate it. */
    tmp = strrchr(state.basename, '.');
    if (tmp)
        *tmp = '\0';

    if (!file_basename)
        outname = xpidl_strdup(state.basename);
    else
        outname = xpidl_strdup(file_basename);

    /* so we don't include it again! */
    g_hash_table_insert(callback_state.already_included,
                        xpidl_strdup(filename), (void *)TRUE);

    parsed_empty_file = FALSE;

    rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state,
                                       msg_callback, &top,
                                       &state.ns,
                                       IDLF_IGNORE_FORWARDS |
                                       IDLF_XPIDL,
                                       enable_warnings ? IDL_WARNING1 :
                                       IDL_ERROR);
    if (parsed_empty_file) {
        /*
         * If we've detected (via hack in msg_callback) that libIDL returned
         * failure because it found a file with no IDL, set the parse tree to
         * null and proceed.  Allowing this is useful to permit .idl files that
         * collect #includes.
         */
        top = NULL;
        state.ns = NULL;
    } else if (rv != IDL_SUCCESS) {
        if (rv == -1) {
            g_warning("Parse of %s failed: %s", filename, g_strerror(errno));
        } else {
            g_warning("Parse of %s failed", filename);
        }
        return 0;
    }

    state.basename = xpidl_strdup(filename);
    tmp = strrchr(state.basename, '.');
    if (tmp)
        *tmp = '\0';

    /* so xpidl_header.c can use it to generate a list of #include directives */
    state.base_includes = callback_state.base_includes;

    emitter = mode->factory();
    state.dispatch = emitter->dispatch_table;

    if (strcmp(outname, "-")) {
        const char *fopen_mode;
        const char *out_basename;

        /* explicit_output_filename can't be true without a filename */
        if (explicit_output_filename) {
            real_outname = g_strdup(outname);
        } else {
/* 
 *This combination seems a little strange, what about OS/2?
 * Assume it's some build issue
 */
#if defined(XP_UNIX) || defined(XP_WIN)
            if (!file_basename) {
                out_basename = xpidl_basename(outname);
            } else {
                out_basename = outname;
            }
#else
            out_basename = outname;
#endif
            real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix);
        }

        /* don't create/open file here for Java */
        if (strcmp(mode->mode, "java") == 0)
        {
            state.filename = real_outname;
        } else {
            /* Use binary write for typelib mode */
            fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
            state.file = fopen(real_outname, fopen_mode);
            if (!state.file) {
                perror("error opening output file");
                return 0;
            }
        }
    } else {
        state.file = stdout;
    }
    state.tree = top;

    if (emitter->emit_prolog)
        emitter->emit_prolog(&state);
    if (state.tree) /* Only if we have a tree to process. */
        ok = xpidl_process_node(&state);
    if (emitter->emit_epilog)
        emitter->emit_epilog(&state);

    if (strcmp(mode->mode, "java") != 0)
    {
        if (state.file != stdout)
            fclose(state.file);
    }

    free(state.basename);
    free(state.package);
    free(outname);
    g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL);
    g_hash_table_destroy(callback_state.already_included);
    g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL);

    if (state.ns)
        IDL_ns_free(state.ns);
    if (top)
        IDL_tree_free(top);

    if (real_outname != NULL) {
        /*
         * Delete partial output file on failure.  (Mac does this in the plugin
         * driver code, if the compiler returns failure.)
         */
#if defined(XP_UNIX) || defined(XP_WIN)
        if (!ok)
            unlink(real_outname);
#endif
        g_free(real_outname);
    }

    return ok;
}