Batched set of fixes to xpidl. NOTE this'll probably cause the world to rebuild.

* fix 20833 - generate numbers of appropriate form in header output mode for short, long, signed or unsigned IDL consts.  Thanks to bratell@lysator.liu.se for finding this and confirming the fix.

* fix 11199, remove .h output file on failure - partially generated files caused trouble, as they had the proper timestamp to fool 'make' next time around. Punted on mac.

* Restore Mac hack to fix \r to \n, requested by Beard.

* Make 'const decl must be short or long' warning into error for typelib mode.  This mirrors an existing error in header mode.

* Fix up various aspects of xpidl, including:

- Move shared functions from xpidl_idl.c and xpidl.c 'main' module to new xpidl_util.c.

- Recast nodehandler-table-per-backend as 'backend' struct, including broken-out prolog and epilog functions.  Replaces overloaded IDLN_NONE node handler that did prolog code on non-null tree, epilog on null.  Move backends to new API.

- Rename a few structs more logically.

- Add a new list to track files included from the base .idl file, for generated #includes in output header file.  This replaces using the 'already-included' hashtable for this purpose, and lets us generate just the minimal set of #includes, in the order they occured in the .h file.

- Various fixes to quiet xpidl warnings.

- Change main() to only accept one input file from the command line, because the basename code assumes this, and multiple files aren't needed by our make system.

r=jband


git-svn-id: svn://10.0.0.236/trunk@57488 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mccabe%netscape.com 2000-01-12 01:46:21 +00:00
parent e953c924c9
commit ecfc9775e8
10 changed files with 674 additions and 571 deletions

View File

@ -32,6 +32,7 @@ INTERNAL_TOOLS = 1
CSRCS = \
xpidl.c \
xpidl_idl.c \
xpidl_util.c \
xpidl_header.c \
xpidl_typelib.c \
xpidl_doc.c \

View File

@ -31,6 +31,7 @@ MOZ_NO_DEBUG_RTL=1
OBJS = \
.\$(OBJDIR)\xpidl.obj \
.\$(OBJDIR)\xpidl_idl.obj \
.\$(OBJDIR)\xpidl_util.obj \
.\$(OBJDIR)\xpidl_header.obj \
.\$(OBJDIR)\xpidl_typelib.obj \
.\$(OBJDIR)\xpidl_doc.obj \

View File

@ -31,7 +31,7 @@ static ModeData modes[] = {
{"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch},
{"doc", "Generate HTML documentation", "html", xpidl_doc_dispatch},
{"java", "Generate Java interface", "java", xpidl_java_dispatch},
{0}
{0, 0, 0, 0}
};
static ModeData *
@ -70,42 +70,6 @@ xpidl_usage(int argc, char *argv[])
}
}
/* XXXbe static */ char OOM[] = "ERROR: out of memory\n";
void *
xpidl_malloc(size_t nbytes)
{
void *p = malloc(nbytes);
if (!p) {
fputs(OOM, stderr);
exit(1);
}
return p;
}
#ifdef XP_MAC
static char *strdup(const char *c)
{
char *newStr = malloc(strlen(c) + 1);
if (newStr)
{
strcpy(newStr, c);
}
return newStr;
}
#endif
char *
xpidl_strdup(const char *s)
{
char *ns = strdup(s);
if (!ns) {
fputs(OOM, stderr);
exit(1);
}
return ns;
}
#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
#define main xpidl_main
int xpidl_main(int argc, char *argv[]);
@ -113,7 +77,7 @@ int xpidl_main(int argc, char *argv[]);
int main(int argc, char *argv[])
{
int i, idlfiles;
int i;
IncludePathEntry *inc, *inc_head, **inc_tail;
char *file_basename = NULL;
ModeData *mode = NULL;
@ -212,12 +176,16 @@ int main(int argc, char *argv[])
xpidl_usage(argc, argv);
return 1;
}
if (argc != i + 1) {
fprintf(stderr, "ERROR: extra arguments after input file\n");
}
for (idlfiles = 0; i < argc; i++)
idlfiles += xpidl_process_idl(argv[i], inc_head, file_basename, mode);
/*
* Don't try to process multiple files, given that we don't handle -o
* multiply.
*/
if (xpidl_process_idl(argv[i], inc_head, file_basename, mode))
return 0;
if (!idlfiles)
return 1;
return 0;
return 1;
}

View File

@ -76,24 +76,28 @@ typedef struct TreeState TreeState;
*/
typedef gboolean (*nodeHandler)(TreeState *);
/* Function that produces a table of nodeHandlers for a given mode */
typedef nodeHandler *(*nodeHandlerFactory)();
extern nodeHandler *xpidl_header_dispatch(void);
extern nodeHandler *xpidl_typelib_dispatch(void);
extern nodeHandler *xpidl_doc_dispatch(void);
extern nodeHandler *xpidl_java_dispatch(void);
/*
* nodeHandler that reports an error.
* Struct containing functions to define the behavior of a given output mode.
*/
gboolean node_is_error(TreeState *state);
typedef struct backend {
nodeHandler *dispatch_table; /* nodeHandlers table, indexed by node type. */
nodeHandler emit_prolog; /* called at beginning of output generation. */
nodeHandler emit_epilog; /* called at end. */
} backend;
/* Function that produces a struct of output-generation functions */
typedef backend *(*backendFactory)();
extern backend *xpidl_header_dispatch(void);
extern backend *xpidl_typelib_dispatch(void);
extern backend *xpidl_doc_dispatch(void);
extern backend *xpidl_java_dispatch(void);
typedef struct ModeData {
char *mode;
char *modeInfo;
char *suffix;
nodeHandlerFactory factory;
backendFactory factory;
} ModeData;
typedef struct IncludePathEntry {
@ -107,16 +111,14 @@ struct TreeState {
char *basename;
IDL_ns ns;
IDL_tree tree;
GHashTable *includes;
IncludePathEntry *include_path;
GSList *base_includes;
nodeHandler *dispatch;
void *priv; /* mode-private data */
};
/*
* Process an IDL file, generating InterfaceInfo, documentation and headers as
* appropriate. Use file_basename instead of basename to avoid conflict
* warnings with basename from some versions of string.h.
* appropriate.
*/
int
xpidl_process_idl(char *filename, IncludePathEntry *include_path,
@ -167,7 +169,7 @@ xpidl_write_comment(TreeState *state, int indent);
* UUID_LENGTH bytes.
*/
gboolean
xpidl_sprint_iid(struct nsID *iid, char iidbuf[]);
xpidl_sprint_iid(nsID *iid, char iidbuf[]);
/*
* Parse a uuid string into an nsID struct. We cannot link against libxpcom,

View File

@ -26,9 +26,10 @@
* Generates documentation from javadoc-style comments in XPIDL files.
*/
nodeHandler *
backend *
xpidl_doc_dispatch(void)
{
static backend result;
static nodeHandler table[IDLN_LAST];
static gboolean initialized = FALSE;
@ -37,5 +38,6 @@ xpidl_doc_dispatch(void)
initialized = TRUE;
}
return table;
result.dispatch_table = table;
return &result;
}

View File

@ -37,32 +37,47 @@ write_indent(FILE *outfile) {
fputs(" ", outfile);
}
static void
write_header(gpointer key, gpointer value, gpointer user_data)
static gboolean
header_prolog(TreeState *state)
{
const char *ident = (const char *)value;
TreeState *state = (TreeState *)user_data;
fprintf(state->file, "#include \"%s.h\"\n",
ident);
const char *define = g_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);
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';
fprintf(state->file, "#include \"%s.h\"\n",
(char *)g_slist_nth_data(state->base_includes, i));
}
}
return TRUE;
}
static gboolean
pass_1(TreeState *state)
header_epilog(TreeState *state)
{
const char *define = g_basename(state->basename);
if (state->tree) {
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);
if (g_hash_table_size(state->includes)) {
fputc('\n', state->file);
g_hash_table_foreach(state->includes, write_header, state);
}
} else {
fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
}
fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
return TRUE;
}
@ -501,7 +516,7 @@ do_const_dcl(TreeState *state)
{
struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
const char *name = IDL_IDENT(dcl->ident).str;
gboolean success;
gboolean success, is_signed, is_long;
/* const -> list -> interface */
if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) ||
@ -517,16 +532,24 @@ do_const_dcl(TreeState *state)
if(success) {
switch(IDL_TYPE_INTEGER(dcl->const_type).f_type) {
case IDL_INTEGER_TYPE_SHORT:
is_long = FALSE;
break;
case IDL_INTEGER_TYPE_LONG:
is_long = TRUE;
break;
default:
success = FALSE;
}
is_signed = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
}
if(success) {
fprintf(state->file, "\n enum { %s = %d };\n",
name, (int) IDL_INTEGER(dcl->const_exp).value);
const char *const_format =
is_long ? (is_signed ? "%ld" : "%lu")
: (is_signed ? "%d" : "%u");
fprintf(state->file, "\n enum { %s = ", name);
fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
fprintf(state->file, " };\n");
} else {
IDL_tree_error(state->tree,
"const declaration \'%s\' must be of type short or long",
@ -770,14 +793,17 @@ codefrag(TreeState *state)
return TRUE;
}
nodeHandler *
backend *
xpidl_header_dispatch(void)
{
static backend result;
static nodeHandler table[IDLN_LAST];
static gboolean initialized = FALSE;
result.emit_prolog = header_prolog;
result.emit_epilog = header_epilog;
if (!initialized) {
table[IDLN_NONE] = pass_1;
table[IDLN_LIST] = list;
table[IDLN_ATTR_DCL] = attr_dcl;
table[IDLN_OP_DCL] = op_dcl;
@ -791,5 +817,6 @@ xpidl_header_dispatch(void)
initialized = TRUE;
}
return table;
result.dispatch_table = table;
return &result;
}

View File

@ -26,27 +26,6 @@
#include "xpidl.h"
/*
* Pass 1 generates #includes for headers and the like.
*/
static gboolean
process_tree_pass1(TreeState *state)
{
nodeHandler handler;
if ((handler = state->dispatch[0]))
return handler(state);
return TRUE;
}
gboolean
node_is_error(TreeState *state)
{
fprintf(stderr, "ERROR: Unexpected node type %d\n",
IDL_NODE_TYPE(state->tree));
return FALSE;
}
void
xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
{
@ -82,24 +61,6 @@ xpidl_process_node(TreeState *state)
return TRUE;
}
/*
* Call the IDLN_NONE handler for pre-generation, then process the tree,
* then call the IDLN_NONE handler again with state->tree == NULL for
* post-generation.
*/
static gboolean
process_tree(TreeState *state)
{
IDL_tree top = state->tree;
if (!process_tree_pass1(state))
return FALSE;
state->tree = top; /* pass1 might mutate state */
if (!xpidl_process_node(state))
return FALSE;
state->tree = NULL;
return process_tree_pass1(state);
}
#ifdef XP_MAC
extern void mac_warning(const char* warning_message);
#endif
@ -126,21 +87,21 @@ msg_callback(int level, int num, int line, const char *file,
#define INPUT_BUF_CHUNK 8192
struct input_callback_data {
typedef struct input_data {
FILE *input; /* stream for getting data */
char *filename; /* where did I come from? */
unsigned int lineno; /* last lineno processed */
unsigned int lineno; /* last lineno processed */
char *buf; /* buffer for data */
char *point; /* next char to feed to libIDL */
int start; /* are we at the start of the file? */
unsigned int len; /* amount of data read into the buffer */
unsigned int max; /* size of the buffer */
struct input_callback_data *next; /* file from which we were included */
struct input_data *next; /* file from which we were included */
int f_raw : 2, /* in a raw block when starting next block */
f_comment : 2, /* in a comment when starting next block */
f_include : 2; /* in an #include when starting next block */
char last_read[2]; /* last 1/2 chars read, for spanning blocks */
};
} input_data;
/* values for f_{raw,comment,include} */
#define INPUT_IN_NONE 0x0
@ -149,32 +110,36 @@ struct input_callback_data {
#define INPUT_IN_MAYBE 0x3 /* we might be about to start one (check
last_read to be sure) */
struct input_callback_stack {
struct input_callback_data *top;
GHashTable *includes;
typedef struct input_callback_state {
struct input_data *input_stack; /* linked list of input_data */
GHashTable *already_included; /* to prevent redundant includes */
IncludePathEntry *include_path;
};
GSList *base_includes; /* to accumulate #includes in *first* file;
* for passing thru TreeState to
* xpidl_header backend. */
} input_callback_state;
static FILE *
static FILE *
fopen_from_includes(const char *filename, const char *mode,
IncludePathEntry *include_path)
{
IncludePathEntry *current_path = include_path;
char *pathname;
FILE *file;
if (!strcmp(filename, "-"))
return stdin;
if (filename[0] != '/') {
while (include_path) {
while (current_path) {
#ifdef XP_MAC
if (!*include_path->directory)
if (!*current_path->directory)
pathname = g_strdup_printf("%s", filename);
else
pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
include_path->directory, filename);
current_path->directory, filename);
#else
pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
include_path->directory, filename);
current_path->directory, filename);
#endif
if (!pathname)
return NULL;
@ -185,7 +150,7 @@ fopen_from_includes(const char *filename, const char *mode,
free(pathname);
if (file)
return file;
include_path = include_path->next;
current_path = current_path->next;
}
} else {
file = fopen(filename, mode);
@ -199,10 +164,10 @@ fopen_from_includes(const char *filename, const char *mode,
extern FILE* mac_fopen(const char* filename, const char *mode);
#endif
static struct input_callback_data *
new_input_callback_data(const char *filename, IncludePathEntry *include_path)
static input_data *
new_input_data(const char *filename, IncludePathEntry *include_path)
{
struct input_callback_data *new_data = xpidl_malloc(sizeof *new_data);
input_data *new_data = xpidl_malloc(sizeof *new_data);
memset(new_data, 0, sizeof *new_data);
#ifdef XP_MAC
// if file is a full path name, just use fopen, otherwise search access paths.
@ -231,9 +196,10 @@ new_input_callback_data(const char *filename, IncludePathEntry *include_path)
}
static int
NextIsRaw(struct input_callback_data *data, char **startp, int *lenp)
NextIsRaw(input_data *data, char **startp, int *lenp)
{
char *end, *start, *data_end = data->buf + data->len;
char *end, *start;
char *data_end = data->buf + data->len;
#ifdef DEBUG_shaver_input
fputs("[R]", stderr);
@ -265,7 +231,7 @@ NextIsRaw(struct input_callback_data *data, char **startp, int *lenp)
}
static int
NextIsComment(struct input_callback_data *data, char **startp, int *lenp)
NextIsComment(input_data *data, char **startp, int *lenp)
{
char *end;
/* process pending comment, or rest of current one */
@ -321,9 +287,11 @@ NextIsComment(struct input_callback_data *data, char **startp, int *lenp)
}
static int
NextIsInclude(struct input_callback_stack *stack, char **startp, int *lenp)
NextIsInclude(input_callback_state *callback_state, char **startp,
int *lenp)
{
struct input_callback_data *data = stack->top, *new_data;
input_data *data = callback_state->input_stack;
input_data *new_data;
char *filename, *start, *end;
const char *scratch;
@ -367,45 +335,55 @@ NextIsInclude(struct input_callback_stack *stack, char **startp, int *lenp)
*end = '\0';
*startp = end + 1;
end = strrchr(filename, '.');
#ifdef DEBUG_shaver_inc
fprintf(stderr, "found #include %s\n", filename);
#endif
if (data->next == NULL) {
/*
* If we're in the initial file, add this filename to the list
* of filenames to be turned into #include "filename.h"
* directives in xpidl_header.c. We do it here rather than in the
* block below so it still gets added to the list even if it's
* already been included from some included file.
*/
char *filename_cp = xpidl_strdup(filename);
/* note that g_slist_append accepts and likes null as list-start. */
callback_state->base_includes =
g_slist_append(callback_state->base_includes, filename_cp);
}
/* store offset for when we pop, or if we skip this one */
data->point = *startp;
assert(stack->includes);
if (!g_hash_table_lookup(stack->includes, filename)) {
char *file_basename = filename;
assert(callback_state->already_included);
if (!g_hash_table_lookup(callback_state->already_included, filename)) {
filename = xpidl_strdup(filename);
if (end)
*end = '\0';
file_basename = xpidl_strdup(file_basename);
g_hash_table_insert(stack->includes, filename, file_basename);
new_data = new_input_callback_data(filename, stack->include_path);
g_hash_table_insert(callback_state->already_included,
filename, (void *)TRUE);
new_data = new_input_data(filename,
callback_state->include_path);
if (!new_data) {
#ifdef XP_MAC
static char warning_message[1024];
IDL_file_get(&scratch, (int *)&data->lineno);
sprintf(warning_message, "%s:%d: can't open included file %s for reading\n", scratch,
data->lineno, filename);
mac_warning(warning_message);
#else
IDL_file_get(&scratch, (int *)&data->lineno);
fprintf(stderr, "%s:%d: can't open included file %s for reading\n", scratch,
data->lineno, filename);
#endif
char *error_message;
IDL_file_get(&scratch, (int *)&data->lineno);
error_message =
g_strdup_printf("can't open included file %s for reading\n",
filename);
msg_callback(IDL_ERROR, 0 /* unused */,
data->lineno, scratch, error_message);
free(error_message);
return -1;
}
new_data->next = data;
IDL_inhibit_push();
IDL_file_get(&scratch, (int *)&data->lineno);
data = stack->top = new_data;
data = callback_state->input_stack = new_data;
IDL_file_set(data->filename, (int)data->lineno);
}
*lenp = 0; /* this is magic, see the comment below */
#ifdef DEBUG_shaver_input
fputs("1]", stderr);
@ -414,8 +392,10 @@ NextIsInclude(struct input_callback_stack *stack, char **startp, int *lenp)
}
static void
FindSpecial(struct input_callback_data *data, char **startp, int *lenp) {
char *point = data->point, *end = data->buf + data->len;
FindSpecial(input_data *data, char **startp, int *lenp)
{
char *point = data->point;
char *end = data->buf + data->len;
/* magic sequences are:
* "%{" raw block
@ -450,6 +430,16 @@ FindSpecial(struct input_callback_data *data, char **startp, int *lenp) {
#endif
}
#ifdef XP_MAC
static void cr2lf(char* str)
{
int ch;
while ((ch = *str++) != '\0') {
if (ch == '\r') str[-1] = '\n';
}
}
#endif
/* set this with a debugger to see exactly what libIDL sees */
static FILE *tracefile;
@ -457,9 +447,11 @@ static int
input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
gpointer user_data)
{
struct input_callback_stack *stack = user_data;
struct input_callback_data *data = stack->top, *new_data = NULL;
unsigned int len, copy, avail, rv;
input_callback_state *callback_state = user_data;
input_data *data = callback_state->input_stack;
input_data *new_data = NULL;
unsigned int len, copy, avail;
int rv;
char *start;
switch(reason) {
@ -472,21 +464,21 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
*/
IncludePathEntry first_entry;
first_entry.directory = stack->include_path->directory;
first_entry.directory = callback_state->include_path->directory;
first_entry.next = NULL;
new_data = new_input_callback_data(cb_data->init.filename,
new_data = new_input_data(cb_data->init.filename,
&first_entry);
} else {
new_data = new_input_callback_data(cb_data->init.filename,
stack->include_path);
new_data = new_input_data(cb_data->init.filename,
callback_state->include_path);
}
if (!new_data)
return -1;
IDL_file_set(new_data->filename, (int)new_data->lineno);
stack->top = new_data;
callback_state->input_stack = new_data;
return 0;
case IDL_INPUT_REASON_FILL:
@ -519,10 +511,10 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
fprintf(stderr, "leaving %s, returning to %s\n",
data->filename, data->next->filename);
#endif
stack->top = data->next;
callback_state->input_stack = data->next;
/* shaver: what about freeing the input structure? */
free(data);
data = stack->top;
data = callback_state->input_stack;
IDL_file_set(data->filename, (int)data->lineno);
IDL_inhibit_pop();
@ -530,6 +522,11 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
}
/* force NUL-termination on the buffer */
#ifdef XP_MAC
/* always make sure lines end with '\n' */
cr2lf(data->buf);
#endif
data->buf[data->len] = 0;
/*
@ -587,7 +584,7 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
if (rv == -1) return -1;
if (!rv) {
/* includes might need to push a new file */
rv = NextIsInclude(stack, &start, (int *)&len);
rv = NextIsInclude(callback_state, &start, (int *)&len);
if (rv == -1) return -1;
if (!rv)
/* FindSpecial can't fail? */
@ -596,7 +593,7 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
}
assert(start);
copy = MIN(len, (int) cb_data->fill.max_size);
copy = MIN(len, (unsigned int) cb_data->fill.max_size);
if (copy) {
memcpy(cb_data->fill.buffer, start, copy);
@ -630,28 +627,53 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
}
}
static void
free_ghash_key(gpointer key, gpointer value, gpointer user_data)
{
/* We're only storing TRUE in the value... */
free(key);
}
static void
free_gslist_data(gpointer data, gpointer user_data)
{
free(data);
}
/* Pick up unlink. */
#ifdef XP_UNIX
#include <unistd.h>
#elif XP_WIN
/* We get it from stdio.h. */
#endif
int
xpidl_process_idl(char *filename, IncludePathEntry *include_path,
char *file_basename, ModeData *mode)
{
char *tmp, *outname, *mode_outname;
char *tmp, *outname, *mode_outname = NULL;
IDL_tree top;
TreeState state;
int rv;
struct input_callback_stack stack;
input_callback_state callback_state;
gboolean ok;
char *fopen_mode;
backend *emitter;
/* Initialize so that stack->top, etc. doesn't come up as garbage. */
memset(&stack, 0, sizeof(struct input_callback_stack));
/*
* Initialize so that callback_state->top, etc. doesn't come up as garbage.
*/
memset(&callback_state, 0, sizeof(struct input_callback_state));
stack.includes = g_hash_table_new(g_str_hash, g_str_equal);
if (!stack.includes) {
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 (EOM?)\n");
return 0;
}
state.basename = xpidl_strdup(filename);
/* if basename has an .extension, truncate it. */
tmp = strrchr(state.basename, '.');
if (tmp)
*tmp = '\0';
@ -673,11 +695,12 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
#endif
/* so we don't include it again! */
g_hash_table_insert(stack.includes, filename, state.basename);
g_hash_table_insert(callback_state.already_included,
xpidl_strdup(filename), (void *)TRUE);
stack.include_path = include_path;
callback_state.include_path = include_path;
rv = IDL_parse_filename_with_input(filename, input_callback, &stack,
rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state,
msg_callback, &top,
&state.ns,
IDLF_IGNORE_FORWARDS |
@ -698,21 +721,18 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
if (tmp)
*tmp = '\0';
/* so we don't make a #include for it */
g_hash_table_remove(stack.includes, filename);
/* so xpidl_header.c can use it to generate a list of #include directives */
state.base_includes = callback_state.base_includes;
emitter = mode->factory();
/* assert(emitter); */
state.dispatch = emitter->dispatch_table;
state.includes = stack.includes;
state.include_path = include_path;
state.dispatch = mode->factory();
if (!state.dispatch) {
/* XXX error */
return 0;
}
if (strcmp(outname, "-")) {
mode_outname = g_strdup_printf("%s.%s", outname, mode->suffix);
fopen_mode = mode->factory == xpidl_typelib_dispatch ? "wb" : "w";
/* Use binary write for typelib mode */
fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
state.file = fopen(mode_outname, fopen_mode);
free(mode_outname);
if (!state.file) {
perror("error opening output file");
return 0;
@ -721,199 +741,39 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
state.file = stdout;
}
state.tree = top;
ok = process_tree(&state);
if (emitter->emit_prolog)
emitter->emit_prolog(&state);
ok = xpidl_process_node(&state);
if (emitter->emit_epilog)
emitter->emit_epilog(&state);
if (state.file != stdout)
fclose(state.file);
if (!ok)
return 0;
free(state.basename);
free(outname);
/* g_hash_table_foreach(state.includes, free_name, NULL);
g_hash_table_destroy(state.includes);
*/
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);
IDL_ns_free(state.ns);
IDL_tree_free(top);
return 1;
}
void
xpidl_write_comment(TreeState *state, int indent)
{
fprintf(state->file, "\n%*s/* ", indent, "");
IDL_tree_to_IDL(state->tree, state->ns, state->file,
IDLF_OUTPUT_NO_NEWLINES |
IDLF_OUTPUT_NO_QUALIFY_IDENTS |
IDLF_OUTPUT_PROPERTIES);
fputs(" */\n", state->file);
}
/*
* Print an iid to into a supplied buffer; the buffer should be at least
* UUID_LENGTH bytes.
*/
gboolean
xpidl_sprint_iid(struct nsID *id, char iidbuf[])
{
int printed;
printed = sprintf(iidbuf,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
(PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2,
(PRUint32) id->m3[0], (PRUint32) id->m3[1],
(PRUint32) id->m3[2], (PRUint32) id->m3[3],
(PRUint32) id->m3[4], (PRUint32) id->m3[5],
(PRUint32) id->m3[6], (PRUint32) id->m3[7]);
#ifdef SPRINTF_RETURNS_STRING
return (printed && strlen((char *)printed) == 36);
#else
return (printed == 36);
if (mode_outname != NULL) {
/*
* Delete partial output file on failure. Looks like this is tricky
* XP, so only enable for unix and win32. Lacking this won't hurt
* compiles of already-working IDL for mac. (NSPR code too scary
* to steal is in macio.c:_MD_Delete(). )
*/
#if defined(XP_UNIX) || defined(XP_WIN)
if (!ok)
unlink(mode_outname);
#endif
}
/* We only parse the {}-less format. (xpidl_header never has, so we're safe.) */
static const char nsIDFmt2[] =
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
/*
* Parse a uuid string into an nsID struct. We cannot link against libxpcom,
* so we re-implement nsID::Parse here.
*/
gboolean
xpidl_parse_iid(struct nsID *id, const char *str)
{
PRInt32 count = 0;
PRInt32 n1, n2, n3[8];
PRInt32 n0, i;
assert(str != NULL);
if (strlen(str) != 36) {
return FALSE;
}
#ifdef DEBUG_shaver_iid
fprintf(stderr, "parsing iid %s\n", str);
#endif
count = sscanf(str, nsIDFmt2,
&n0, &n1, &n2,
&n3[0],&n3[1],&n3[2],&n3[3],
&n3[4],&n3[5],&n3[6],&n3[7]);
id->m0 = (PRInt32) n0;
id->m1 = (PRInt16) n1;
id->m2 = (PRInt16) n2;
for (i = 0; i < 8; i++) {
id->m3[i] = (PRInt8) n3[i];
free(mode_outname);
}
#ifdef DEBUG_shaver_iid
if (count == 11) {
fprintf(stderr, "IID parsed to ");
print_IID(id, stderr);
fputs("\n", stderr);
}
#endif
return (gboolean)(count == 11);
}
/*
* Common method verification code, called by *op_dcl in the various backends.
*/
gboolean
verify_method_declaration(IDL_tree method_tree)
{
struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
IDL_tree iface;
gboolean scriptable_interface;
if (op->f_varargs) {
/* We don't currently support varargs. */
IDL_tree_error(method_tree, "varargs are not currently supported\n");
return FALSE;
}
/*
* Verify that we've been called on an interface, and decide if the
* interface was marked [scriptable].
*/
if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree)))
== IDLN_INTERFACE)
{
scriptable_interface =
(IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
!= NULL);
} else {
IDL_tree_error(method_tree, "verify_op_dcl called on a non-interface?");
return FALSE;
}
/*
* Require that any method in an interface marked as [scriptable], that
* *isn't* scriptable because it refers to some native type, be marked
* [noscript] or [notxpcom].
*/
if (scriptable_interface &&
IDL_tree_property_get(op->ident, "notxpcom") == NULL &&
IDL_tree_property_get(op->ident, "noscript") == NULL)
{
IDL_tree iter;
/* Loop through the parameters and check. */
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
IDL_tree param_type =
IDL_PARAM_DCL(IDL_LIST(iter).data).param_type_spec;
IDL_tree simple_decl =
IDL_PARAM_DCL(IDL_LIST(iter).data).simple_declarator;
/*
* Reject this method if a parameter is native and isn't marked
* with either nsid or iid_is.
*/
if (UP_IS_NATIVE(param_type) &&
IDL_tree_property_get(param_type, "nsid") == NULL &&
IDL_tree_property_get(simple_decl, "iid_is") == NULL)
{
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces which are "
"non-scriptable because they refer to native "
"types (parameter \"%s\") must be marked "
"[noscript]\n", IDL_IDENT(simple_decl).str);
return FALSE;
}
}
/* How about the return type? */
if (op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec)) {
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces which are "
"non-scriptable because they return native "
"types must be marked [noscript]\n");
return FALSE;
}
}
return TRUE;
}
/*
* Verify that a native declaration has an associated C++ expression, i.e. that
* it's of the form native <idl-name>(<c++-name>)
*/
gboolean
check_native(TreeState *state)
{
char *native_name;
/* require that native declarations give a native type */
if (IDL_NATIVE(state->tree).user_type)
return TRUE;
native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str;
IDL_tree_error(state->tree,
"``native %s;'' needs C++ type: ``native %s(<C++ type>);''",
native_name, native_name);
return FALSE;
return ok;
}
/*

View File

@ -57,47 +57,49 @@ write_classname_iid_define(FILE *file, const char *className)
return TRUE;
}
static gboolean
initial_pass(TreeState *state)
static gboolean
java_prolog(TreeState *state)
{
if (state->tree) {
state->priv = calloc(1, sizeof(struct java_priv_data));
if (!state->priv)
return FALSE;
TYPEDEFS(state) = 0;
TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
if (!TYPEDEFS(state)) {
/* XXX report error */
free(state->priv);
return FALSE;
}
/*
* First pass
*/
fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
state->file);
fprintf(state->file,
" *\n * This file was automatically generated from %s.idl.\n",
state->basename);
fputs(" */\n\n", state->file);
} else {
/* points to other elements of the tree, so just destroy the table */
g_hash_table_destroy(TYPEDEFS(state));
state->priv = calloc(1, sizeof(struct java_priv_data));
if (!state->priv)
return FALSE;
TYPEDEFS(state) = 0;
TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
if (!TYPEDEFS(state)) {
/* XXX report error */
free(state->priv);
state->priv = NULL;
/*
* Last pass
*/
fprintf(state->file, "\n/*\n * end\n */\n");
return FALSE;
}
/*
* First pass
*/
fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
state->file);
fprintf(state->file,
" *\n * This file was automatically generated from %s.idl.\n",
state->basename);
fputs(" */\n\n", state->file);
return TRUE;
}
static gboolean
java_epilog(TreeState *state)
{
/* points to other elements of the tree, so just destroy the table */
g_hash_table_destroy(TYPEDEFS(state));
free(state->priv);
state->priv = NULL;
/*
* Last pass
*/
fprintf(state->file, "\n/*\n * end\n */\n");
return TRUE;
}
@ -716,13 +718,17 @@ enum_declaration(TreeState *state)
return TRUE;
}
nodeHandler *
backend *
xpidl_java_dispatch(void)
{
static backend result;
static nodeHandler table[IDLN_LAST];
static gboolean initialized = FALSE;
if (!table[IDLN_NONE]) {
table[IDLN_NONE] = initial_pass;
result.emit_prolog = java_prolog;
result.emit_epilog = java_epilog;
if (!initialized) {
table[IDLN_INTERFACE] = interface_declaration;
table[IDLN_LIST] = process_list;
@ -734,7 +740,10 @@ xpidl_java_dispatch(void)
table[IDLN_FORWARD_DCL] = forward_declaration;
table[IDLN_TYPE_ENUM] = enum_declaration;
initialized = TRUE;
}
return table;
result.dispatch_table = table;
return &result;
}

View File

@ -339,139 +339,121 @@ typelib_list(TreeState *state)
}
static gboolean
pass_1(TreeState *state)
typelib_prolog(TreeState *state)
{
gboolean ok = FALSE;
state->priv = calloc(1, sizeof(struct priv_data));
if (!state->priv)
return FALSE;
IFACES(state) = 0;
IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
if (!IFACE_MAP(state)) {
/* XXX report error */
free(state->priv);
return FALSE;
}
/* find all interfaces, top-level and referenced by others */
IDL_tree_walk_in_order(state->tree, find_interfaces, state);
HEADER(state) = XPT_NewHeader(IFACES(state));
if (state->tree) {
state->priv = calloc(1, sizeof(struct priv_data));
if (!state->priv)
return FALSE;
IFACES(state) = 0;
IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
if (!IFACE_MAP(state)) {
/* XXX report error */
free(state->priv);
return FALSE;
/* fill IDEs from hash table */
IFACES(state) = 0;
g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
/* if any are left then we must have failed in fill_ide_table */
if (g_hash_table_size(IFACE_MAP(state)))
return FALSE;
/* sort the IDEs by IID order and store indices in the interface map */
sort_ide_block(state);
return TRUE;
}
static gboolean
typelib_epilog(TreeState *state)
{
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
XPTCursor curs, *cursor = &curs;
PRUint32 i, len, header_sz;
char *data;
/* Write any annotations */
if (emit_typelib_annotations) {
PRUint32 annotation_len, written_so_far;
char *annotate_val, *timestr;
time_t now;
static char *annotation_format =
"Created from %s.idl\nCreation date: %sInterfaces:";
/* fill in the annotations, listing resolved interfaces in order */
(void)time(&now);
timestr = ctime(&now);
/* Avoid dependence on nspr; no PR_smprintf and friends. */
/* How large should the annotation string be? */
annotation_len = strlen(annotation_format) + strlen(state->basename) +
strlen(timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
annotation_len += strlen(ide->name) + 1;
}
}
/* find all interfaces, top-level and referenced by others */
#ifdef DEBUG_shaver_ifaces
fprintf(stderr, "finding interfaces\n");
#endif
IDL_tree_walk_in_order(state->tree, find_interfaces, state);
#ifdef DEBUG_shaver_faces
fprintf(stderr, "found %d interfaces\n", IFACES(state));
#endif
HEADER(state) = XPT_NewHeader(IFACES(state));
annotate_val = (char *) malloc(annotation_len);
written_so_far = sprintf(annotate_val, annotation_format,
state->basename, timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
written_so_far += sprintf(annotate_val + written_so_far, " %s",
ide->name);
}
}
/* fill IDEs from hash table */
IFACES(state) = 0;
#ifdef DEBUG_shaver_ifaces
fprintf(stderr, "filling IDE table\n");
#endif
g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
/* if any are left then we must have failed in fill_ide_table */
if (g_hash_table_size(IFACE_MAP(state)))
return FALSE;
/* sort the IDEs by IID order and store indices in the interface map */
sort_ide_block(state);
ok = TRUE;
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.9"),
XPT_NewStringZ(annotate_val));
free(annotate_val);
} else {
/* write the typelib */
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
XPTCursor curs, *cursor = &curs;
PRUint32 i, len, header_sz;
char *data;
if(emit_typelib_annotations) {
PRUint32 annotation_len, written_so_far;
char *annotate_val, *timestr;
time_t now;
static char *annotation_format =
"Created from %s.idl\nCreation date: %sInterfaces:";
/* fill in the annotations, listing resolved interfaces in order */
(void)time(&now);
timestr = ctime(&now);
/* Avoid dependence on nspr; no PR_smprintf and friends. */
/* How large should the annotation string be? */
annotation_len = strlen(annotation_format) +
strlen(state->basename) +
strlen(timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
annotation_len += strlen(ide->name) + 1;
}
}
annotate_val = (char *) malloc(annotation_len);
written_so_far = sprintf(annotate_val, annotation_format,
state->basename, timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
written_so_far += sprintf(annotate_val + written_so_far,
" %s", ide->name);
}
}
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.9"),
XPT_NewStringZ(annotate_val));
free(annotate_val);
} else {
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST, NULL, NULL);
}
if (!HEADER(state)->annotations) {
/* XXX report out of memory error */
return FALSE;
}
#ifdef DEBUG_shaver_misc
fprintf(stderr, "writing the typelib\n");
#endif
header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
if (!xstate ||
!XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
goto destroy_header;
if (!XPT_DoHeader(cursor, &HEADER(state)))
goto destroy;
XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
fwrite(data, len, 1, state->file);
XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
fwrite(data, len, 1, state->file);
ok = TRUE;
destroy:
XPT_DestroyXDRState(xstate);
destroy_header:
/* XXX XPT_DestroyHeader(HEADER(state)) */
; /* msvc would like a statement here */
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST, NULL, NULL);
}
return ok;
if (!HEADER(state)->annotations) {
/* XXX report out of memory error */
return FALSE;
}
/* Write the typelib */
header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
if (!xstate ||
!XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
goto destroy_header;
if (!XPT_DoHeader(cursor, &HEADER(state)))
goto destroy;
XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
fwrite(data, len, 1, state->file);
XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
fwrite(data, len, 1, state->file);
destroy:
XPT_DestroyXDRState(xstate);
destroy_header:
/* XXX XPT_DestroyHeader(HEADER(state)) */
/* XXX should destroy priv_data here */
return TRUE;
}
static XPTInterfaceDirectoryEntry *
@ -1171,8 +1153,10 @@ typelib_const_dcl(TreeState *state)
}
NEXT_CONST(state)++;
} else {
XPIDL_WARNING((state->tree, IDL_WARNING1,
"const decl \'%s\' was not of type short or long, ignored", name));
IDL_tree_error(state->tree,
"const declaration \'%s\' must be of type short or long",
name);
return FALSE;
}
return TRUE;
@ -1278,24 +1262,31 @@ typelib_enum(TreeState *state)
return TRUE;
}
nodeHandler *
backend *
xpidl_typelib_dispatch(void)
{
static nodeHandler table[IDLN_LAST];
static gboolean initialized = FALSE;
static backend result;
static nodeHandler table[IDLN_LAST];
static gboolean initialized = FALSE;
if (!initialized) {
/* Initialize non-NULL elements */
table[IDLN_NONE] = pass_1;
table[IDLN_LIST] = typelib_list;
table[IDLN_ATTR_DCL] = typelib_attr_dcl;
table[IDLN_OP_DCL] = typelib_op_dcl;
table[IDLN_INTERFACE] = typelib_interface;
table[IDLN_CONST_DCL] = typelib_const_dcl;
table[IDLN_TYPE_ENUM] = typelib_enum;
table[IDLN_NATIVE] = check_native;
initialized = TRUE;
}
result.emit_prolog = typelib_prolog;
result.emit_epilog = typelib_epilog;
return table;
if (!initialized) {
/* Initialize non-NULL elements */
table[IDLN_LIST] = typelib_list;
table[IDLN_ATTR_DCL] = typelib_attr_dcl;
table[IDLN_OP_DCL] = typelib_op_dcl;
table[IDLN_INTERFACE] = typelib_interface;
table[IDLN_CONST_DCL] = typelib_const_dcl;
table[IDLN_TYPE_ENUM] = typelib_enum;
table[IDLN_NATIVE] = check_native;
initialized = TRUE;
}
result.dispatch_table = table;
return &result;
}

View File

@ -0,0 +1,242 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* Utility functions called by various backends.
*/
#include "xpidl.h"
/* XXXbe static */ char OOM[] = "ERROR: out of memory\n";
void *
xpidl_malloc(size_t nbytes)
{
void *p = malloc(nbytes);
if (!p) {
fputs(OOM, stderr);
exit(1);
}
return p;
}
#ifdef XP_MAC
static char *strdup(const char *c)
{
char *newStr = malloc(strlen(c) + 1);
if (newStr)
{
strcpy(newStr, c);
}
return newStr;
}
#endif
char *
xpidl_strdup(const char *s)
{
char *ns = strdup(s);
if (!ns) {
fputs(OOM, stderr);
exit(1);
}
return ns;
}
void
xpidl_write_comment(TreeState *state, int indent)
{
fprintf(state->file, "\n%*s/* ", indent, "");
IDL_tree_to_IDL(state->tree, state->ns, state->file,
IDLF_OUTPUT_NO_NEWLINES |
IDLF_OUTPUT_NO_QUALIFY_IDENTS |
IDLF_OUTPUT_PROPERTIES);
fputs(" */\n", state->file);
}
/*
* Print an iid to into a supplied buffer; the buffer should be at least
* UUID_LENGTH bytes.
*/
gboolean
xpidl_sprint_iid(nsID *id, char iidbuf[])
{
int printed;
printed = sprintf(iidbuf,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
(PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2,
(PRUint32) id->m3[0], (PRUint32) id->m3[1],
(PRUint32) id->m3[2], (PRUint32) id->m3[3],
(PRUint32) id->m3[4], (PRUint32) id->m3[5],
(PRUint32) id->m3[6], (PRUint32) id->m3[7]);
#ifdef SPRINTF_RETURNS_STRING
return (printed && strlen((char *)printed) == 36);
#else
return (printed == 36);
#endif
}
/* We only parse the {}-less format. (xpidl_header never has, so we're safe.) */
static const char nsIDFmt2[] =
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
/*
* Parse a uuid string into an nsID struct. We cannot link against libxpcom,
* so we re-implement nsID::Parse here.
*/
gboolean
xpidl_parse_iid(nsID *id, const char *str)
{
PRInt32 count = 0;
PRInt32 n1, n2, n3[8];
PRInt32 n0, i;
assert(str != NULL);
if (strlen(str) != 36) {
return FALSE;
}
#ifdef DEBUG_shaver_iid
fprintf(stderr, "parsing iid %s\n", str);
#endif
count = sscanf(str, nsIDFmt2,
&n0, &n1, &n2,
&n3[0],&n3[1],&n3[2],&n3[3],
&n3[4],&n3[5],&n3[6],&n3[7]);
id->m0 = (PRInt32) n0;
id->m1 = (PRInt16) n1;
id->m2 = (PRInt16) n2;
for (i = 0; i < 8; i++) {
id->m3[i] = (PRInt8) n3[i];
}
#ifdef DEBUG_shaver_iid
if (count == 11) {
fprintf(stderr, "IID parsed to ");
print_IID(id, stderr);
fputs("\n", stderr);
}
#endif
return (gboolean)(count == 11);
}
/*
* Common method verification code, called by *op_dcl in the various backends.
*/
gboolean
verify_method_declaration(IDL_tree method_tree)
{
struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
IDL_tree iface;
gboolean scriptable_interface;
if (op->f_varargs) {
/* We don't currently support varargs. */
IDL_tree_error(method_tree, "varargs are not currently supported\n");
return FALSE;
}
/*
* Verify that we've been called on an interface, and decide if the
* interface was marked [scriptable].
*/
if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree)))
== IDLN_INTERFACE)
{
scriptable_interface =
(IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
!= NULL);
} else {
IDL_tree_error(method_tree, "verify_op_dcl called on a non-interface?");
return FALSE;
}
/*
* Require that any method in an interface marked as [scriptable], that
* *isn't* scriptable because it refers to some native type, be marked
* [noscript] or [notxpcom].
*/
if (scriptable_interface &&
IDL_tree_property_get(op->ident, "notxpcom") == NULL &&
IDL_tree_property_get(op->ident, "noscript") == NULL)
{
IDL_tree iter;
/* Loop through the parameters and check. */
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
IDL_tree param_type =
IDL_PARAM_DCL(IDL_LIST(iter).data).param_type_spec;
IDL_tree simple_decl =
IDL_PARAM_DCL(IDL_LIST(iter).data).simple_declarator;
/*
* Reject this method if a parameter is native and isn't marked
* with either nsid or iid_is.
*/
if (UP_IS_NATIVE(param_type) &&
IDL_tree_property_get(param_type, "nsid") == NULL &&
IDL_tree_property_get(simple_decl, "iid_is") == NULL)
{
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces which are "
"non-scriptable because they refer to native "
"types (parameter \"%s\") must be marked "
"[noscript]\n", IDL_IDENT(simple_decl).str);
return FALSE;
}
}
/* How about the return type? */
if (op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec)) {
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces which are "
"non-scriptable because they return native "
"types must be marked [noscript]\n");
return FALSE;
}
}
return TRUE;
}
/*
* Verify that a native declaration has an associated C++ expression, i.e. that
* it's of the form native <idl-name>(<c++-name>)
*/
gboolean
check_native(TreeState *state)
{
char *native_name;
/* require that native declarations give a native type */
if (IDL_NATIVE(state->tree).user_type)
return TRUE;
native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str;
IDL_tree_error(state->tree,
"``native %s;'' needs C++ type: ``native %s(<C++ type>);''",
native_name, native_name);
return FALSE;
}