зеркало из https://github.com/mozilla/pjs.git
Rework xpidl_idl to not use a circular buffer. This fixes many problems with buffer boundaries. Fixes
9716 unterminated %{ escape causes endless loop Clean up memory handling and other aspects of xpidl. Fixes 11058 bad free in xpidl 13464 memory leak in xpidl Store doc comments in IDL-processing phase, and emit them into generated header files. Fixes 24734 xpidl should emit doc comments Add error towards fixing 24965, and fix 13100 'xpidl should error on multiple inheritance' r=jband
This commit is contained in:
Родитель
2e0819a6c6
Коммит
acad3b303e
|
@ -210,4 +210,7 @@ verify_method_declaration(IDL_tree method_tree);
|
|||
gboolean
|
||||
check_native(TreeState *state);
|
||||
|
||||
void
|
||||
printlist(FILE *outfile, GSList *slist);
|
||||
|
||||
#endif /* __xpidl_h */
|
||||
|
|
|
@ -68,6 +68,8 @@ header_prolog(TreeState *state)
|
|||
fprintf(state->file, "#include \"%s.h\"\n",
|
||||
(char *)g_slist_nth_data(state->base_includes, i));
|
||||
}
|
||||
if (i > 0)
|
||||
fputc('\n', state->file);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -108,17 +110,14 @@ interface(TreeState *state)
|
|||
const char *name_space;
|
||||
struct nsID id;
|
||||
char iid_parsed[UUID_LENGTH];
|
||||
GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
|
||||
|
||||
#define FAIL do {ok = FALSE; goto out;} while(0)
|
||||
|
||||
orig = state->tree;
|
||||
|
||||
fprintf(state->file, "\n/* starting interface: %s */\n",
|
||||
className);
|
||||
|
||||
name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace");
|
||||
iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
|
||||
|
||||
if (name_space) {
|
||||
fprintf(state->file, "/* namespace: %s */\n",
|
||||
name_space);
|
||||
|
@ -126,6 +125,7 @@ interface(TreeState *state)
|
|||
name_space,className);
|
||||
}
|
||||
|
||||
iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
|
||||
if (iid) {
|
||||
/* Redundant, but a better error than 'cannot parse.' */
|
||||
if (strlen(iid) != 36) {
|
||||
|
@ -147,7 +147,6 @@ interface(TreeState *state)
|
|||
}
|
||||
|
||||
/* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */
|
||||
fputc('\n', state->file);
|
||||
fputs("#define ", state->file);
|
||||
write_classname_iid_define(state->file, className);
|
||||
fprintf(state->file, "_STR \"%s\"\n", iid_parsed);
|
||||
|
@ -166,25 +165,30 @@ interface(TreeState *state)
|
|||
fputc('\n', state->file);
|
||||
}
|
||||
|
||||
if (doc_comments != NULL)
|
||||
printlist(state->file, doc_comments);
|
||||
|
||||
/* The interface declaration itself. */
|
||||
fprintf(state->file, "class %s", className);
|
||||
if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
|
||||
fputs(" : ", state->file);
|
||||
do {
|
||||
fprintf(state->file, "public %s",
|
||||
IDL_IDENT(IDL_LIST(iter).data).str);
|
||||
if (IDL_LIST(iter).next)
|
||||
fputs(", ", state->file);
|
||||
} while ((iter = IDL_LIST(iter).next));
|
||||
if (IDL_LIST(iter).next != NULL) {
|
||||
IDL_tree_error(iter,
|
||||
"multiple inheritance is not supported by xpidl");
|
||||
FAIL;
|
||||
}
|
||||
fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str);
|
||||
}
|
||||
fputs(" {\n"
|
||||
" public: \n", state->file);
|
||||
" public: \n\n", state->file);
|
||||
if (iid) {
|
||||
fputs(" NS_DEFINE_STATIC_IID_ACCESSOR(", state->file);
|
||||
write_classname_iid_define(state->file, className);
|
||||
fputs(")\n", state->file);
|
||||
fputs(")\n\n", state->file);
|
||||
}
|
||||
|
||||
orig = state->tree; /* It would be nice to remove this state-twiddling. */
|
||||
|
||||
state->tree = IDL_INTERFACE(iface).body;
|
||||
|
||||
if (state->tree && !xpidl_process_node(state))
|
||||
|
@ -487,6 +491,27 @@ write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
|
|||
static gboolean
|
||||
attr_dcl(TreeState *state)
|
||||
{
|
||||
/*
|
||||
* XXX lists of attributes with the same type, e.g.
|
||||
* attribute string foo, bar sil;
|
||||
* are legal IDL... but we don't do anything with 'em.
|
||||
*/
|
||||
|
||||
GSList *doc_comments =
|
||||
IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
|
||||
(state->tree).simple_declarations).data).comments;
|
||||
|
||||
if (doc_comments != NULL) {
|
||||
write_indent(state->file);
|
||||
printlist(state->file, doc_comments);
|
||||
}
|
||||
|
||||
if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) {
|
||||
XPIDL_WARNING((state->tree, IDL_WARNING1,
|
||||
"multiple attributes in a single declaration aren't "
|
||||
"currently supported by xpidl"));
|
||||
}
|
||||
|
||||
xpidl_write_comment(state, 2);
|
||||
|
||||
write_indent(state->file);
|
||||
|
@ -500,6 +525,8 @@ attr_dcl(TreeState *state)
|
|||
return FALSE;
|
||||
fputs(" = 0;\n", state->file);
|
||||
}
|
||||
fputc('\n', state->file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -517,6 +544,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, is_signed;
|
||||
GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
|
||||
|
||||
/* const -> list -> interface */
|
||||
if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) ||
|
||||
|
@ -541,11 +569,17 @@ do_const_dcl(TreeState *state)
|
|||
is_signed = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
|
||||
}
|
||||
|
||||
if (doc_comments != NULL) {
|
||||
write_indent(state->file);
|
||||
printlist(state->file, doc_comments);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
const char *const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "u";
|
||||
fprintf(state->file, "\n enum { %s = ", name);
|
||||
write_indent(state->file);
|
||||
fprintf(state->file, "enum { %s = ", name);
|
||||
fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
|
||||
fprintf(state->file, " };\n");
|
||||
fprintf(state->file, " };\n\n");
|
||||
} else {
|
||||
IDL_tree_error(state->tree,
|
||||
"const declaration \'%s\' must be of type short or long",
|
||||
|
@ -558,21 +592,26 @@ do_const_dcl(TreeState *state)
|
|||
static gboolean
|
||||
do_typedef(TreeState *state)
|
||||
{
|
||||
IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec,
|
||||
dcls = IDL_TYPE_DCL(state->tree).dcls,
|
||||
complex;
|
||||
IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
|
||||
IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
|
||||
IDL_tree complex;
|
||||
GSList *doc_comments;
|
||||
|
||||
if (IDL_NODE_TYPE(type) == IDLN_TYPE_SEQUENCE) {
|
||||
XPIDL_WARNING((state->tree, IDL_WARNING1,
|
||||
"sequences not supported, ignored"));
|
||||
} else {
|
||||
state->tree = type;
|
||||
fputs("\ntypedef ", state->file);
|
||||
if (!write_type(state->tree, state->file))
|
||||
return FALSE;
|
||||
fputs(" ", state->file);
|
||||
if (IDL_NODE_TYPE(complex = IDL_LIST(dcls).data) == IDLN_TYPE_ARRAY) {
|
||||
IDL_tree dim = IDL_TYPE_ARRAY(complex).size_list;
|
||||
doc_comments = IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).comments;
|
||||
|
||||
if (doc_comments != NULL)
|
||||
printlist(state->file, doc_comments);
|
||||
|
||||
fputs("typedef ", state->file);
|
||||
if (!write_type(type, state->file))
|
||||
return FALSE;
|
||||
fputs(" ", state->file);
|
||||
|
||||
fprintf(state->file, "%s",
|
||||
IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).str);
|
||||
|
@ -585,10 +624,18 @@ do_typedef(TreeState *state)
|
|||
fputc(']', state->file);
|
||||
} while ((dim = IDL_LIST(dim).next) != NULL);
|
||||
} else {
|
||||
doc_comments = IDL_IDENT(IDL_LIST(dcls).data).comments;
|
||||
|
||||
if (doc_comments != NULL)
|
||||
printlist(state->file, doc_comments);
|
||||
|
||||
fputs("typedef ", state->file);
|
||||
if (!write_type(type, state->file))
|
||||
return FALSE;
|
||||
fputs(" ", state->file);
|
||||
fputs(IDL_IDENT(IDL_LIST(dcls).data).str, state->file);
|
||||
}
|
||||
fputs(";\n", state->file);
|
||||
fputs(";\n\n", state->file);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -634,7 +681,8 @@ write_param(IDL_tree param_tree, FILE *outfile)
|
|||
|
||||
/* arrays get a bonus * too */
|
||||
/* XXX Should this be a leading '*' or a trailing "[]" ?*/
|
||||
if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator, "array"))
|
||||
if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
|
||||
"array"))
|
||||
fputc('*', outfile);
|
||||
|
||||
fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile);
|
||||
|
@ -650,9 +698,15 @@ forward_dcl(TreeState *state)
|
|||
{
|
||||
IDL_tree iface = state->tree;
|
||||
const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
|
||||
GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
|
||||
|
||||
if (!className)
|
||||
return FALSE;
|
||||
fprintf(state->file, "class %s; /* forward decl */\n", className);
|
||||
|
||||
if (doc_comments != NULL)
|
||||
printlist(state->file, doc_comments);
|
||||
|
||||
fprintf(state->file, "class %s; /* forward declaration */\n\n", className);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -746,19 +800,25 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, gboolean as_call)
|
|||
static gboolean
|
||||
op_dcl(TreeState *state)
|
||||
{
|
||||
GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments;
|
||||
|
||||
/*
|
||||
* Verify that e.g. non-scriptable methods in [scriptable] interfaces
|
||||
* are declared so. Do this in a seperate verification pass?
|
||||
* are declared so. Do this in a separate verification pass?
|
||||
*/
|
||||
if (!verify_method_declaration(state->tree))
|
||||
return FALSE;
|
||||
|
||||
if (doc_comments != NULL) {
|
||||
write_indent(state->file);
|
||||
printlist(state->file, doc_comments);
|
||||
}
|
||||
xpidl_write_comment(state, 2);
|
||||
|
||||
write_indent(state->file);
|
||||
if (!write_method_signature(state->tree, state->file, FALSE))
|
||||
return FALSE;
|
||||
fputs(" = 0;\n", state->file);
|
||||
fputs(" = 0;\n\n", state->file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -776,6 +836,8 @@ static gboolean
|
|||
codefrag(TreeState *state)
|
||||
{
|
||||
const char *desc = IDL_CODEFRAG(state->tree).desc;
|
||||
GSList *lines = IDL_CODEFRAG(state->tree).lines;
|
||||
guint fragment_length;
|
||||
|
||||
if (strcmp(desc, "C++") && /* libIDL bug? */ strcmp(desc, "C++\r")) {
|
||||
XPIDL_WARNING((state->tree, IDL_WARNING1,
|
||||
|
@ -784,8 +846,28 @@ codefrag(TreeState *state)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
g_slist_foreach(IDL_CODEFRAG(state->tree).lines, write_codefrag_line,
|
||||
(gpointer)state);
|
||||
|
||||
/*
|
||||
* Emit #file directive to point debuggers back to the original .idl file
|
||||
* for the duration of the code fragment. We look at internal IDL node
|
||||
* properties _file, _line to do this; hopefully they won't change.
|
||||
*
|
||||
* _line seems to refer to the line immediately after the closing %}, so
|
||||
* we backtrack to get the proper line for the beginning of the block.
|
||||
*/
|
||||
/*
|
||||
* Looks like getting this right means maintaining an accurate line
|
||||
* count of everything generated, so we can set the file back to the
|
||||
* correct line in the generated file afterwards. Skipping for now...
|
||||
*/
|
||||
|
||||
fragment_length = g_slist_length(lines);
|
||||
/* fprintf(state->file, "#line %d \"%s\"\n", */
|
||||
/* state->tree->_line - fragment_length - 1, */
|
||||
/* state->tree->_file); */
|
||||
|
||||
g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,20 +26,6 @@
|
|||
|
||||
#include "xpidl.h"
|
||||
|
||||
void
|
||||
xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
|
||||
{
|
||||
IDL_tree_func_data tfd;
|
||||
|
||||
while (p) {
|
||||
struct _IDL_LIST *list = &IDL_LIST(p);
|
||||
tfd.tree = list->data;
|
||||
if (!foreach(&tfd, user_data))
|
||||
return;
|
||||
p = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The bulk of the generation happens here.
|
||||
*/
|
||||
|
@ -52,11 +38,7 @@ xpidl_process_node(TreeState *state)
|
|||
assert(state->tree);
|
||||
type = IDL_NODE_TYPE(state->tree);
|
||||
|
||||
/*
|
||||
* type == 0 shouldn't ever happen for real, so we use that slot for
|
||||
* pass-1 processing
|
||||
*/
|
||||
if (type && (dispatch = state->dispatch) && (handler = dispatch[type]))
|
||||
if ((dispatch = state->dispatch) && (handler = dispatch[type]))
|
||||
return handler(state);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -85,36 +67,28 @@ msg_callback(int level, int num, int line, const char *file,
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define INPUT_BUF_CHUNK 8192
|
||||
|
||||
/*
|
||||
* To keep track of the state associated with a given input file. The 'next'
|
||||
* field lets us maintain a stack of input files.
|
||||
*/
|
||||
typedef struct input_data {
|
||||
FILE *input; /* stream for getting data */
|
||||
char *filename; /* where did I come from? */
|
||||
unsigned int lineno; /* last lineno processed */
|
||||
char *buf; /* buffer for data */
|
||||
char *buf; /* contents of file */
|
||||
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 */
|
||||
char *max; /* 1 past last char in buf */
|
||||
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
|
||||
#define INPUT_IN_FULL 0x1 /* we've already started one */
|
||||
#define INPUT_IN_START 0x2 /* we're about to start one */
|
||||
#define INPUT_IN_MAYBE 0x3 /* we might be about to start one (check
|
||||
last_read to be sure) */
|
||||
|
||||
/*
|
||||
* Passed to us by libIDL. Holds global information and the current stack of
|
||||
* include files.
|
||||
*/
|
||||
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;
|
||||
IncludePathEntry *include_path; /* search path for included files */
|
||||
GSList *base_includes; /* to accumulate #includes from *first* file;
|
||||
* for passing thru TreeState to
|
||||
* xpidl_header backend. */
|
||||
} input_callback_state;
|
||||
|
@ -125,39 +99,28 @@ fopen_from_includes(const char *filename, const char *mode,
|
|||
{
|
||||
IncludePathEntry *current_path = include_path;
|
||||
char *pathname;
|
||||
FILE *file;
|
||||
FILE *inputfile;
|
||||
if (!strcmp(filename, "-"))
|
||||
return stdin;
|
||||
|
||||
if (filename[0] != '/') {
|
||||
while (current_path) {
|
||||
#ifdef XP_MAC
|
||||
if (!*current_path->directory)
|
||||
pathname = g_strdup_printf("%s", filename);
|
||||
else
|
||||
pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
||||
current_path->directory, filename);
|
||||
#else
|
||||
pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
||||
current_path->directory, filename);
|
||||
#endif
|
||||
pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
|
||||
current_path->directory, filename);
|
||||
if (!pathname)
|
||||
return NULL;
|
||||
#ifdef DEBUG_shaver_bufmgmt
|
||||
fprintf(stderr, "looking for %s as %s\n", filename, pathname);
|
||||
#endif
|
||||
file = fopen(pathname, mode);
|
||||
inputfile = fopen(pathname, mode);
|
||||
free(pathname);
|
||||
if (file)
|
||||
return file;
|
||||
if (inputfile)
|
||||
return inputfile;
|
||||
current_path = current_path->next;
|
||||
}
|
||||
} else {
|
||||
file = fopen(filename, mode);
|
||||
if (file)
|
||||
return file;
|
||||
inputfile = fopen(filename, mode);
|
||||
if (inputfile)
|
||||
return inputfile;
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
@ -167,123 +130,168 @@ extern FILE* mac_fopen(const char* filename, const char *mode);
|
|||
static input_data *
|
||||
new_input_data(const char *filename, IncludePathEntry *include_path)
|
||||
{
|
||||
input_data *new_data = xpidl_malloc(sizeof *new_data);
|
||||
memset(new_data, 0, sizeof *new_data);
|
||||
input_data *new_data;
|
||||
FILE *inputfile;
|
||||
char *buffer = NULL;
|
||||
size_t offset = 0;
|
||||
size_t buffer_size;
|
||||
#ifdef XP_MAC
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
// if file is a full path name, just use fopen, otherwise search access paths.
|
||||
#if 0
|
||||
if (strchr(filename, ':') == NULL)
|
||||
new_data->input = mac_fopen(filename, "r");
|
||||
inputfile = mac_fopen(filename, "r");
|
||||
else
|
||||
new_data->input = fopen(filename, "r");
|
||||
inputfile = fopen(filename, "r");
|
||||
#else
|
||||
// on Mac, fopen knows how to find files.
|
||||
new_data->input = fopen(filename, "r");
|
||||
inputfile = fopen(filename, "r");
|
||||
#endif
|
||||
#else
|
||||
new_data->input = fopen_from_includes(filename, "r", include_path);
|
||||
inputfile = fopen_from_includes(filename, "r", include_path);
|
||||
#endif
|
||||
if (!new_data->input)
|
||||
return NULL;
|
||||
new_data->buf = xpidl_malloc(INPUT_BUF_CHUNK + 1); /* trailing NUL */
|
||||
new_data->point = new_data->buf;
|
||||
new_data->max = INPUT_BUF_CHUNK;
|
||||
new_data->filename = xpidl_strdup(filename);
|
||||
|
||||
if (!inputfile)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Rather than try to keep track of many different varieties of state
|
||||
* around the boundaries of a circular buffer, we just read in the entire
|
||||
* file.
|
||||
*
|
||||
* We iteratively grow the buffer here; an alternative would be to use
|
||||
* stat to find the exact buffer size we need, as xpt_dump does.
|
||||
*/
|
||||
for (buffer_size = 8191; ; buffer_size *= 2) {
|
||||
size_t just_read;
|
||||
buffer = realloc(buffer, buffer_size + 1); /* +1 for trailing nul */
|
||||
just_read = fread(buffer + offset, 1, buffer_size - offset, inputfile);
|
||||
if (ferror(inputfile))
|
||||
return NULL;
|
||||
|
||||
if (just_read < buffer_size - offset || just_read == 0) {
|
||||
/* Done reading. */
|
||||
offset += just_read;
|
||||
break;
|
||||
}
|
||||
offset += just_read;
|
||||
}
|
||||
fclose(inputfile);
|
||||
|
||||
#ifdef XP_MAC
|
||||
/*
|
||||
* libIDL doesn't speak '\r' properly - always make sure lines end with
|
||||
* '\n'.
|
||||
*/
|
||||
for (i = 0; i < offset; i++) {
|
||||
if (buffer[i] == '\r')
|
||||
buffer[i] = '\n';
|
||||
}
|
||||
#endif
|
||||
|
||||
new_data = xpidl_malloc(sizeof (struct input_data));
|
||||
new_data->point = new_data->buf = buffer;
|
||||
new_data->max = buffer + offset;
|
||||
*new_data->max = '\0';
|
||||
new_data->filename = xpidl_strdup(filename);
|
||||
/* libIDL expects the line number to be that of the *next* line */
|
||||
new_data->lineno = 2;
|
||||
new_data->next = NULL;
|
||||
|
||||
return new_data;
|
||||
}
|
||||
|
||||
/* process pending raw section */
|
||||
static int
|
||||
NextIsRaw(input_data *data, char **startp, int *lenp)
|
||||
{
|
||||
char *end, *start;
|
||||
char *data_end = data->buf + data->len;
|
||||
|
||||
#ifdef DEBUG_shaver_input
|
||||
fputs("[R]", stderr);
|
||||
#endif
|
||||
|
||||
/* process pending raw section, or rest of current one */
|
||||
if (!(data->f_raw ||
|
||||
(data->point[0] == '%' && data->point[1] == '{')))
|
||||
/*
|
||||
* XXXmccabe still needed: an in_raw flag to handle the case where we're in
|
||||
* a raw block, but haven't managed to copy it all to xpidl. This will
|
||||
* happen when we have a raw block larger than
|
||||
* IDL_input_data->fill.max_size (currently 8192.)
|
||||
*/
|
||||
if (!(data->point[0] == '%' && data->point[1] == '{'))
|
||||
return 0;
|
||||
|
||||
start = *startp = data->point;
|
||||
|
||||
while (start < data_end && (end = strstr(start, "%}"))) {
|
||||
end = NULL;
|
||||
while (start < data->max && (end = strstr(start, "%}"))) {
|
||||
if (end[-1] == '\r' ||
|
||||
end[-1] == '\n')
|
||||
break;
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
if (end) {
|
||||
|
||||
if (end && start < data->max) {
|
||||
*lenp = end - data->point + 2;
|
||||
data->f_raw = 0;
|
||||
return 1;
|
||||
} else {
|
||||
*lenp = data->buf + data->len - data->point;
|
||||
data->f_raw = 1;
|
||||
const char *filename;
|
||||
int lineno;
|
||||
|
||||
IDL_file_get(&filename, &lineno);
|
||||
msg_callback(IDL_ERROR, 0, lineno, filename,
|
||||
"unterminated %{ block");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* process pending comment */
|
||||
static int
|
||||
NextIsComment(input_data *data, char **startp, int *lenp)
|
||||
{
|
||||
char *end;
|
||||
/* process pending comment, or rest of current one */
|
||||
|
||||
/*
|
||||
* XXX someday, my prince will come. Also, we'll upgrade to a
|
||||
* libIDL that handles comments for us.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_shaver_input
|
||||
fputs("[C]", stderr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* I tried to do the right thing by handing doc comments to libIDL, but
|
||||
* it barfed. Go figger.
|
||||
*/
|
||||
if (!(data->f_comment ||
|
||||
(data->point[0] == '/' && data->point[1] == '*')))
|
||||
if (!(data->point[0] == '/' && data->point[1] == '*'))
|
||||
return 0;
|
||||
|
||||
end = strstr(data->point, "*/");
|
||||
*lenp = 0;
|
||||
if (end) {
|
||||
int skippedLines;
|
||||
int skippedLines = 0;
|
||||
char *tempPoint;
|
||||
|
||||
/* get current lineno */
|
||||
IDL_file_get(NULL,(int *)&data->lineno);
|
||||
|
||||
/* get current lineno */
|
||||
IDL_file_get(NULL,(int *)&data->lineno);
|
||||
|
||||
*startp = data->point;
|
||||
|
||||
/* get line count */
|
||||
for(skippedLines = 0;;)
|
||||
{
|
||||
*startp = strstr(*startp,"\n");
|
||||
if (!*startp || *startp >= end)
|
||||
break;
|
||||
|
||||
*startp += 1;
|
||||
skippedLines++;
|
||||
}
|
||||
data->lineno += skippedLines;
|
||||
IDL_file_set(data->filename, (int)data->lineno);
|
||||
/* get line count */
|
||||
for (tempPoint = data->point; tempPoint < end; tempPoint++) {
|
||||
if (*tempPoint == '\n')
|
||||
skippedLines++;
|
||||
}
|
||||
|
||||
data->lineno += skippedLines;
|
||||
IDL_file_set(data->filename, (int)data->lineno);
|
||||
|
||||
*startp = end + 2;
|
||||
data->f_comment = 0;
|
||||
|
||||
/* If it's a ** comment, tell libIDL about it. */
|
||||
if (data->point[2] == '*') {
|
||||
/* hack termination. +2 to get past '*' '/' */
|
||||
char t = *(end + 2);
|
||||
*(end + 2) = '\0';
|
||||
IDL_queue_new_ident_comment(data->point);
|
||||
*(end + 2) = t;
|
||||
}
|
||||
|
||||
data->point = *startp; /* XXXmccabe move this out of function? */
|
||||
return 1;
|
||||
} else {
|
||||
*startp = data->buf + data->len;
|
||||
data->f_comment = 1;
|
||||
const char *filename;
|
||||
int lineno;
|
||||
|
||||
IDL_file_get(&filename, &lineno);
|
||||
msg_callback(IDL_ERROR, 0, lineno, filename,
|
||||
"unterminated comment");
|
||||
return -1;
|
||||
}
|
||||
data->point = *startp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -295,58 +303,53 @@ NextIsInclude(input_callback_state *callback_state, char **startp,
|
|||
char *filename, *start, *end;
|
||||
const char *scratch;
|
||||
|
||||
#ifdef DEBUG_shaver_input
|
||||
fputs("[I", stderr);
|
||||
#endif
|
||||
/* process the #include that we're in now */
|
||||
if (strncmp(data->point, "#include \"", 10)) {
|
||||
#ifdef DEBUG_shaver_input
|
||||
fputs("0]", stderr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
start = filename = data->point + 10; /* skip #include " */
|
||||
assert(start < data->buf + data->len);
|
||||
end = strchr(filename, '\"');
|
||||
if (!end) {
|
||||
/* filename probably stops at next whitespace */
|
||||
char *data_end = data->buf + data->len;
|
||||
start = end = filename - 1;
|
||||
|
||||
while (end < data_end) {
|
||||
if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t') {
|
||||
*end = '\0';
|
||||
filename = data->point + 10; /* skip #include " */
|
||||
assert(filename < data->max);
|
||||
end = filename;
|
||||
while (end < data->max) {
|
||||
if (*end == '\"' || *end == '\n' || *end == '\r')
|
||||
break;
|
||||
end++;
|
||||
}
|
||||
|
||||
if (*end != '\"') {
|
||||
/*
|
||||
* Didn't find end of include file. Scan 'til next whitespace to find
|
||||
* some reasonable approximation of the filename, and use it to report
|
||||
* an error.
|
||||
*/
|
||||
|
||||
end = filename;
|
||||
while (end < data->max) {
|
||||
if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t')
|
||||
break;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
*end = '\0';
|
||||
|
||||
/* make sure we have accurate line info */
|
||||
IDL_file_get(&scratch, (int *)&data->lineno);
|
||||
fprintf(stderr,
|
||||
"%s:%d: didn't find end of quoted include name %*s\n",
|
||||
scratch, data->lineno, end - start, start);
|
||||
"%s:%d: didn't find end of quoted include name \"%s\n",
|
||||
scratch, data->lineno, filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*end == '\r' || *end == '\n')
|
||||
IDL_file_set(NULL,(int)(++data->lineno));
|
||||
|
||||
*end = '\0';
|
||||
*startp = end + 1;
|
||||
|
||||
#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.
|
||||
* already been recursively included from some other file.
|
||||
*/
|
||||
char *filename_cp = xpidl_strdup(filename);
|
||||
|
||||
|
@ -358,36 +361,32 @@ NextIsInclude(input_callback_state *callback_state, char **startp,
|
|||
/* store offset for when we pop, or if we skip this one */
|
||||
data->point = *startp;
|
||||
|
||||
assert(callback_state->already_included);
|
||||
if (!g_hash_table_lookup(callback_state->already_included, filename)) {
|
||||
filename = xpidl_strdup(filename);
|
||||
g_hash_table_insert(callback_state->already_included,
|
||||
filename, (void *)TRUE);
|
||||
new_data = new_input_data(filename,
|
||||
callback_state->include_path);
|
||||
new_data = new_input_data(filename, callback_state->include_path);
|
||||
if (!new_data) {
|
||||
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 */,
|
||||
msg_callback(IDL_ERROR, 0,
|
||||
data->lineno, scratch, error_message);
|
||||
free(error_message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_data->next = data;
|
||||
/* tell libIDL to exclude this IDL from the toplevel tree */
|
||||
IDL_inhibit_push();
|
||||
IDL_file_get(&scratch, (int *)&data->lineno);
|
||||
data = callback_state->input_stack = new_data;
|
||||
IDL_file_set(data->filename, (int)data->lineno);
|
||||
callback_state->input_stack = new_data;
|
||||
IDL_file_set(new_data->filename, (int)new_data->lineno);
|
||||
}
|
||||
|
||||
*lenp = 0; /* this is magic, see the comment below */
|
||||
#ifdef DEBUG_shaver_input
|
||||
fputs("1]", stderr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -395,28 +394,28 @@ static void
|
|||
FindSpecial(input_data *data, char **startp, int *lenp)
|
||||
{
|
||||
char *point = data->point;
|
||||
char *end = data->buf + data->len;
|
||||
|
||||
/* magic sequences are:
|
||||
* "%{" raw block
|
||||
* "/\*" comment
|
||||
* "/\*" comment
|
||||
* "#include \"" include
|
||||
* The first and last want a newline [\r\n] before, or the start of the
|
||||
* file.
|
||||
*/
|
||||
|
||||
#define LINE_START(data, point) (data->start || \
|
||||
#define LINE_START(data, point) (point == data->buf || \
|
||||
(point > data->point && \
|
||||
(point[-1] == '\r' || point[-1] == '\n')))
|
||||
|
||||
while (point < end) {
|
||||
/* XXX unroll? */
|
||||
if (point[0] == '%' && LINE_START(data, point) && point[1] == '{')
|
||||
break;
|
||||
if (point[0] == '/' && point[1] == '*') /* && point[2] != '*') */
|
||||
break;
|
||||
if (!strncmp(point, "#include \"", 10) && LINE_START(data, point))
|
||||
while (point < data->max) {
|
||||
if (point[0] == '/' && point[1] == '*')
|
||||
break;
|
||||
if (LINE_START(data, point)) {
|
||||
if (point[0] == '%' && point[1] == '{')
|
||||
break;
|
||||
if (point[0] == '#' && !strncmp(point + 1, "include \"", 9))
|
||||
break;
|
||||
}
|
||||
point++;
|
||||
}
|
||||
|
||||
|
@ -424,22 +423,8 @@ FindSpecial(input_data *data, char **startp, int *lenp)
|
|||
|
||||
*startp = data->point;
|
||||
*lenp = point - data->point;
|
||||
#ifdef DEBUG_shaver_input
|
||||
fprintf(stderr, "*startp = offset %d, *lenp = %d\n", *startp - data->buf,
|
||||
*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;
|
||||
|
||||
|
@ -450,7 +435,7 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
input_callback_state *callback_state = user_data;
|
||||
input_data *data = callback_state->input_stack;
|
||||
input_data *new_data = NULL;
|
||||
unsigned int len, copy, avail;
|
||||
unsigned int len, copy;
|
||||
int rv;
|
||||
char *start;
|
||||
|
||||
|
@ -462,6 +447,10 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
* file, we only look for it in the first entry in the include
|
||||
* path, which we assume to be the current directory.
|
||||
*/
|
||||
|
||||
/* XXXmccabe proper assumption? Do we handle files in other
|
||||
directories? */
|
||||
|
||||
IncludePathEntry first_entry;
|
||||
|
||||
first_entry.directory = callback_state->include_path->directory;
|
||||
|
@ -482,58 +471,29 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
return 0;
|
||||
|
||||
case IDL_INPUT_REASON_FILL:
|
||||
/* get data into the buffer */
|
||||
data->start = 0;
|
||||
start = NULL;
|
||||
len = 0;
|
||||
|
||||
while (!(avail = data->buf + data->len - data->point)) {
|
||||
data->point = data->buf;
|
||||
|
||||
/* fill the buffer */
|
||||
data->len = fread(data->buf, 1, data->max, data->input);
|
||||
/* if we've got data in the buffer, no need for the tricks below */
|
||||
if (data->len) {
|
||||
data->start = 1;
|
||||
break;
|
||||
}
|
||||
if (ferror(data->input))
|
||||
return -1;
|
||||
|
||||
/* pop include */
|
||||
/* beard: what about closing the file? */
|
||||
fclose(data->input);
|
||||
data->input = NULL; /* prevent double close */
|
||||
while (data->point >= data->max) {
|
||||
if (!data->next)
|
||||
return 0;
|
||||
data->input = NULL;
|
||||
#ifdef DEBUG_shaver_includes
|
||||
fprintf(stderr, "leaving %s, returning to %s\n",
|
||||
data->filename, data->next->filename);
|
||||
#endif
|
||||
|
||||
/* Current file is done; revert to including file */
|
||||
callback_state->input_stack = data->next;
|
||||
/* shaver: what about freeing the input structure? */
|
||||
free(data->filename);
|
||||
free(data->buf);
|
||||
free(data);
|
||||
data = callback_state->input_stack;
|
||||
|
||||
IDL_file_set(data->filename, (int)data->lineno);
|
||||
IDL_inhibit_pop();
|
||||
data->f_include = INPUT_IN_NONE;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/*
|
||||
* Now we scan for sequences which require special attention:
|
||||
* \n#include begins an include statement
|
||||
* \n%{ begins a raw-source block
|
||||
* /\* begins a comment
|
||||
* /\* begins a comment
|
||||
*
|
||||
* We used to be fancier here, so make sure that we sent the most
|
||||
* data possible at any given time. To that end, we skipped over
|
||||
|
@ -544,30 +504,21 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
* state! what fun! -- so now we just do this:
|
||||
*
|
||||
* if (special at start) {
|
||||
* process that special;
|
||||
* send next chunk of data to libIDL;
|
||||
* process that special -
|
||||
* - raw: send it to libIDL, and don't look inside for specials
|
||||
* - comments: adjust point and start over
|
||||
* - includes: push new input_data struct for included file, and
|
||||
* start over
|
||||
* } else {
|
||||
* scan for next special;
|
||||
* send data up to that special to libIDL;
|
||||
* scan for next special
|
||||
* send data up to that special to libIDL
|
||||
* }
|
||||
*
|
||||
* Easy as pie. Except that libIDL takes a return of zero to mean
|
||||
* ``all done'', so whenever we would want to do that, we send a single
|
||||
* space in the buffer. Nobody'll notice, promise. (For the curious,
|
||||
* we would want to send zero bytes but be called again when we start
|
||||
* include processing or when a comment/raw follows another
|
||||
* immediately, etc.)
|
||||
*
|
||||
* XXX we don't handle the case where the \n#include or /\* or \n%{
|
||||
* sequence straddles a block boundary. We should really fix that.
|
||||
*
|
||||
* XXX we don't handle doc-comments correctly (correct would be sending
|
||||
* them to through to libIDL where they will get tokenized and made
|
||||
* available to backends that want to generate docs). When we next
|
||||
* upgrade libIDL versions, it'll handle comments for us, which will
|
||||
* help a lot.
|
||||
* If len is set to zero, it is a sentinel value indicating we a comment
|
||||
* or include was found, and parsing should start over.
|
||||
*
|
||||
* XXX const string foo = "/\*" will just screw us horribly.
|
||||
* Hm but. We could treat strings as we treat raw blocks, eh?
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -575,37 +526,43 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
* #includes within raw sections, and so that you can comment out
|
||||
* #includes.
|
||||
*/
|
||||
|
||||
/* XXX should check for errors here, too */
|
||||
rv = NextIsRaw(data, &start, (int *)&len);
|
||||
if (rv == -1) return -1;
|
||||
if (!rv) {
|
||||
/*
|
||||
* When NextIsComment succeeds, it returns a 0 len (requesting a
|
||||
* restart) and adjusts data->point to pick up after the comment.
|
||||
*/
|
||||
rv = NextIsComment(data, &start, (int *)&len);
|
||||
if (rv == -1) return -1;
|
||||
if (!rv) {
|
||||
/* includes might need to push a new file */
|
||||
/*
|
||||
* NextIsInclude might push a new input_data struct; if so, it
|
||||
* will return a 0 len, letting the callback pick up the new
|
||||
* file the next time around.
|
||||
*/
|
||||
rv = NextIsInclude(callback_state, &start, (int *)&len);
|
||||
if (rv == -1) return -1;
|
||||
if (!rv)
|
||||
/* FindSpecial can't fail? */
|
||||
FindSpecial(data, &start, (int *)&len);
|
||||
}
|
||||
}
|
||||
|
||||
assert(start);
|
||||
copy = MIN(len, (unsigned int) cb_data->fill.max_size);
|
||||
|
||||
if (copy) {
|
||||
memcpy(cb_data->fill.buffer, start, copy);
|
||||
data->point = start + copy;
|
||||
} else {
|
||||
cb_data->fill.buffer[0] = ' ';
|
||||
copy = 1;
|
||||
if (len == 0) {
|
||||
/*
|
||||
* len == 0 is a sentinel value that means we found a comment or
|
||||
* include. If we found a comment, point has been adjusted to
|
||||
* point past the comment. If we found an include, a new input_data
|
||||
* has been pushed. In both cases, calling the input_callback again
|
||||
* will pick up the new state.
|
||||
*/
|
||||
return input_callback(reason, cb_data, user_data);
|
||||
}
|
||||
#ifdef DEBUG_shaver_input
|
||||
fprintf(stderr, "COPYING %d->%.*s<-COPYING\n", copy, (int)copy,
|
||||
cb_data->fill.buffer);
|
||||
#endif
|
||||
|
||||
copy = MIN(len, (unsigned int) cb_data->fill.max_size);
|
||||
memcpy(cb_data->fill.buffer, start, copy);
|
||||
data->point = start + copy;
|
||||
|
||||
if (tracefile)
|
||||
fwrite(cb_data->fill.buffer, copy, 1, tracefile);
|
||||
|
||||
|
@ -613,12 +570,15 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
|
|||
|
||||
case IDL_INPUT_REASON_ABORT:
|
||||
case IDL_INPUT_REASON_FINISH:
|
||||
if (data->input && data->input != stdin)
|
||||
fclose(data->input);
|
||||
data->input = NULL;
|
||||
free(data->buf);
|
||||
data->buf = data->point = NULL;
|
||||
data->len = data->max = 0;
|
||||
while (data != NULL) {
|
||||
input_data *next;
|
||||
|
||||
next = data->next;
|
||||
free(data->filename);
|
||||
free(data->buf);
|
||||
free(data);
|
||||
data = next;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
@ -657,17 +617,15 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
|
|||
int rv;
|
||||
input_callback_state callback_state;
|
||||
gboolean ok;
|
||||
char *fopen_mode;
|
||||
backend *emitter;
|
||||
|
||||
/*
|
||||
* Initialize so that callback_state->top, etc. doesn't come up as garbage.
|
||||
*/
|
||||
memset(&callback_state, 0, sizeof(struct input_callback_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 (EOM?)\n");
|
||||
fprintf(stderr, "failed to create hashtable. out of memory?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -678,28 +636,15 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
|
|||
if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
#ifdef XP_MAC
|
||||
// on the Mac, we let CodeWarrior tell us where to put the output file.
|
||||
if (!file_basename) {
|
||||
outname = xpidl_strdup(filename);
|
||||
tmp = strrchr(outname, '.');
|
||||
if (tmp != NULL) *tmp = '\0';
|
||||
} else {
|
||||
outname = xpidl_strdup(file_basename);
|
||||
}
|
||||
#else
|
||||
if (!file_basename)
|
||||
outname = xpidl_strdup(state.basename);
|
||||
else
|
||||
outname = xpidl_strdup(file_basename);
|
||||
#endif
|
||||
|
||||
/* so we don't include it again! */
|
||||
g_hash_table_insert(callback_state.already_included,
|
||||
xpidl_strdup(filename), (void *)TRUE);
|
||||
|
||||
callback_state.include_path = include_path;
|
||||
|
||||
rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state,
|
||||
msg_callback, &top,
|
||||
&state.ns,
|
||||
|
@ -725,10 +670,11 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
|
|||
state.base_includes = callback_state.base_includes;
|
||||
|
||||
emitter = mode->factory();
|
||||
/* assert(emitter); */
|
||||
state.dispatch = emitter->dispatch_table;
|
||||
|
||||
if (strcmp(outname, "-")) {
|
||||
const char *fopen_mode;
|
||||
|
||||
mode_outname = g_strdup_printf("%s.%s", outname, mode->suffix);
|
||||
/* Use binary write for typelib mode */
|
||||
fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
|
||||
|
@ -761,10 +707,8 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path,
|
|||
|
||||
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(). )
|
||||
* 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)
|
||||
|
@ -800,7 +744,7 @@ xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...)
|
|||
}
|
||||
|
||||
/* call our message callback, like IDL_tree_warning would */
|
||||
msg_callback(level, 0 /* unused in callee */, lineno, file, msg);
|
||||
msg_callback(level, 0, lineno, file, msg);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
|
@ -451,6 +451,7 @@ method_declaration(TreeState *state)
|
|||
if (!verify_method_declaration(state->tree))
|
||||
return FALSE;
|
||||
|
||||
fputc('\n', state->file);
|
||||
xpidl_write_comment(state, 4);
|
||||
|
||||
/*
|
||||
|
@ -621,7 +622,8 @@ constant_declaration(TreeState *state)
|
|||
}
|
||||
|
||||
if (success) {
|
||||
xpidl_write_comment(state, 4);
|
||||
fputc('\n', state->file);
|
||||
xpidl_write_comment(state, 4);
|
||||
|
||||
fprintf(state->file, " public static final %s %s = %d;\n",
|
||||
(isshort ? "short" : "int"),
|
||||
|
@ -652,6 +654,7 @@ attribute_declaration(TreeState *state)
|
|||
|
||||
|
||||
/* Comment */
|
||||
fputc('\n', state->file);
|
||||
xpidl_write_comment(state, 4);
|
||||
|
||||
state->tree = ATTR_TYPE_DECL(state->tree);
|
||||
|
|
|
@ -65,7 +65,7 @@ xpidl_strdup(const char *s)
|
|||
void
|
||||
xpidl_write_comment(TreeState *state, int indent)
|
||||
{
|
||||
fprintf(state->file, "\n%*s/* ", indent, "");
|
||||
fprintf(state->file, "%*s/* ", indent, "");
|
||||
IDL_tree_to_IDL(state->tree, state->ns, state->file,
|
||||
IDLF_OUTPUT_NO_NEWLINES |
|
||||
IDLF_OUTPUT_NO_QUALIFY_IDENTS |
|
||||
|
@ -240,3 +240,32 @@ check_native(TreeState *state)
|
|||
native_name, native_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a GSList as char strings to a file.
|
||||
*/
|
||||
void
|
||||
printlist(FILE *outfile, GSList *slist)
|
||||
{
|
||||
guint i;
|
||||
guint len = g_slist_length(slist);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
fprintf(outfile,
|
||||
"%s\n", (char *)g_slist_nth_data(slist, i));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
|
||||
{
|
||||
IDL_tree_func_data tfd;
|
||||
|
||||
while (p) {
|
||||
struct _IDL_LIST *list = &IDL_LIST(p);
|
||||
tfd.tree = list->data;
|
||||
if (!foreach(&tfd, user_data))
|
||||
return;
|
||||
p = list->next;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче