Update to 0.5.7 IDL_tree_property_get API.
Reworked input callback for cleanliness.
Add (not-yet-working) infrastructure for %{ C %} raw blocks.
This commit is contained in:
shaver%netscape.com 1998-12-09 13:08:29 +00:00
Родитель 8716e7650b
Коммит b7e56cfb2f
6 изменённых файлов: 286 добавлений и 240 удалений

Просмотреть файл

@ -33,7 +33,7 @@ gboolean generate_nothing = FALSE;
static char xpidl_usage_str[] = static char xpidl_usage_str[] =
"Usage: %s [-i] [-d] [-h] [-w] [-v] [-I path] [-n] filename.idl\n" "Usage: %s [-i] [-d] [-h] [-w] [-v] [-I path] [-n] filename.idl\n"
" -i generate InterfaceInfo data (filename.int) (NYI)\n" " -i generate InterfaceInfo data (filename.int) (NYI)\n"
" -d generate HTML documenation (filename.html) (NYI)\n" " -d generate HTML documentation (filename.html) (NYI)\n"
" -h generate C++ headers (filename.h)\n" " -h generate C++ headers (filename.h)\n"
" -w turn on warnings (recommended)\n" " -w turn on warnings (recommended)\n"
" -v verbose mode (NYI)\n" " -v verbose mode (NYI)\n"

Просмотреть файл

@ -93,7 +93,7 @@ interface(TreeState *state)
fprintf(state->file, "/* starting interface %s */\n", fprintf(state->file, "/* starting interface %s */\n",
className); className);
iid = IDL_interface_get_property(iface, "uuid"); iid = IDL_tree_property_get(iface, "uuid");
if (iid) { if (iid) {
char *iidName, *iidStruct; char *iidName, *iidStruct;
/* XXX use nsID parsing routines to validate? */ /* XXX use nsID parsing routines to validate? */

Просмотреть файл

@ -112,16 +112,27 @@ msg_callback(int level, int num, int line, const char *file,
#define INPUT_BUF_CHUNK 8192 #define INPUT_BUF_CHUNK 8192
struct input_callback_data { struct input_callback_data {
FILE *input; FILE *input; /* stream for getting data */
char *filename; char *filename; /* where did I come from? */
int lineno; int lineno; /* last lineno processed */
char *buf; char *buf; /* buffer for data */
char *point; char *point; /* next char to feed to libIDL */
int len; int len; /* amount of data read into the buffer */
int max; int max; /* size of the buffer */
struct input_callback_data *next; struct input_callback_data *next; /* file from which we were included */
char 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 */
}; };
/* 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_PART 0x3 /* we might be about to start one (check
last_read to be sure) */
struct input_callback_stack { struct input_callback_stack {
struct input_callback_data *top; struct input_callback_data *top;
GHashTable *includes; GHashTable *includes;
@ -138,7 +149,7 @@ fopen_from_includes(const char *filename, const char *mode,
filebuf = g_strdup_printf("%s/%s", include_path->directory, filename); filebuf = g_strdup_printf("%s/%s", include_path->directory, filename);
if (!filebuf) if (!filebuf)
return NULL; return NULL;
#ifdef DEBUG_shaver #ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "looking for %s as %s\n", filename, filebuf); fprintf(stderr, "looking for %s as %s\n", filename, filebuf);
#endif #endif
file = fopen(filebuf, mode); file = fopen(filebuf, mode);
@ -150,13 +161,13 @@ fopen_from_includes(const char *filename, const char *mode,
static struct input_callback_data * static struct input_callback_data *
new_input_callback_data(const char *filename, IncludePathEntry *include_path) new_input_callback_data(const char *filename, IncludePathEntry *include_path)
{ {
struct input_callback_data *new_data = malloc(sizeof *new_data); struct input_callback_data *new_data = calloc(1, sizeof *new_data);
if (!new_data) if (!new_data)
return NULL; return NULL;
new_data->input = fopen_from_includes(filename, "r", include_path); new_data->input = fopen_from_includes(filename, "r", include_path);
if (!new_data->input) if (!new_data->input)
return NULL; return NULL;
new_data->buf = malloc(INPUT_BUF_CHUNK); new_data->buf = malloc(INPUT_BUF_CHUNK + 1); /* trailing NUL */
if (!new_data->buf) { if (!new_data->buf) {
fclose(new_data->input); fclose(new_data->input);
return NULL; return NULL;
@ -182,7 +193,8 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
struct input_callback_stack *stack = user_data; struct input_callback_stack *stack = user_data;
struct input_callback_data *data = stack->top, *new_data = NULL; struct input_callback_data *data = stack->top, *new_data = NULL;
int rv, avail, copy; int rv, avail, copy;
char *include_start, *ptr; char *search, *check_point, *ptr, *end_copy, *raw_start, *comment_start,
*include_start;
switch(reason) { switch(reason) {
case IDL_INPUT_REASON_INIT: case IDL_INPUT_REASON_INIT:
@ -203,7 +215,6 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
assert(avail >= 0); assert(avail >= 0);
if (!avail) { if (!avail) {
char *comment_start = NULL, *include_start = NULL, *ptr;
data->point = data->buf; data->point = data->buf;
/* fill the buffer */ /* fill the buffer */
@ -222,78 +233,94 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
stack->top = data; stack->top = data;
IDL_file_set(data->filename, ++data->lineno); IDL_file_set(data->filename, ++data->lineno);
IDL_inhibit_pop(); IDL_inhibit_pop();
data->f_include = INPUT_IN_NONE;
goto fill_start; goto fill_start;
} }
return 0; return 0;
} }
data->buf[data->len] = 0;
/*
* strip comments
*/
/*
* XXX
* What if the last char in this block is '/' and the first in the
* next block is '*'? I'm not sure it matters, because I don't
* think there are any legal IDL syntaxes with '/' in them.
*
* XXX what about "/* " appearing in the IDL?
*/
if (!comment_start)
comment_start = strstr(data->buf, "/*");
while (comment_start) {
char *end = strstr(comment_start, "*/");
int comment_length;
int bytes_after_comment;
if (!end)
goto fill_buffer;
end += 2; /* star-slash */
comment_length = end - comment_start;
bytes_after_comment = data->buf + data->len - end;
/* found the end, move data around */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr,
"FOUND COMMENT: (%d) %.*s, moving %d back\n",
comment_length, comment_length,
comment_start, bytes_after_comment);
#endif
memmove(comment_start, end, bytes_after_comment);
comment_start[bytes_after_comment] = '\0';
data->len -= comment_length;
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "new buffer:\n---\n%.*s\n---\n",
data->len, data->buf);
#endif
/* look for the next comment */
comment_start = strstr(data->buf, "/*");
} /* while(comment_start) */
/* we set avail here, because data->len is changed above */
avail = data->buf + data->len - data->point;
} }
check_point = data->point;
end_copy = data->buf + data->len;
/* /*
* process includes * When we're stripping comments and processing #includes,
* we need to be sure that we don't process anything inside
* \n%{ and \n%}. In order to simplify things, we only process
* comment, include or raw-block stuff when they're at the
* beginning of the block we're about to send (data->point).
* This makes the processing much simpler, since we can skip
* data->point ahead for comments and #include, and skip
* check_point ahead for raw blocks.
*/ */
/* if (!(data->f_raw || data->f_comment || data->f_include)) {
* we only do #include magic at the beginning of the buffer. /* look for first raw/comment/include */
* otherwise, we just set avail to cap the amount of data sent
* on this pass. /* raw block */
*/ if ((raw_start = strstr(check_point, "\n%{"))) {
include_start = strstr(data->point, "#include \""); end_copy = raw_start;
if (include_start == data->point) { }
/* time to process the #include */
/* comment */
if ((comment_start = strstr(check_point, "/*")) &&
(!raw_start || comment_start < raw_start)) {
end_copy = comment_start;
}
/* include */
if ((include_start = strstr(check_point, "#include")) &&
(!raw_start || include_start < raw_start) &&
(!comment_start || include_start < comment_start)) {
end_copy = include_start;
}
if (end_copy == raw_start)
data->f_raw = INPUT_IN_START;
else if (end_copy == comment_start)
data->f_comment = INPUT_IN_START;
else if (end_copy == include_start)
data->f_include = INPUT_IN_START;
}
if ((end_copy == data->buf || /* just found one at the start */
end_copy == data->buf + data->len /* left over */) &&
(data->f_raw || data->f_comment || data->f_include)) {
if (data->f_raw) {
ptr = strstr(check_point, "\n%}");
if (ptr) {
data->f_raw = INPUT_IN_NONE;
end_copy = ptr + 3;
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "RAW->%.*s<-RAW\n", end_copy - data->point,
data->point);
#endif
}
assert(!data->f_comment && !data->f_include);
} else if (data->f_comment) {
/* XXX process doc comment */
ptr = strstr(check_point, "*/");
if (ptr) {
data->point = ptr + 2; /* star-slash */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "COMMENT->%.*s<-COMMENT\n",
data->point - check_point, check_point);
#endif
}
assert(!data->f_raw && !data->f_include);
} else if (data->f_include) {
/* process include */
const char *scratch; const char *scratch;
char *filename = include_start + 10; char *filename;
include_start = data->buf;
assert(!strncmp(include_start, "#include \"", 10));
filename = include_start + 10; /* skip #include " */
assert(filename < data->buf + data->len);
ptr = strchr(filename, '\"'); ptr = strchr(filename, '\"');
if (!ptr) { if (!ptr) {
/* XXX report error */ /* XXX report error */
@ -303,12 +330,12 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
*ptr = 0; *ptr = 0;
ptr = strrchr(filename, '.'); ptr = strrchr(filename, '.');
/* XXX is this a safe optimization? */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "found #include %s\n", filename);
#endif
if (!g_hash_table_lookup(stack->includes, filename)) { if (!g_hash_table_lookup(stack->includes, filename)) {
char *basename = filename; char *basename = filename;
#ifdef DEBUG_shaver_includes
fprintf(stderr, "processing #include %s\n", filename);
#endif
filename = strdup(filename); filename = strdup(filename);
ptr = strrchr(basename, '.'); ptr = strrchr(basename, '.');
if (ptr) if (ptr)
@ -326,20 +353,16 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
IDL_file_get(&scratch, &data->lineno); IDL_file_get(&scratch, &data->lineno);
data = stack->top = new_data; data = stack->top = new_data;
IDL_file_set(data->filename, data->lineno); IDL_file_set(data->filename, data->lineno);
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "processing #include %s\n", filename);
#endif
/* now continue getting data from new file */ /* now continue getting data from new file */
goto fill_start; goto fill_start;
} else {
#ifdef DEBUG_shaver_includes
fprintf(stderr, "not processing #include %s again\n",
filename);
#endif
} }
} else if (include_start) {
#ifdef DEBUG_shaver_includes
fprintf(stderr, "not processing #include yet\n");
#endif
avail = include_start - data->point;
} }
} else
avail = MIN(data->buf + data->len, end_copy) - data->point;
copy = MIN(avail, cb_data->fill.max_size); copy = MIN(avail, cb_data->fill.max_size);
memcpy(cb_data->fill.buffer, data->point, copy); memcpy(cb_data->fill.buffer, data->point, copy);
data->point += copy; data->point += copy;

Просмотреть файл

@ -33,7 +33,7 @@ gboolean generate_nothing = FALSE;
static char xpidl_usage_str[] = static char xpidl_usage_str[] =
"Usage: %s [-i] [-d] [-h] [-w] [-v] [-I path] [-n] filename.idl\n" "Usage: %s [-i] [-d] [-h] [-w] [-v] [-I path] [-n] filename.idl\n"
" -i generate InterfaceInfo data (filename.int) (NYI)\n" " -i generate InterfaceInfo data (filename.int) (NYI)\n"
" -d generate HTML documenation (filename.html) (NYI)\n" " -d generate HTML documentation (filename.html) (NYI)\n"
" -h generate C++ headers (filename.h)\n" " -h generate C++ headers (filename.h)\n"
" -w turn on warnings (recommended)\n" " -w turn on warnings (recommended)\n"
" -v verbose mode (NYI)\n" " -v verbose mode (NYI)\n"

Просмотреть файл

@ -93,7 +93,7 @@ interface(TreeState *state)
fprintf(state->file, "/* starting interface %s */\n", fprintf(state->file, "/* starting interface %s */\n",
className); className);
iid = IDL_interface_get_property(iface, "uuid"); iid = IDL_tree_property_get(iface, "uuid");
if (iid) { if (iid) {
char *iidName, *iidStruct; char *iidName, *iidStruct;
/* XXX use nsID parsing routines to validate? */ /* XXX use nsID parsing routines to validate? */

Просмотреть файл

@ -112,16 +112,27 @@ msg_callback(int level, int num, int line, const char *file,
#define INPUT_BUF_CHUNK 8192 #define INPUT_BUF_CHUNK 8192
struct input_callback_data { struct input_callback_data {
FILE *input; FILE *input; /* stream for getting data */
char *filename; char *filename; /* where did I come from? */
int lineno; int lineno; /* last lineno processed */
char *buf; char *buf; /* buffer for data */
char *point; char *point; /* next char to feed to libIDL */
int len; int len; /* amount of data read into the buffer */
int max; int max; /* size of the buffer */
struct input_callback_data *next; struct input_callback_data *next; /* file from which we were included */
char 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 */
}; };
/* 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_PART 0x3 /* we might be about to start one (check
last_read to be sure) */
struct input_callback_stack { struct input_callback_stack {
struct input_callback_data *top; struct input_callback_data *top;
GHashTable *includes; GHashTable *includes;
@ -138,7 +149,7 @@ fopen_from_includes(const char *filename, const char *mode,
filebuf = g_strdup_printf("%s/%s", include_path->directory, filename); filebuf = g_strdup_printf("%s/%s", include_path->directory, filename);
if (!filebuf) if (!filebuf)
return NULL; return NULL;
#ifdef DEBUG_shaver #ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "looking for %s as %s\n", filename, filebuf); fprintf(stderr, "looking for %s as %s\n", filename, filebuf);
#endif #endif
file = fopen(filebuf, mode); file = fopen(filebuf, mode);
@ -150,13 +161,13 @@ fopen_from_includes(const char *filename, const char *mode,
static struct input_callback_data * static struct input_callback_data *
new_input_callback_data(const char *filename, IncludePathEntry *include_path) new_input_callback_data(const char *filename, IncludePathEntry *include_path)
{ {
struct input_callback_data *new_data = malloc(sizeof *new_data); struct input_callback_data *new_data = calloc(1, sizeof *new_data);
if (!new_data) if (!new_data)
return NULL; return NULL;
new_data->input = fopen_from_includes(filename, "r", include_path); new_data->input = fopen_from_includes(filename, "r", include_path);
if (!new_data->input) if (!new_data->input)
return NULL; return NULL;
new_data->buf = malloc(INPUT_BUF_CHUNK); new_data->buf = malloc(INPUT_BUF_CHUNK + 1); /* trailing NUL */
if (!new_data->buf) { if (!new_data->buf) {
fclose(new_data->input); fclose(new_data->input);
return NULL; return NULL;
@ -182,7 +193,8 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
struct input_callback_stack *stack = user_data; struct input_callback_stack *stack = user_data;
struct input_callback_data *data = stack->top, *new_data = NULL; struct input_callback_data *data = stack->top, *new_data = NULL;
int rv, avail, copy; int rv, avail, copy;
char *include_start, *ptr; char *search, *check_point, *ptr, *end_copy, *raw_start, *comment_start,
*include_start;
switch(reason) { switch(reason) {
case IDL_INPUT_REASON_INIT: case IDL_INPUT_REASON_INIT:
@ -203,7 +215,6 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
assert(avail >= 0); assert(avail >= 0);
if (!avail) { if (!avail) {
char *comment_start = NULL, *include_start = NULL, *ptr;
data->point = data->buf; data->point = data->buf;
/* fill the buffer */ /* fill the buffer */
@ -222,78 +233,94 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
stack->top = data; stack->top = data;
IDL_file_set(data->filename, ++data->lineno); IDL_file_set(data->filename, ++data->lineno);
IDL_inhibit_pop(); IDL_inhibit_pop();
data->f_include = INPUT_IN_NONE;
goto fill_start; goto fill_start;
} }
return 0; return 0;
} }
data->buf[data->len] = 0;
/*
* strip comments
*/
/*
* XXX
* What if the last char in this block is '/' and the first in the
* next block is '*'? I'm not sure it matters, because I don't
* think there are any legal IDL syntaxes with '/' in them.
*
* XXX what about "/* " appearing in the IDL?
*/
if (!comment_start)
comment_start = strstr(data->buf, "/*");
while (comment_start) {
char *end = strstr(comment_start, "*/");
int comment_length;
int bytes_after_comment;
if (!end)
goto fill_buffer;
end += 2; /* star-slash */
comment_length = end - comment_start;
bytes_after_comment = data->buf + data->len - end;
/* found the end, move data around */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr,
"FOUND COMMENT: (%d) %.*s, moving %d back\n",
comment_length, comment_length,
comment_start, bytes_after_comment);
#endif
memmove(comment_start, end, bytes_after_comment);
comment_start[bytes_after_comment] = '\0';
data->len -= comment_length;
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "new buffer:\n---\n%.*s\n---\n",
data->len, data->buf);
#endif
/* look for the next comment */
comment_start = strstr(data->buf, "/*");
} /* while(comment_start) */
/* we set avail here, because data->len is changed above */
avail = data->buf + data->len - data->point;
} }
check_point = data->point;
end_copy = data->buf + data->len;
/* /*
* process includes * When we're stripping comments and processing #includes,
* we need to be sure that we don't process anything inside
* \n%{ and \n%}. In order to simplify things, we only process
* comment, include or raw-block stuff when they're at the
* beginning of the block we're about to send (data->point).
* This makes the processing much simpler, since we can skip
* data->point ahead for comments and #include, and skip
* check_point ahead for raw blocks.
*/ */
/* if (!(data->f_raw || data->f_comment || data->f_include)) {
* we only do #include magic at the beginning of the buffer. /* look for first raw/comment/include */
* otherwise, we just set avail to cap the amount of data sent
* on this pass. /* raw block */
*/ if ((raw_start = strstr(check_point, "\n%{"))) {
include_start = strstr(data->point, "#include \""); end_copy = raw_start;
if (include_start == data->point) { }
/* time to process the #include */
/* comment */
if ((comment_start = strstr(check_point, "/*")) &&
(!raw_start || comment_start < raw_start)) {
end_copy = comment_start;
}
/* include */
if ((include_start = strstr(check_point, "#include")) &&
(!raw_start || include_start < raw_start) &&
(!comment_start || include_start < comment_start)) {
end_copy = include_start;
}
if (end_copy == raw_start)
data->f_raw = INPUT_IN_START;
else if (end_copy == comment_start)
data->f_comment = INPUT_IN_START;
else if (end_copy == include_start)
data->f_include = INPUT_IN_START;
}
if ((end_copy == data->buf || /* just found one at the start */
end_copy == data->buf + data->len /* left over */) &&
(data->f_raw || data->f_comment || data->f_include)) {
if (data->f_raw) {
ptr = strstr(check_point, "\n%}");
if (ptr) {
data->f_raw = INPUT_IN_NONE;
end_copy = ptr + 3;
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "RAW->%.*s<-RAW\n", end_copy - data->point,
data->point);
#endif
}
assert(!data->f_comment && !data->f_include);
} else if (data->f_comment) {
/* XXX process doc comment */
ptr = strstr(check_point, "*/");
if (ptr) {
data->point = ptr + 2; /* star-slash */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "COMMENT->%.*s<-COMMENT\n",
data->point - check_point, check_point);
#endif
}
assert(!data->f_raw && !data->f_include);
} else if (data->f_include) {
/* process include */
const char *scratch; const char *scratch;
char *filename = include_start + 10; char *filename;
include_start = data->buf;
assert(!strncmp(include_start, "#include \"", 10));
filename = include_start + 10; /* skip #include " */
assert(filename < data->buf + data->len);
ptr = strchr(filename, '\"'); ptr = strchr(filename, '\"');
if (!ptr) { if (!ptr) {
/* XXX report error */ /* XXX report error */
@ -303,12 +330,12 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
*ptr = 0; *ptr = 0;
ptr = strrchr(filename, '.'); ptr = strrchr(filename, '.');
/* XXX is this a safe optimization? */
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "found #include %s\n", filename);
#endif
if (!g_hash_table_lookup(stack->includes, filename)) { if (!g_hash_table_lookup(stack->includes, filename)) {
char *basename = filename; char *basename = filename;
#ifdef DEBUG_shaver_includes
fprintf(stderr, "processing #include %s\n", filename);
#endif
filename = strdup(filename); filename = strdup(filename);
ptr = strrchr(basename, '.'); ptr = strrchr(basename, '.');
if (ptr) if (ptr)
@ -326,20 +353,16 @@ input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
IDL_file_get(&scratch, &data->lineno); IDL_file_get(&scratch, &data->lineno);
data = stack->top = new_data; data = stack->top = new_data;
IDL_file_set(data->filename, data->lineno); IDL_file_set(data->filename, data->lineno);
#ifdef DEBUG_shaver_bufmgmt
fprintf(stderr, "processing #include %s\n", filename);
#endif
/* now continue getting data from new file */ /* now continue getting data from new file */
goto fill_start; goto fill_start;
} else {
#ifdef DEBUG_shaver_includes
fprintf(stderr, "not processing #include %s again\n",
filename);
#endif
} }
} else if (include_start) {
#ifdef DEBUG_shaver_includes
fprintf(stderr, "not processing #include yet\n");
#endif
avail = include_start - data->point;
} }
} else
avail = MIN(data->buf + data->len, end_copy) - data->point;
copy = MIN(avail, cb_data->fill.max_size); copy = MIN(avail, cb_data->fill.max_size);
memcpy(cb_data->fill.buffer, data->point, copy); memcpy(cb_data->fill.buffer, data->point, copy);
data->point += copy; data->point += copy;