зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
5f986c1b54
Коммит
4b46863128
|
@ -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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче