Add dependency on libxpt and NSPR for typelib generation.

Only output |static const IID()| if we have an IID defined.
Output forward declarations.
Initial -m typelib stuff (handles methods, barely).
This commit is contained in:
shaver%netscape.com 1999-02-18 17:43:38 +00:00
Родитель 5f986c1b54
Коммит 4b46863128
8 изменённых файлов: 968 добавлений и 22 удалений

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

@ -39,7 +39,7 @@ include $(topsrcdir)/config/config.mk
CFLAGS += $(shell glib-config --cflags) CFLAGS += $(shell glib-config --cflags)
# XXX need configure test # XXX need configure test
EX_LIBS = -lIDL $(shell glib-config --libs) EX_LIBS = -lIDL -L$(DIST)/bin -lxpt $(NSPR_LIBS) $(shell glib-config --libs)
PROGS = $(OBJDIR)/xpidl PROGS = $(OBJDIR)/xpidl

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

@ -106,7 +106,7 @@ main(int argc, char *argv[])
break; break;
switch (argv[i][1]) { switch (argv[i][1]) {
case '-': case '-':
argc++; argc++; /* pretend we didn't see this */
/* fall through */ /* fall through */
case 0: /* - is a legal input filename (stdin) */ case 0: /* - is a legal input filename (stdin) */
goto done_options; goto done_options;

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

@ -123,13 +123,15 @@ interface(TreeState *state)
} }
} }
fputs(" {\n" fputs(" {\n"
" public: \n" " public: \n", state->file);
" static const nsIID& IID() {\n" if (iid) {
" static nsIID iid = ", fputs(" static const nsIID& IID() {\n"
state->file); " static nsIID iid = ",
if (!output_classname_iid_define(state->file, className)) state->file);
return FALSE; if (!output_classname_iid_define(state->file, className))
fputs(";\n return iid;\n }\n", state->file); return FALSE;
fputs(";\n return iid;\n }\n", state->file);
}
state->tree = IDL_INTERFACE(iface).body; state->tree = IDL_INTERFACE(iface).body;
@ -322,6 +324,20 @@ xpcom_param(TreeState *state)
return TRUE; return TRUE;
} }
/*
* A forward declaration, usually an interface.
*/
static gboolean
forward_dcl(TreeState *state)
{
IDL_tree iface = state->tree;
char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
if (!className)
return FALSE;
fprintf(state->file, "class %s; /* forward decl */\n", className);
return TRUE;
}
/* /*
* A method is an `operation', therefore a method decl is an `op dcl'. * A method is an `operation', therefore a method decl is an `op dcl'.
* I blame Elliot. * I blame Elliot.
@ -395,6 +411,7 @@ xpidl_header_dispatch(void)
table[IDLN_LIST] = list; table[IDLN_LIST] = list;
table[IDLN_ATTR_DCL] = attr_dcl; table[IDLN_ATTR_DCL] = attr_dcl;
table[IDLN_OP_DCL] = op_dcl; table[IDLN_OP_DCL] = op_dcl;
table[IDLN_FORWARD_DCL] = forward_dcl;
table[IDLN_TYPE_ENUM] = do_enum; table[IDLN_TYPE_ENUM] = do_enum;
table[IDLN_INTERFACE] = interface; table[IDLN_INTERFACE] = interface;
table[IDLN_CODEFRAG] = codefrag; table[IDLN_CODEFRAG] = codefrag;

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

@ -22,6 +22,458 @@
*/ */
#include "xpidl.h" #include "xpidl.h"
#include <xpt_xdr.h>
#include <xpt_struct.h>
struct priv_data {
XPTHeader *header;
uint16 ifaces;
GHashTable *interface_map;
XPTInterfaceDescriptor *current;
uint16 next_method;
};
#define HEADER(state) (((struct priv_data *)state->priv)->header)
#define IFACES(state) (((struct priv_data *)state->priv)->ifaces)
#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map)
#define CURRENT(state) (((struct priv_data *)state->priv)->current)
#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
/*
* If p is an ident for an interface, and we don't have an entry in the
* interface map yet, add one.
*/
static gboolean
add_interface_maybe(IDL_tree p, IDL_tree scope, gpointer user_data)
{
TreeState *state = user_data;
IDL_tree up;
if (IDL_NODE_TYPE(p) == IDLN_IDENT) {
if ((IDL_NODE_TYPE((up = IDL_NODE_UP(p))) == IDLN_INTERFACE)) {
char *iface = IDL_IDENT(p).str;
if (!g_hash_table_lookup(IFACE_MAP(state), iface)) {
/* XXX should we parse here and store a struct nsID *? */
char *iid = (char *)IDL_tree_property_get(up, "uuid");
if (iid)
iid = strdup(iid);
g_hash_table_insert(IFACE_MAP(state), iface, iid);
IFACES(state)++;
#ifdef DEBUG_shaver
fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
iface, iid ? iid : "<unresolved>");
#endif
}
} else {
#ifdef DEBUG_shaver
fprintf(stderr, "ident %s isn't an interface (%s)\n",
IDL_IDENT(p).str, IDL_NODE_TYPE_NAME(up));
#endif
}
}
return PR_TRUE;
}
/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
static gboolean
find_interfaces(IDL_tree p, IDL_tree scope, gpointer user_data)
{
IDL_tree node = NULL;
switch (IDL_NODE_TYPE(p)) {
case IDLN_ATTR_DCL:
node = IDL_ATTR_DCL(p).param_type_spec;
break;
case IDLN_OP_DCL:
IDL_tree_walk_in_order(IDL_OP_DCL(p).parameter_dcls, find_interfaces,
user_data);
node = IDL_OP_DCL(p).op_type_spec;
break;
case IDLN_PARAM_DCL:
node = IDL_PARAM_DCL(p).param_type_spec;
break;
case IDLN_INTERFACE:
node = IDL_INTERFACE(p).inheritance_spec;
if (node)
xpidl_list_foreach(node, add_interface_maybe, user_data);
node = IDL_INTERFACE(p).ident;
break;
default:
node = NULL;
}
if (node && IDL_NODE_TYPE(node) == IDLN_IDENT)
add_interface_maybe(node, scope, user_data);
return TRUE;
}
/* parse str and fill id */
static gboolean
fill_iid(struct nsID *id, char *str)
{
/* XXX parse! */
memset(id, 0, sizeof(struct nsID));
return TRUE;
}
/* fill the interface_directory IDE table from the interface_map */
static gboolean
fill_ide_table(gpointer key, gpointer value, gpointer user_data)
{
TreeState *state = user_data;
char *interface = key, *iid = value;
struct nsID id = {
0x00112233,
0x4455,
0x6677,
{0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
};
XPTInterfaceDirectoryEntry *ide;
#if 0
if (!fill_iid(&id, iid)) {
/* XXX report error */
return FALSE;
}
#endif
ide = &(HEADER(state)->interface_directory[IFACES(state)]);
if (!XPT_FillInterfaceDirectoryEntry(ide, &id, interface, NULL, NULL)) {
/* XXX report error */
return FALSE;;
}
IFACES(state)++;
if (iid)
free(iid);
return TRUE;
}
/* sort the IDE block as per the typelib spec: IID order, unresolved first */
static void
sort_ide_block(TreeState *state)
{
XPTInterfaceDirectoryEntry *ide;
int i;
/* XXX we should sort, but for now just enumerate */
for (i = 0; i < IFACES(state); i++) {
ide = HEADER(state)->interface_directory + i;
g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
}
return;
}
static gboolean
typelib_list(TreeState *state)
{
IDL_tree iter;
for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
return TRUE;
}
static gboolean
pass_1(TreeState *state)
{
gboolean ok = FALSE;
if (state->tree) {
state->priv = calloc(1, sizeof(struct priv_data));
if (!state->priv)
return PR_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 */
#ifdef DEBUG_shaver
fprintf(stderr, "finding interfaces\n");
#endif
IDL_tree_walk_in_order(state->tree, find_interfaces, state);
#ifdef DEBUG_shaver
fprintf(stderr, "found %d interfaces\n", IFACES(state));
#endif
HEADER(state) = XPT_NewHeader(IFACES(state));
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.1"),
XPT_NewStringZ("I should put something here."));
/* fill IDEs from hash table */
IFACES(state) = 0;
#ifdef DEBUG_shaver
fprintf(stderr, "filling IDE table\n");
#endif
g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
/* sort the IDEs by IID order and store indices in the interface map */
sort_ide_block(state);
ok = TRUE;
} else {
/* write the typelib */
char *data;
uint32 len, header_sz;
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
XPTCursor curs, *cursor = &curs;
#ifdef DEBUG_shaver
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)) */
#ifdef DEBUG_shaver
fprintf(stderr, "writing typelib was %ssuccessful\n",
ok ? "" : "not ");
#endif
}
return ok;
}
static XPTInterfaceDirectoryEntry *
FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
const char *name)
{
int i;
for (i = 0; i < num_interfaces; i++) {
if (!strcmp(ides[i].name, name))
return &ides[i];
}
return NULL;
}
static gboolean
typelib_interface(TreeState *state)
{
IDL_tree iface = state->tree, iter;
char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
XPTInterfaceDirectoryEntry *ide;
XPTInterfaceDescriptor *id;
uint16 parent_id = 0;
ide = FindInterfaceByName(HEADER(state)->interface_directory,
HEADER(state)->num_interfaces, name);
if (!ide) {
fprintf(stderr,
"ERROR: didn't find interface %s in IDE block. Giving up.\n",
name);
return FALSE;
}
if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
char *parent;
if (IDL_LIST(iter).next) {
fprintf(stderr, "ERROR: more than one parent interface for %s\n",
name);
return FALSE;
}
parent = IDL_IDENT(IDL_LIST(iter).data).str;
parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
parent);
if (!parent_id) {
fprintf(stderr, "ERROR: no index found for %s. Giving up.\n",
parent);
return FALSE;
}
}
id = XPT_NewInterfaceDescriptor(parent_id, 0, 0);
if (!id)
return FALSE;
CURRENT(state) = ide->interface_descriptor = id;
NEXT_METH(state) = 0;
state->tree = IDL_INTERFACE(iface).body;
if (state->tree && !xpidl_process_node(state))
return FALSE;
return TRUE;
}
static gboolean
fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
IDL_tree type)
{
IDL_tree up;
pd->flags = flags;
if (type) {
switch (IDL_NODE_TYPE(type)) {
case IDLN_TYPE_INTEGER: {
gboolean sign = IDL_TYPE_INTEGER(type).f_type;
switch(IDL_TYPE_INTEGER(type).f_type) {
case IDL_INTEGER_TYPE_SHORT:
pd->type.prefix.flags = sign ? TD_INT16 : TD_UINT16;
break;
case IDL_INTEGER_TYPE_LONG:
pd->type.prefix.flags = sign ? TD_INT32 : TD_UINT32;
break;
case IDL_INTEGER_TYPE_LONGLONG:
pd->type.prefix.flags = sign ? TD_INT64 : TD_UINT64;
break;
}
break;
}
case IDLN_TYPE_CHAR:
pd->type.prefix.flags = TD_CHAR;
break;
case IDLN_TYPE_WIDE_CHAR:
pd->type.prefix.flags = TD_WCHAR;
break;
case IDLN_TYPE_STRING:
pd->type.prefix.flags = TD_PSTRING; /* XXXshaver string-type? */
break;
case IDLN_TYPE_WIDE_STRING:
pd->type.prefix.flags = TD_PWSTRING;
break;
case IDLN_TYPE_BOOLEAN:
pd->type.prefix.flags = TD_BOOL;
break;
case IDLN_NATIVE:
pd->type.prefix.flags = TD_VOID | XPT_TDP_POINTER;
break;
case IDLN_IDENT:
if (!(up = IDL_NODE_UP(type))) {
fprintf(stderr, "FATAL: orphan ident %s in param list\n",
IDL_IDENT(type).str);
return FALSE;
}
switch (IDL_NODE_TYPE(up)) {
case IDLN_INTERFACE: {
XPTInterfaceDirectoryEntry *ide,
*ides = HEADER(state)->interface_directory;
uint16 num_ifaces = HEADER(state)->num_interfaces;
char *className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
pd->type.prefix.flags = TD_INTERFACE_TYPE;
ide = FindInterfaceByName(ides, num_ifaces, className);
if (!ide || ide < ides || ide > ides + num_ifaces) {
fprintf(stderr, "FATAL: unknown iface %s in params\n",
className);
return FALSE;
}
pd->type.type.interface = ide - ides + 1;
#ifdef DEBUG_shaver
fprintf(stderr, "DBG: index %d for %s\n",
pd->type.type.interface, className);
#endif
break;
}
default:
fprintf(stderr, "Can't yet handle %s ident in param list\n",
IDL_NODE_TYPE_NAME(up));
return FALSE;
}
break;
default:
fprintf(stderr, "Can't yet handle %s in param list\n",
IDL_NODE_TYPE_NAME(type));
return FALSE;
}
} else {
pd->type.prefix.flags = TD_VOID;
}
return TRUE;
}
static gboolean
fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
{
uint8 flags = 0;
switch (IDL_PARAM_DCL(tree).attr) {
case IDL_PARAM_IN:
flags = XPT_PD_IN;
break;
case IDL_PARAM_OUT:
flags = XPT_PD_OUT;
break;
case IDL_PARAM_INOUT:
flags = XPT_PD_IN | XPT_PD_OUT;
break;
}
/* XXXshaver retval */
return fill_pd_from_type(state, pd, flags,
IDL_PARAM_DCL(tree).param_type_spec);
}
static gboolean
typelib_op_dcl(TreeState *state)
{
XPTInterfaceDescriptor *id = CURRENT(state);
XPTMethodDescriptor *meth;
struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
IDL_tree iter;
uint16 num_args = 0;
uint8 op_flags = 0;
if (!XPT_InterfaceDescriptorAddMethods(id, 1))
return PR_FALSE;
meth = &id->method_descriptors[NEXT_METH(state)];
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
num_args++; /* count params */
if (op->f_noscript)
op_flags |= XPT_MD_HIDDEN;
if (op->f_varargs)
op_flags |= XPT_MD_VARARGS;
/* XXXshaver constructor? */
#ifdef DEBUG_shaver
fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
IDL_IDENT(op->ident).str, num_args);
#endif
if (!XPT_FillMethodDescriptor(meth, op_flags, IDL_IDENT(op->ident).str,
num_args))
return PR_FALSE;
for (num_args = 0, iter = op->parameter_dcls; iter;
iter = IDL_LIST(iter).next, num_args++) {
if (!fill_pd_from_param(state, &meth->params[num_args],
IDL_LIST(iter).data))
return PR_FALSE;
}
if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
op->op_type_spec))
return PR_FALSE;
NEXT_METH(state)++;
return PR_TRUE;
}
nodeHandler * nodeHandler *
xpidl_typelib_dispatch(void) xpidl_typelib_dispatch(void)
@ -30,8 +482,12 @@ xpidl_typelib_dispatch(void)
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
if (!initialized) { if (!initialized) {
/* Initialize non-NULL elements */ /* Initialize non-NULL elements */
initialized = TRUE; table[IDLN_NONE] = pass_1;
table[IDLN_LIST] = typelib_list;
table[IDLN_INTERFACE] = typelib_interface;
table[IDLN_OP_DCL] = typelib_op_dcl;
initialized = TRUE;
} }
return table; return table;

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

@ -39,7 +39,7 @@ include $(topsrcdir)/config/config.mk
CFLAGS += $(shell glib-config --cflags) CFLAGS += $(shell glib-config --cflags)
# XXX need configure test # XXX need configure test
EX_LIBS = -lIDL $(shell glib-config --libs) EX_LIBS = -lIDL -L$(DIST)/bin -lxpt $(NSPR_LIBS) $(shell glib-config --libs)
PROGS = $(OBJDIR)/xpidl PROGS = $(OBJDIR)/xpidl

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

@ -106,7 +106,7 @@ main(int argc, char *argv[])
break; break;
switch (argv[i][1]) { switch (argv[i][1]) {
case '-': case '-':
argc++; argc++; /* pretend we didn't see this */
/* fall through */ /* fall through */
case 0: /* - is a legal input filename (stdin) */ case 0: /* - is a legal input filename (stdin) */
goto done_options; goto done_options;

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

@ -123,13 +123,15 @@ interface(TreeState *state)
} }
} }
fputs(" {\n" fputs(" {\n"
" public: \n" " public: \n", state->file);
" static const nsIID& IID() {\n" if (iid) {
" static nsIID iid = ", fputs(" static const nsIID& IID() {\n"
state->file); " static nsIID iid = ",
if (!output_classname_iid_define(state->file, className)) state->file);
return FALSE; if (!output_classname_iid_define(state->file, className))
fputs(";\n return iid;\n }\n", state->file); return FALSE;
fputs(";\n return iid;\n }\n", state->file);
}
state->tree = IDL_INTERFACE(iface).body; state->tree = IDL_INTERFACE(iface).body;
@ -322,6 +324,20 @@ xpcom_param(TreeState *state)
return TRUE; return TRUE;
} }
/*
* A forward declaration, usually an interface.
*/
static gboolean
forward_dcl(TreeState *state)
{
IDL_tree iface = state->tree;
char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
if (!className)
return FALSE;
fprintf(state->file, "class %s; /* forward decl */\n", className);
return TRUE;
}
/* /*
* A method is an `operation', therefore a method decl is an `op dcl'. * A method is an `operation', therefore a method decl is an `op dcl'.
* I blame Elliot. * I blame Elliot.
@ -395,6 +411,7 @@ xpidl_header_dispatch(void)
table[IDLN_LIST] = list; table[IDLN_LIST] = list;
table[IDLN_ATTR_DCL] = attr_dcl; table[IDLN_ATTR_DCL] = attr_dcl;
table[IDLN_OP_DCL] = op_dcl; table[IDLN_OP_DCL] = op_dcl;
table[IDLN_FORWARD_DCL] = forward_dcl;
table[IDLN_TYPE_ENUM] = do_enum; table[IDLN_TYPE_ENUM] = do_enum;
table[IDLN_INTERFACE] = interface; table[IDLN_INTERFACE] = interface;
table[IDLN_CODEFRAG] = codefrag; table[IDLN_CODEFRAG] = codefrag;

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

@ -22,6 +22,458 @@
*/ */
#include "xpidl.h" #include "xpidl.h"
#include <xpt_xdr.h>
#include <xpt_struct.h>
struct priv_data {
XPTHeader *header;
uint16 ifaces;
GHashTable *interface_map;
XPTInterfaceDescriptor *current;
uint16 next_method;
};
#define HEADER(state) (((struct priv_data *)state->priv)->header)
#define IFACES(state) (((struct priv_data *)state->priv)->ifaces)
#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map)
#define CURRENT(state) (((struct priv_data *)state->priv)->current)
#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
/*
* If p is an ident for an interface, and we don't have an entry in the
* interface map yet, add one.
*/
static gboolean
add_interface_maybe(IDL_tree p, IDL_tree scope, gpointer user_data)
{
TreeState *state = user_data;
IDL_tree up;
if (IDL_NODE_TYPE(p) == IDLN_IDENT) {
if ((IDL_NODE_TYPE((up = IDL_NODE_UP(p))) == IDLN_INTERFACE)) {
char *iface = IDL_IDENT(p).str;
if (!g_hash_table_lookup(IFACE_MAP(state), iface)) {
/* XXX should we parse here and store a struct nsID *? */
char *iid = (char *)IDL_tree_property_get(up, "uuid");
if (iid)
iid = strdup(iid);
g_hash_table_insert(IFACE_MAP(state), iface, iid);
IFACES(state)++;
#ifdef DEBUG_shaver
fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
iface, iid ? iid : "<unresolved>");
#endif
}
} else {
#ifdef DEBUG_shaver
fprintf(stderr, "ident %s isn't an interface (%s)\n",
IDL_IDENT(p).str, IDL_NODE_TYPE_NAME(up));
#endif
}
}
return PR_TRUE;
}
/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
static gboolean
find_interfaces(IDL_tree p, IDL_tree scope, gpointer user_data)
{
IDL_tree node = NULL;
switch (IDL_NODE_TYPE(p)) {
case IDLN_ATTR_DCL:
node = IDL_ATTR_DCL(p).param_type_spec;
break;
case IDLN_OP_DCL:
IDL_tree_walk_in_order(IDL_OP_DCL(p).parameter_dcls, find_interfaces,
user_data);
node = IDL_OP_DCL(p).op_type_spec;
break;
case IDLN_PARAM_DCL:
node = IDL_PARAM_DCL(p).param_type_spec;
break;
case IDLN_INTERFACE:
node = IDL_INTERFACE(p).inheritance_spec;
if (node)
xpidl_list_foreach(node, add_interface_maybe, user_data);
node = IDL_INTERFACE(p).ident;
break;
default:
node = NULL;
}
if (node && IDL_NODE_TYPE(node) == IDLN_IDENT)
add_interface_maybe(node, scope, user_data);
return TRUE;
}
/* parse str and fill id */
static gboolean
fill_iid(struct nsID *id, char *str)
{
/* XXX parse! */
memset(id, 0, sizeof(struct nsID));
return TRUE;
}
/* fill the interface_directory IDE table from the interface_map */
static gboolean
fill_ide_table(gpointer key, gpointer value, gpointer user_data)
{
TreeState *state = user_data;
char *interface = key, *iid = value;
struct nsID id = {
0x00112233,
0x4455,
0x6677,
{0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
};
XPTInterfaceDirectoryEntry *ide;
#if 0
if (!fill_iid(&id, iid)) {
/* XXX report error */
return FALSE;
}
#endif
ide = &(HEADER(state)->interface_directory[IFACES(state)]);
if (!XPT_FillInterfaceDirectoryEntry(ide, &id, interface, NULL, NULL)) {
/* XXX report error */
return FALSE;;
}
IFACES(state)++;
if (iid)
free(iid);
return TRUE;
}
/* sort the IDE block as per the typelib spec: IID order, unresolved first */
static void
sort_ide_block(TreeState *state)
{
XPTInterfaceDirectoryEntry *ide;
int i;
/* XXX we should sort, but for now just enumerate */
for (i = 0; i < IFACES(state); i++) {
ide = HEADER(state)->interface_directory + i;
g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
}
return;
}
static gboolean
typelib_list(TreeState *state)
{
IDL_tree iter;
for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
return TRUE;
}
static gboolean
pass_1(TreeState *state)
{
gboolean ok = FALSE;
if (state->tree) {
state->priv = calloc(1, sizeof(struct priv_data));
if (!state->priv)
return PR_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 */
#ifdef DEBUG_shaver
fprintf(stderr, "finding interfaces\n");
#endif
IDL_tree_walk_in_order(state->tree, find_interfaces, state);
#ifdef DEBUG_shaver
fprintf(stderr, "found %d interfaces\n", IFACES(state));
#endif
HEADER(state) = XPT_NewHeader(IFACES(state));
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.1"),
XPT_NewStringZ("I should put something here."));
/* fill IDEs from hash table */
IFACES(state) = 0;
#ifdef DEBUG_shaver
fprintf(stderr, "filling IDE table\n");
#endif
g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
/* sort the IDEs by IID order and store indices in the interface map */
sort_ide_block(state);
ok = TRUE;
} else {
/* write the typelib */
char *data;
uint32 len, header_sz;
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
XPTCursor curs, *cursor = &curs;
#ifdef DEBUG_shaver
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)) */
#ifdef DEBUG_shaver
fprintf(stderr, "writing typelib was %ssuccessful\n",
ok ? "" : "not ");
#endif
}
return ok;
}
static XPTInterfaceDirectoryEntry *
FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
const char *name)
{
int i;
for (i = 0; i < num_interfaces; i++) {
if (!strcmp(ides[i].name, name))
return &ides[i];
}
return NULL;
}
static gboolean
typelib_interface(TreeState *state)
{
IDL_tree iface = state->tree, iter;
char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
XPTInterfaceDirectoryEntry *ide;
XPTInterfaceDescriptor *id;
uint16 parent_id = 0;
ide = FindInterfaceByName(HEADER(state)->interface_directory,
HEADER(state)->num_interfaces, name);
if (!ide) {
fprintf(stderr,
"ERROR: didn't find interface %s in IDE block. Giving up.\n",
name);
return FALSE;
}
if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
char *parent;
if (IDL_LIST(iter).next) {
fprintf(stderr, "ERROR: more than one parent interface for %s\n",
name);
return FALSE;
}
parent = IDL_IDENT(IDL_LIST(iter).data).str;
parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
parent);
if (!parent_id) {
fprintf(stderr, "ERROR: no index found for %s. Giving up.\n",
parent);
return FALSE;
}
}
id = XPT_NewInterfaceDescriptor(parent_id, 0, 0);
if (!id)
return FALSE;
CURRENT(state) = ide->interface_descriptor = id;
NEXT_METH(state) = 0;
state->tree = IDL_INTERFACE(iface).body;
if (state->tree && !xpidl_process_node(state))
return FALSE;
return TRUE;
}
static gboolean
fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
IDL_tree type)
{
IDL_tree up;
pd->flags = flags;
if (type) {
switch (IDL_NODE_TYPE(type)) {
case IDLN_TYPE_INTEGER: {
gboolean sign = IDL_TYPE_INTEGER(type).f_type;
switch(IDL_TYPE_INTEGER(type).f_type) {
case IDL_INTEGER_TYPE_SHORT:
pd->type.prefix.flags = sign ? TD_INT16 : TD_UINT16;
break;
case IDL_INTEGER_TYPE_LONG:
pd->type.prefix.flags = sign ? TD_INT32 : TD_UINT32;
break;
case IDL_INTEGER_TYPE_LONGLONG:
pd->type.prefix.flags = sign ? TD_INT64 : TD_UINT64;
break;
}
break;
}
case IDLN_TYPE_CHAR:
pd->type.prefix.flags = TD_CHAR;
break;
case IDLN_TYPE_WIDE_CHAR:
pd->type.prefix.flags = TD_WCHAR;
break;
case IDLN_TYPE_STRING:
pd->type.prefix.flags = TD_PSTRING; /* XXXshaver string-type? */
break;
case IDLN_TYPE_WIDE_STRING:
pd->type.prefix.flags = TD_PWSTRING;
break;
case IDLN_TYPE_BOOLEAN:
pd->type.prefix.flags = TD_BOOL;
break;
case IDLN_NATIVE:
pd->type.prefix.flags = TD_VOID | XPT_TDP_POINTER;
break;
case IDLN_IDENT:
if (!(up = IDL_NODE_UP(type))) {
fprintf(stderr, "FATAL: orphan ident %s in param list\n",
IDL_IDENT(type).str);
return FALSE;
}
switch (IDL_NODE_TYPE(up)) {
case IDLN_INTERFACE: {
XPTInterfaceDirectoryEntry *ide,
*ides = HEADER(state)->interface_directory;
uint16 num_ifaces = HEADER(state)->num_interfaces;
char *className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
pd->type.prefix.flags = TD_INTERFACE_TYPE;
ide = FindInterfaceByName(ides, num_ifaces, className);
if (!ide || ide < ides || ide > ides + num_ifaces) {
fprintf(stderr, "FATAL: unknown iface %s in params\n",
className);
return FALSE;
}
pd->type.type.interface = ide - ides + 1;
#ifdef DEBUG_shaver
fprintf(stderr, "DBG: index %d for %s\n",
pd->type.type.interface, className);
#endif
break;
}
default:
fprintf(stderr, "Can't yet handle %s ident in param list\n",
IDL_NODE_TYPE_NAME(up));
return FALSE;
}
break;
default:
fprintf(stderr, "Can't yet handle %s in param list\n",
IDL_NODE_TYPE_NAME(type));
return FALSE;
}
} else {
pd->type.prefix.flags = TD_VOID;
}
return TRUE;
}
static gboolean
fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
{
uint8 flags = 0;
switch (IDL_PARAM_DCL(tree).attr) {
case IDL_PARAM_IN:
flags = XPT_PD_IN;
break;
case IDL_PARAM_OUT:
flags = XPT_PD_OUT;
break;
case IDL_PARAM_INOUT:
flags = XPT_PD_IN | XPT_PD_OUT;
break;
}
/* XXXshaver retval */
return fill_pd_from_type(state, pd, flags,
IDL_PARAM_DCL(tree).param_type_spec);
}
static gboolean
typelib_op_dcl(TreeState *state)
{
XPTInterfaceDescriptor *id = CURRENT(state);
XPTMethodDescriptor *meth;
struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
IDL_tree iter;
uint16 num_args = 0;
uint8 op_flags = 0;
if (!XPT_InterfaceDescriptorAddMethods(id, 1))
return PR_FALSE;
meth = &id->method_descriptors[NEXT_METH(state)];
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
num_args++; /* count params */
if (op->f_noscript)
op_flags |= XPT_MD_HIDDEN;
if (op->f_varargs)
op_flags |= XPT_MD_VARARGS;
/* XXXshaver constructor? */
#ifdef DEBUG_shaver
fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
IDL_IDENT(op->ident).str, num_args);
#endif
if (!XPT_FillMethodDescriptor(meth, op_flags, IDL_IDENT(op->ident).str,
num_args))
return PR_FALSE;
for (num_args = 0, iter = op->parameter_dcls; iter;
iter = IDL_LIST(iter).next, num_args++) {
if (!fill_pd_from_param(state, &meth->params[num_args],
IDL_LIST(iter).data))
return PR_FALSE;
}
if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
op->op_type_spec))
return PR_FALSE;
NEXT_METH(state)++;
return PR_TRUE;
}
nodeHandler * nodeHandler *
xpidl_typelib_dispatch(void) xpidl_typelib_dispatch(void)
@ -30,8 +482,12 @@ xpidl_typelib_dispatch(void)
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
if (!initialized) { if (!initialized) {
/* Initialize non-NULL elements */ /* Initialize non-NULL elements */
initialized = TRUE; table[IDLN_NONE] = pass_1;
table[IDLN_LIST] = typelib_list;
table[IDLN_INTERFACE] = typelib_interface;
table[IDLN_OP_DCL] = typelib_op_dcl;
initialized = TRUE;
} }
return table; return table;