Fixed IID copying (duh -- all the bytes matter).
NewString and NewStringZ APIs. No more bit-fields (nod to jband and fur, thanks). Cleaned up Annotation structures. On-disk offsets are 1-based. Write annotations to disk, and account for them in header size, etc. Fix sundry cursor-vs-&cursor bugs and don't-allocate-on-decode bugs. Write MethodDescriptors and InterfaceDescriptors to disk! Executive Summary: can now write very simple .xpt files! git-svn-id: svn://10.0.0.236/trunk@18505 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -47,8 +47,6 @@ typedef struct XPTTypeDescriptor XPTTypeDescriptor;
|
||||
typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
|
||||
typedef struct XPTString XPTString;
|
||||
typedef struct XPTAnnotation XPTAnnotation;
|
||||
typedef struct XPTAnnotationPrefix XPTAnnotationPrefix;
|
||||
typedef struct XPTPrivateAnnotation XPTPrivateAnnotation;
|
||||
#ifndef nsID_h__
|
||||
/*
|
||||
* We can't include nsID.h, because it's full of C++ goop and we're not doing
|
||||
@@ -72,7 +70,11 @@ typedef struct nsID nsID;
|
||||
(to).m3[0] = (from).m3[0]; \
|
||||
(to).m3[1] = (from).m3[1]; \
|
||||
(to).m3[2] = (from).m3[2]; \
|
||||
(to).m3[3] = (from).m3[3];
|
||||
(to).m3[3] = (from).m3[3]; \
|
||||
(to).m3[4] = (from).m3[4]; \
|
||||
(to).m3[5] = (from).m3[5]; \
|
||||
(to).m3[6] = (from).m3[6]; \
|
||||
(to).m3[7] = (from).m3[7];
|
||||
|
||||
|
||||
/*
|
||||
@@ -151,7 +153,10 @@ struct XPTString {
|
||||
};
|
||||
|
||||
XPTString *
|
||||
XPT_NewString(char *bytes, uint16 len);
|
||||
XPT_NewString(uint16 length, char *bytes);
|
||||
|
||||
XPTString *
|
||||
XPT_NewStringZ(char *bytes);
|
||||
|
||||
/*
|
||||
* A TypeDescriptor is a variable-size record used to identify the type of a
|
||||
@@ -170,11 +175,21 @@ XPT_NewString(char *bytes, uint16 len);
|
||||
* InterfaceIsTypeDescriptor.
|
||||
*/
|
||||
|
||||
/* XXX why bother with a struct? */
|
||||
struct XPTTypeDescriptorPrefix {
|
||||
uint8 is_pointer:1, is_unique_pointer:1, is_reference:1,
|
||||
tag:5;
|
||||
uint8 flags;
|
||||
};
|
||||
|
||||
/* flag bits -- fur and jband were right, I was miserably wrong */
|
||||
#define XPT_TDP_POINTER 0x80
|
||||
#define XPT_TDP_UNIQUE_POINTER 0x40
|
||||
#define XPT_TDP_REFERENCE 0x20
|
||||
#define XPT_TDP_FLAGMASK 0xe0
|
||||
#define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK)
|
||||
#define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK)
|
||||
|
||||
/* XXX TD #defines should include required flag bits! */
|
||||
|
||||
/*
|
||||
* The following defines map mnemonic names to the different numeric values
|
||||
* of XPTTypeDescriptor->tag when XPTTypeDescriptor->is_pointer is FALSE.
|
||||
@@ -241,12 +256,11 @@ struct XPTTypeDescriptor {
|
||||
} type;
|
||||
};
|
||||
|
||||
#define XPT_COPY_TYPE(to, from) \
|
||||
(to).prefix.is_pointer = (from).prefix.is_pointer; \
|
||||
(to).prefix.is_unique_pointer = (from).prefix.is_unique_pointer; \
|
||||
(to).prefix.is_reference = (from).prefix.is_reference; \
|
||||
(to).prefix.tag = (from).prefix.tag; \
|
||||
(to).type.interface = (from).type.interface
|
||||
#define XPT_TYPEDESCRIPTOR_SIZE (1 + 4)
|
||||
|
||||
#define XPT_COPY_TYPE(to, from) \
|
||||
(to).prefix.flags = (from).prefix.flags; \
|
||||
(to).type.interface = (from).type.interface;
|
||||
|
||||
/*
|
||||
* A ConstDescriptor is a variable-size record that records the name and
|
||||
@@ -290,31 +304,44 @@ struct XPTConstDescriptor {
|
||||
* single argument to a method or a method's result.
|
||||
*/
|
||||
struct XPTParamDescriptor {
|
||||
uint8 in:1, out:1, retval:1, reserved:5;
|
||||
uint8 flags;
|
||||
XPTTypeDescriptor type;
|
||||
};
|
||||
|
||||
/* flag bits -- jband and fur were right, and I was miserably wrong */
|
||||
#define XPT_PD_IN 0x80
|
||||
#define XPT_PD_OUT 0x40
|
||||
#define XPT_PD_RETVAL 0x20
|
||||
#define XPT_PD_FLAGMASK 0x70
|
||||
|
||||
#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1)
|
||||
|
||||
PRBool
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRBool in, PRBool out,
|
||||
PRBool retval, XPTTypeDescriptor type);
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, uint8 flags,
|
||||
XPTTypeDescriptor *type);
|
||||
|
||||
/*
|
||||
* A MethodDescriptor is a variable-size record used to describe a single
|
||||
* interface method.
|
||||
*/
|
||||
struct XPTMethodDescriptor {
|
||||
uint8 is_getter:1, is_setter:1, is_varargs:1,
|
||||
is_constructor:1, is_hidden:1, reserved:3;
|
||||
uint8 flags;
|
||||
char *name;
|
||||
uint8 num_args;
|
||||
XPTParamDescriptor *params;
|
||||
XPTParamDescriptor *result;
|
||||
};
|
||||
|
||||
/* flag bits -- jband and fur were right, and I was miserably wrong */
|
||||
#define XPT_MD_GETTER 0x80
|
||||
#define XPT_MD_SETTER 0x40
|
||||
#define XPT_MD_VARARGS 0x20
|
||||
#define XPT_MD_CTOR 0x10
|
||||
#define XPT_MD_HIDDEN 0x08
|
||||
#define XPT_MD_FLAGMASK 0xf8
|
||||
|
||||
PRBool
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
PRBool is_setter, PRBool is_varargs,
|
||||
PRBool is_constructor, PRBool is_hidden, char *name,
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, uint8 flags, char *name,
|
||||
uint8 num_args);
|
||||
|
||||
/*
|
||||
@@ -335,26 +362,21 @@ XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
* indicate an array of Annotation's that's completely empty. If the tag
|
||||
* is 1, the record is a PrivateAnnotation.
|
||||
*/
|
||||
#define EMPTY_ANNOTATION 0
|
||||
#define PRIVATE_ANNOTATION 1
|
||||
|
||||
struct XPTAnnotationPrefix {
|
||||
uint8 is_last:1, tag:7;
|
||||
};
|
||||
|
||||
struct XPTPrivateAnnotation {
|
||||
struct XPTAnnotation {
|
||||
XPTAnnotation *next;
|
||||
uint8 flags;
|
||||
/* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */
|
||||
XPTString *creator;
|
||||
XPTString *private_data;
|
||||
};
|
||||
|
||||
struct XPTAnnotation {
|
||||
XPTAnnotation *next;
|
||||
XPTAnnotationPrefix prefix;
|
||||
XPTPrivateAnnotation private;
|
||||
};
|
||||
#define XPT_ANN_LAST 0x80
|
||||
#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
|
||||
#define XPT_ANN_PRIVATE 0x40
|
||||
#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
|
||||
|
||||
XPTAnnotation *
|
||||
XPT_NewAnnotation(PRBool is_last, PRBool is_empty, XPTString *creator,
|
||||
XPTString *private_data);
|
||||
XPT_NewAnnotation(uint8 flags, XPTString *creator, XPTString *private_data);
|
||||
|
||||
#endif /* __xpt_struct_h__ */
|
||||
|
||||
@@ -22,6 +22,15 @@
|
||||
#include "xpt_struct.h"
|
||||
#include <string.h>
|
||||
|
||||
#define CURS_POOL_OFFSET_RAW(cursor) \
|
||||
((cursor)->pool == XPT_HEADER \
|
||||
? (cursor)->offset \
|
||||
: (PR_ASSERT((cursor)->state->data_offset), \
|
||||
(cursor)->offset + (cursor)->state->data_offset))
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
(CURS_POOL_OFFSET_RAW(cursor) - 1)
|
||||
|
||||
uint32
|
||||
XPT_SizeOfHeader(XPTHeader *header)
|
||||
{
|
||||
@@ -31,8 +40,15 @@ XPT_SizeOfHeader(XPTHeader *header)
|
||||
2 /* num_interfaces */ + 4 /* file_length */ +
|
||||
4 /* interface_directory */ + 4 /* data_pool */;
|
||||
|
||||
/* XXX annotations */
|
||||
fprintf(stderr, "header size is %d ", size);
|
||||
ann = header->annotations;
|
||||
do {
|
||||
size += 1; /* Annotation prefix */
|
||||
if (XPT_ANN_IS_PRIVATE(ann->flags))
|
||||
size += 2 + ann->creator->length + 2 + ann->private_data->length;
|
||||
} while (!XPT_ANN_IS_LAST(ann->flags));
|
||||
|
||||
fprintf(stderr, " (%d with annotations)\n", size);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -114,19 +130,21 @@ XPT_DoHeader(XPTCursor *cursor, XPTHeader **headerp)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* XXX handle annotations */
|
||||
if (!XPT_DoAnnotation(cursor, &header->annotations))
|
||||
goto error;
|
||||
|
||||
/* shouldn't be necessary now, but maybe later */
|
||||
XPT_SeekTo(cursor, ide_offset);
|
||||
|
||||
for (i = 0; i < header->num_interfaces; i++) {
|
||||
if (!XPT_DoInterfaceDirectoryEntry(&cursor,
|
||||
if (!XPT_DoInterfaceDirectoryEntry(cursor,
|
||||
&header->interface_directory[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
/* XXX need to free child data sometimes! */
|
||||
XPT_ERROR_HANDLE(header);
|
||||
}
|
||||
|
||||
@@ -145,26 +163,20 @@ XPT_FillInterfaceDirectoryEntry(XPTInterfaceDirectoryEntry *ide,
|
||||
/* InterfaceDirectoryEntry records go in the header */
|
||||
PRBool
|
||||
XPT_DoInterfaceDirectoryEntry(XPTCursor *cursor,
|
||||
XPTInterfaceDirectoryEntry **idep)
|
||||
XPTInterfaceDirectoryEntry *ide)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTInterfaceDirectoryEntry *ide;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
ide = PR_NEWZAP(XPTInterfaceDirectoryEntry);
|
||||
else
|
||||
ide = *idep;
|
||||
|
||||
/* write the IID in our cursor space */
|
||||
if (!XPT_DoIID(cursor, &ide->iid) ||
|
||||
if (!XPT_DoIID(cursor, &(ide->iid)) ||
|
||||
|
||||
/* write the name string in the data pool, and the offset in our
|
||||
cursor space */
|
||||
!XPT_DoCString(&cursor, &ide->name) ||
|
||||
!XPT_DoCString(cursor, &(ide->name)) ||
|
||||
|
||||
/* write the namespace string in the data pool, and the offset in our
|
||||
cursor space */
|
||||
!XPT_DoCString(&cursor, &ide->namespace)) {
|
||||
!XPT_DoCString(cursor, &(ide->namespace))) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
@@ -172,7 +184,7 @@ XPT_DoInterfaceDirectoryEntry(XPTCursor *cursor,
|
||||
/* write the InterfaceDescriptor in the data pool, and the offset
|
||||
in our cursor space, but only if we're encoding. */
|
||||
if (mode == XPT_ENCODE) {
|
||||
if (!XPT_DoInterfaceDescriptor(&cursor,
|
||||
if (!XPT_DoInterfaceDescriptor(cursor,
|
||||
&ide->interface_descriptor)) {
|
||||
goto error;
|
||||
}
|
||||
@@ -224,30 +236,65 @@ XPT_NewInterfaceDescriptor(uint32 parent_interface, uint32 num_methods,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor **idp)
|
||||
uint32
|
||||
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTInterfaceDescriptor *id;
|
||||
int i;
|
||||
return 1 /* flags */ + 4 /* name */ + 1 /* num_args */
|
||||
+ ((md->num_args + 1) * XPT_PARAMDESCRIPTOR_SIZE);
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
uint32
|
||||
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32
|
||||
XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
|
||||
{
|
||||
uint32 size = 4 /* parent interface */ + 2 /* num_methods */
|
||||
+ 2 /* num_constants */, i;
|
||||
for (i = 0; i < id->num_methods; i++)
|
||||
size += XPT_SizeOfMethodDescriptor(&id->method_descriptors[i]);
|
||||
for (i = 0; i < id->num_constants; i++)
|
||||
size += XPT_SizeOfConstDescriptor(&id->const_descriptors[i]);
|
||||
return size;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoInterfaceDescriptor(XPTCursor *outer, XPTInterfaceDescriptor **idp)
|
||||
{
|
||||
XPTMode mode = outer->state->mode;
|
||||
XPTInterfaceDescriptor *id;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
uint32 i, id_sz = 0;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
id = PR_NEWZAP(XPTInterfaceDescriptor);
|
||||
else
|
||||
if (!id)
|
||||
return PR_FALSE;
|
||||
} else {
|
||||
id = *idp;
|
||||
id_sz = XPT_SizeOfInterfaceDescriptor(id);
|
||||
}
|
||||
|
||||
if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
|
||||
goto error;
|
||||
|
||||
if(!XPT_Do32(cursor, &id->parent_interface) ||
|
||||
!XPT_Do16(cursor, &id->num_methods)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
id->method_descriptors = PR_CALLOC(id->num_methods *
|
||||
if (mode == XPT_DECODE && id->num_methods) {
|
||||
id->method_descriptors = PR_CALLOC(id->num_methods *
|
||||
sizeof(XPTMethodDescriptor));
|
||||
if (!id->method_descriptors)
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < id->num_methods; i++) {
|
||||
if (!XPT_DoMethodDescriptor(&cursor, &id->method_descriptors[i]))
|
||||
if (!XPT_DoMethodDescriptor(cursor, &id->method_descriptors[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -283,60 +330,54 @@ XPT_FillConstDescriptor(XPTConstDescriptor *cd, char *name,
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor **cdp)
|
||||
XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTConstDescriptor *cd;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
cd = PR_NEWZAP(XPTConstDescriptor);
|
||||
else
|
||||
cd = *cdp;
|
||||
|
||||
if (!XPT_DoCString(&cursor, &cd->name) ||
|
||||
!XPT_DoTypeDescriptor(&cursor, &cd->type)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch(cd->type.prefix.tag) {
|
||||
case TD_INT8:
|
||||
switch(XPT_TDP_TAG(cd->type.prefix)) {
|
||||
case TD_INT8:
|
||||
XPT_Do8(cursor, &cd->value.i8);
|
||||
break;
|
||||
case TD_INT16:
|
||||
case TD_INT16:
|
||||
XPT_Do16(cursor, &cd->value.i16);
|
||||
break;
|
||||
case TD_INT32:
|
||||
case TD_INT32:
|
||||
XPT_Do32(cursor, &cd->value.i32);
|
||||
break;
|
||||
case TD_INT64:
|
||||
case TD_INT64:
|
||||
XPT_Do64(cursor, &cd->value.i64);
|
||||
break;
|
||||
case TD_UINT8:
|
||||
case TD_UINT8:
|
||||
XPT_Do8(cursor, &cd->value.ui8);
|
||||
break;
|
||||
case TD_UINT16:
|
||||
case TD_UINT16:
|
||||
XPT_Do16(cursor, &cd->value.ui16);
|
||||
break;
|
||||
case TD_UINT32:
|
||||
case TD_UINT32:
|
||||
XPT_Do32(cursor, &cd->value.ui32);
|
||||
break;
|
||||
case TD_UINT64:
|
||||
case TD_UINT64:
|
||||
XPT_Do64(cursor, &cd->value.ui64);
|
||||
break;
|
||||
case TD_CHAR:
|
||||
case TD_CHAR:
|
||||
XPT_Do8(cursor, &cd->value.ch);
|
||||
break;
|
||||
case TD_WCHAR:
|
||||
case TD_WCHAR:
|
||||
XPT_Do16(cursor, &cd->value.wch);
|
||||
break;
|
||||
case TD_PBSTR:
|
||||
if (cd->type.prefix.is_pointer == 1) {
|
||||
case TD_PBSTR:
|
||||
if (cd->type.prefix.flags & XPT_TDP_POINTER) {
|
||||
XPT_DoString(cursor, &cd->value.string);
|
||||
break;
|
||||
}
|
||||
goto error;
|
||||
default:
|
||||
default:
|
||||
fprintf(stderr, "illegal type!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -346,23 +387,21 @@ XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor **cdp)
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
PRBool is_setter, PRBool is_varargs,
|
||||
PRBool is_constructor, PRBool is_hidden, char *name,
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, uint8 flags, char *name,
|
||||
uint8 num_args)
|
||||
{
|
||||
meth->is_getter = is_getter;
|
||||
meth->is_setter = is_setter;
|
||||
meth->is_constructor = is_constructor;
|
||||
meth->is_hidden = is_hidden;
|
||||
meth->reserved = 0;
|
||||
meth->flags = flags & XPT_MD_FLAGMASK;
|
||||
meth->name = strdup(name);
|
||||
if (!name)
|
||||
return PR_FALSE;
|
||||
meth->num_args = num_args;
|
||||
meth->params = PR_CALLOC(num_args * sizeof(XPTParamDescriptor));
|
||||
if (!meth->params)
|
||||
goto free_name;
|
||||
if (meth->num_args) {
|
||||
meth->params = PR_CALLOC(num_args * sizeof(XPTParamDescriptor));
|
||||
if (!meth->params)
|
||||
goto free_name;
|
||||
} else {
|
||||
meth->params = NULL;
|
||||
}
|
||||
meth->result = PR_NEWZAP(XPTParamDescriptor);
|
||||
if (!meth->result)
|
||||
goto free_params;
|
||||
@@ -376,128 +415,92 @@ XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor **mdp)
|
||||
XPT_DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTMethodDescriptor *md;
|
||||
uintn scratch;
|
||||
int i;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
md = PR_NEWZAP(XPTMethodDescriptor);
|
||||
else
|
||||
md = *mdp;
|
||||
#ifdef DEBUG_shaver_method
|
||||
if (mode == XPT_ENCODE)
|
||||
fprintf(stderr, "wrote method \"%s\" at offset %x\n",
|
||||
md->name, CURS_POOL_OFFSET(cursor));
|
||||
#endif
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, md->is_getter, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_setter, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_varargs, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_constructor, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_hidden, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->reserved, 3, scratch) ||
|
||||
!XPT_DoCString(&cursor, &md->name) ||
|
||||
!XPT_Do8(cursor, &md->num_args)) {
|
||||
|
||||
goto error;
|
||||
if (!XPT_Do8(cursor, &md->flags) ||
|
||||
!XPT_DoCString(cursor, &md->name) ||
|
||||
!XPT_Do8(cursor, &md->num_args))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
if (md->num_args)
|
||||
md->params = PR_CALLOC(md->num_args * sizeof(XPTParamDescriptor));
|
||||
if (!md->params)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
(uint8)md->num_args = PR_CALLOC(md->num_args * (int)sizeof(XPTParamDescriptor));
|
||||
|
||||
for(i = 0; i < md->num_args; i++) {
|
||||
if (!XPT_DoParamDescriptor(&cursor, &md->params))
|
||||
if (!XPT_DoParamDescriptor(cursor, &md->params[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!XPT_DoParamDescriptor(&cursor, &md->result))
|
||||
if (!XPT_DoParamDescriptor(cursor, md->result))
|
||||
goto error;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(md);
|
||||
XPT_ERROR_HANDLE(md->params);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRBool in, PRBool out,
|
||||
PRBool retval, XPTTypeDescriptor type)
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, uint8 flags,
|
||||
XPTTypeDescriptor *type)
|
||||
{
|
||||
pd->in = in;
|
||||
pd->out = out;
|
||||
pd->retval = retval;
|
||||
pd->reserved = 0;
|
||||
XPT_COPY_TYPE(pd->type, type);
|
||||
pd->flags = flags & XPT_PD_FLAGMASK;
|
||||
XPT_COPY_TYPE(pd->type, *type);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor **pdp)
|
||||
XPT_DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTParamDescriptor *pd;
|
||||
uintn scratch;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
pd = PR_NEWZAP(XPTParamDescriptor);
|
||||
else
|
||||
pd = *pdp;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, pd->in, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->out, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->retval, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->reserved, 5, scratch) ||
|
||||
!XPT_DoTypeDescriptor(&cursor, &pd->type)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
#ifdef DEBUG_shaver_param
|
||||
if (mode == XPT_ENCODE)
|
||||
fprintf(stderr, "wrote param %02x%02x at offset %x\n",
|
||||
pd->flags, pd->type.prefix.flags, CURS_POOL_OFFSET(cursor));
|
||||
#endif
|
||||
|
||||
if (!XPT_Do8(cursor, &pd->flags) ||
|
||||
!XPT_DoTypeDescriptor(cursor, &pd->type))
|
||||
return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
XPT_ERROR_HANDLE(pd);
|
||||
/* XXX when we lose the useless TDP wrapper struct, #define this to Do8 */
|
||||
PRBool
|
||||
XPT_DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
|
||||
{
|
||||
return XPT_Do8(cursor, &tdp->flags);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix **tdpp)
|
||||
XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTTypeDescriptorPrefix *tdp;
|
||||
uintn scratch;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
tdp = PR_NEWZAP(XPTTypeDescriptorPrefix);
|
||||
else
|
||||
tdp = *tdpp;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, tdp->is_pointer, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->is_unique_pointer, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->is_reference, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->tag, 5, scratch)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(tdp);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor **tdp)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTTypeDescriptor *td;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
td = PR_NEWZAP(XPTTypeDescriptor);
|
||||
else
|
||||
td = *tdp;
|
||||
|
||||
if (!XPT_DoTypeDescriptorPrefix(cursor, &td->prefix)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (td->prefix.tag == TD_INTERFACE_TYPE) {
|
||||
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
|
||||
if (!XPT_Do32(cursor, &td->type.interface))
|
||||
goto error;
|
||||
} else {
|
||||
if (td->prefix.tag == TD_INTERFACE_IS_TYPE) {
|
||||
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
|
||||
if (!XPT_Do8(cursor, &td->type.argnum))
|
||||
goto error;
|
||||
}
|
||||
@@ -509,90 +512,63 @@ XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor **tdp)
|
||||
}
|
||||
|
||||
XPTAnnotation *
|
||||
XPT_NewAnnotation(PRBool is_last, PRBool is_empty, XPTString *creator,
|
||||
XPTString *private_data)
|
||||
XPT_NewAnnotation(uint8 flags, XPTString *creator, XPTString *private_data)
|
||||
{
|
||||
XPTAnnotation *ann = PR_NEWZAP(XPTAnnotation);
|
||||
if (!ann)
|
||||
return NULL;
|
||||
ann->prefix.is_last = is_last;
|
||||
ann->prefix.tag = is_empty ? 0 : 1;
|
||||
if (!is_empty) {
|
||||
ann->private.creator = creator;
|
||||
ann->private.private_data = private_data;
|
||||
ann->flags = flags;
|
||||
if (XPT_ANN_IS_PRIVATE(flags)) {
|
||||
ann->creator = creator;
|
||||
ann->private_data = private_data;
|
||||
}
|
||||
return ann;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoAnnotationPrefix(XPTCursor *cursor, XPTAnnotationPrefix **app)
|
||||
XPT_DoAnnotation(XPTCursor *cursor, XPTAnnotation **annp)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTAnnotationPrefix *ap;
|
||||
uintn scratch;
|
||||
XPTAnnotation *ann;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
ap = PR_NEWZAP(XPTAnnotationPrefix);
|
||||
else
|
||||
ap = *app;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, ap->is_last, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, ap->tag, 7, scratch)) {
|
||||
|
||||
goto error;
|
||||
fprintf(stderr, "DoAnnotation\n");
|
||||
if (mode == XPT_DECODE) {
|
||||
ann = PR_NEWZAP(XPTAnnotation);
|
||||
if (!ann)
|
||||
return PR_FALSE;
|
||||
*annp = ann;
|
||||
} else {
|
||||
ann = *annp;
|
||||
}
|
||||
|
||||
if (!XPT_Do8(cursor, &ann->flags))
|
||||
goto error;
|
||||
|
||||
if (XPT_ANN_IS_PRIVATE(ann->flags)) {
|
||||
if (!XPT_DoStringInline(cursor, &ann->creator) ||
|
||||
!XPT_DoStringInline(cursor, &ann->private_data))
|
||||
goto error_2;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a subsequent Annotation fails, what to do?
|
||||
* - free all annotations, return PR_FALSE? (current behaviout)
|
||||
* - free failed annotation only, return PR_FALSE (caller can check for
|
||||
* non-NULL *annp on PR_FALSE return to detect partial annotation
|
||||
* decoding)?
|
||||
*/
|
||||
if (!XPT_ANN_IS_LAST(ann->flags) &&
|
||||
!XPT_DoAnnotation(cursor, &ann->next))
|
||||
goto error_2;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(ap);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoPrivateAnnotation(XPTCursor *cursor, XPTPrivateAnnotation **pap)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTPrivateAnnotation *pa;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
pa = PR_NEWZAP(XPTPrivateAnnotation);
|
||||
else
|
||||
pa = *pap;
|
||||
|
||||
if (!XPT_DoString(cursor, &pa->creator) ||
|
||||
!XPT_DoString(cursor, &pa->private_data)) {
|
||||
|
||||
goto error;
|
||||
error_2:
|
||||
if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
|
||||
PR_FREEIF(ann->creator);
|
||||
PR_FREEIF(ann->private_data);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(pa);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoAnnotation(XPTCursor *cursor, XPTAnnotation **ap)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTAnnotation *a;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
a = PR_NEWZAP(XPTAnnotation);
|
||||
else
|
||||
a = *ap;
|
||||
|
||||
if (!XPT_DoAnnotationPrefix(cursor, &a->prefix)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (a->prefix.tag == PRIVATE_ANNOTATION) {
|
||||
if (!XPT_DoPrivateAnnotation(cursor, &a->private)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(a);
|
||||
XPT_ERROR_HANDLE(ann);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@@ -601,12 +577,6 @@ XPT_DoAnnotations(XPTCursor *cursor, XPTAnnotation **ap)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *idp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
XPTInterfaceDescriptor *
|
||||
XPT_GetDescriptorByOffset(XPTState *state, XPTHeader *header, uint32
|
||||
descriptor_num)
|
||||
|
||||
@@ -25,12 +25,15 @@
|
||||
#define ENCODING(cursor) \
|
||||
((cursor)->state->mode == XPT_ENCODE)
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
#define CURS_POOL_OFFSET_RAW(cursor) \
|
||||
((cursor)->pool == XPT_HEADER \
|
||||
? (cursor)->offset \
|
||||
: (PR_ASSERT((cursor)->state->data_offset), \
|
||||
(cursor)->offset + (cursor)->state->data_offset))
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
(CURS_POOL_OFFSET_RAW(cursor) - 1)
|
||||
|
||||
/* can be used as lvalue */
|
||||
#define CURS_POINT(cursor) \
|
||||
((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
|
||||
@@ -45,7 +48,7 @@
|
||||
#define CHECK_COUNT_(cursor, space) \
|
||||
/* if we're in the header, then exceeding the data_offset is illegal */ \
|
||||
((cursor)->pool == XPT_HEADER ? \
|
||||
((cursor)->offset + (space) > (cursor)->state->data_offset \
|
||||
((cursor)->offset - 1 + (space) > (cursor)->state->data_offset \
|
||||
? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \
|
||||
(space), (cursor)->state->data_offset)), PR_FALSE) \
|
||||
: PR_TRUE) : \
|
||||
@@ -61,7 +64,8 @@
|
||||
#define CHECK_COUNT(cursor, space) \
|
||||
(CHECK_COUNT_(cursor, space) \
|
||||
? PR_TRUE \
|
||||
: (fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
|
||||
: (PR_ASSERT(0), \
|
||||
fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
|
||||
PR_FALSE))
|
||||
|
||||
/* increase the data allocation for the pool by XPT_GROW_CHUNK */
|
||||
@@ -85,7 +89,7 @@ XPT_NewXDRState(XPTMode mode, char *data, uint32 len)
|
||||
|
||||
state->mode = mode;
|
||||
state->pool = PR_NEW(XPTDatapool);
|
||||
state->next_cursor[0] = state->next_cursor[1] = 0;
|
||||
state->next_cursor[0] = state->next_cursor[1] = 1;
|
||||
if (!state->pool)
|
||||
goto err_free_state;
|
||||
|
||||
@@ -133,9 +137,10 @@ XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len)
|
||||
} else {
|
||||
*data = state->pool->data + state->data_offset;
|
||||
}
|
||||
*len = state->next_cursor[pool];
|
||||
*len = state->next_cursor[pool] - 1;
|
||||
}
|
||||
|
||||
/* All offsets are 1-based */
|
||||
void
|
||||
XPT_DataOffset(XPTState *state, uint32 *data_offsetp)
|
||||
{
|
||||
@@ -192,33 +197,80 @@ XPT_SeekTo(XPTCursor *cursor, uint32 offset)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
XPTString *
|
||||
XPT_NewString(uint16 length, char *bytes)
|
||||
{
|
||||
XPTString *str = PR_NEW(XPTString);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->length = length;
|
||||
str->bytes = malloc(length);
|
||||
if (!str->bytes) {
|
||||
PR_DELETE(str);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(str->bytes, bytes, length);
|
||||
return str;
|
||||
}
|
||||
|
||||
XPTString *
|
||||
XPT_NewStringZ(char *bytes)
|
||||
{
|
||||
uint32 length = strlen(bytes);
|
||||
if (length > 0xffff)
|
||||
return NULL; /* too long */
|
||||
return XPT_NewString((uint16)length, bytes);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoStringInline(XPTCursor *cursor, XPTString **strp)
|
||||
{
|
||||
XPTString *str = *strp;
|
||||
XPTMode mode = cursor->state->mode;
|
||||
int i;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
str = PR_NEWZAP(XPTString);
|
||||
if (!str)
|
||||
return PR_FALSE;
|
||||
*strp = str;
|
||||
}
|
||||
|
||||
if (!XPT_Do16(cursor, &str->length))
|
||||
goto error;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
if (!(str->bytes = malloc(str->length + 1)))
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < str->length; i++)
|
||||
if (!XPT_Do8(cursor, &str->bytes[i]))
|
||||
goto error_2;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
str->bytes[str->length] = 0;
|
||||
|
||||
return PR_TRUE;
|
||||
error_2:
|
||||
PR_DELETE(str->bytes);
|
||||
error:
|
||||
PR_DELETE(str);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoString(XPTCursor *cursor, XPTString **strp)
|
||||
{
|
||||
XPTCursor my_cursor;
|
||||
XPTString *str = *strp;
|
||||
PRBool already;
|
||||
XPTMode mode = cursor->state->mode;
|
||||
int i;
|
||||
|
||||
XPT_PREAMBLE(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
|
||||
already, XPTString, str);
|
||||
XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
|
||||
already);
|
||||
|
||||
if (!XPT_Do16(&my_cursor, &str->length))
|
||||
goto error;
|
||||
|
||||
if (cursor->state->mode == XPT_DECODE)
|
||||
if (!(str->bytes = malloc(str->length)))
|
||||
goto error;
|
||||
for (i = 0; i < str->length; i++)
|
||||
if (!XPT_Do8(&my_cursor, &str->bytes[i]))
|
||||
goto error_2;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
error_2:
|
||||
free(str->bytes);
|
||||
|
||||
XPT_ERROR_HANDLE(str);
|
||||
return XPT_DoStringInline(&my_cursor, strp);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@@ -332,7 +384,7 @@ XPT_CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, int len,
|
||||
|
||||
|
||||
/*
|
||||
* When we're writing an IID, we have to do it in a magic order. From the
|
||||
* IIDs are written in struct order, in the usual big-endian way. From the
|
||||
* typelib file spec:
|
||||
*
|
||||
* "For example, this IID:
|
||||
|
||||
@@ -21,14 +21,17 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = libxpt
|
||||
|
||||
SIMPLE_PROGRAMS = PrimitiveTest SimpleTypeLib
|
||||
|
||||
CSRCS = PrimitiveTest.c SimpleTypeLib.c
|
||||
CSRCS = PrimitiveTest.c SimpleTypeLib.c
|
||||
|
||||
LIBS = \
|
||||
-lxpt \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
LDFLAGS = \
|
||||
-L$(DIST)/bin \
|
||||
-lxpt \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
@@ -38,17 +38,22 @@
|
||||
#define TRY(msg, cond) TRY_(msg, cond, 0)
|
||||
#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
|
||||
|
||||
nsID iid = {
|
||||
struct nsID iid = {
|
||||
0x00112233,
|
||||
0x4455,
|
||||
0x6677,
|
||||
{0x88, 0x99, 0xaa, 0xbb} };
|
||||
{0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
|
||||
};
|
||||
|
||||
XPTTypeDescriptor td_void = { TD_VOID };
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
XPTHeader *header;
|
||||
XPTAnnotation *ann;
|
||||
XPTInterfaceDescriptor *id;
|
||||
XPTMethodDescriptor *meth;
|
||||
|
||||
XPTState *state;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
@@ -69,18 +74,41 @@ main(int argc, char **argv)
|
||||
header = XPT_NewHeader(1);
|
||||
TRY("NewHeader", header);
|
||||
|
||||
header->annotations = XPT_NewAnnotation(PR_TRUE, PR_TRUE, NULL, NULL);
|
||||
TRY("NewAnnotation", header->annotations);
|
||||
|
||||
ann = XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
|
||||
XPT_NewStringZ("SimpleTypeLib 1.0"),
|
||||
XPT_NewStringZ("See You In Rome"));
|
||||
TRY("NewAnnotation", ann);
|
||||
header->annotations = ann;
|
||||
|
||||
header_sz = XPT_SizeOfHeaderBlock(header);
|
||||
|
||||
id = XPT_NewInterfaceDescriptor(0, 0, 0);
|
||||
id = XPT_NewInterfaceDescriptor(0xdead, 2, 0);
|
||||
TRY("NewInterfaceDescriptor", id);
|
||||
|
||||
ok = XPT_FillInterfaceDirectoryEntry(header->interface_directory, &iid,
|
||||
"nsIFoo", "nsIBar", id);
|
||||
"Interface", "NS", id);
|
||||
TRY("FillInterfaceDirectoryEntry", ok);
|
||||
|
||||
/* void method1(void) */
|
||||
meth = &id->method_descriptors[0];
|
||||
ok = XPT_FillMethodDescriptor(meth, 0, "method1", 0);
|
||||
TRY("FillMethodDescriptor", ok);
|
||||
meth->result->flags = 0;
|
||||
meth->result->type.prefix.flags = TD_VOID;
|
||||
|
||||
/* wstring method2(in uint32, in bool) */
|
||||
meth = &id->method_descriptors[1];
|
||||
ok = XPT_FillMethodDescriptor(meth, 0, "method2", 2);
|
||||
TRY("FillMethodDescriptor", ok);
|
||||
|
||||
meth->result->flags = 0;
|
||||
meth->result->type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER;
|
||||
meth->params[0].type.prefix.flags = TD_UINT32;
|
||||
meth->params[0].flags = XPT_PD_IN;
|
||||
meth->params[1].type.prefix.flags = TD_BOOL;
|
||||
meth->params[1].flags = XPT_PD_IN;
|
||||
|
||||
/* serialize it */
|
||||
state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
|
||||
TRY("NewState (ENCODE)", state);
|
||||
@@ -94,7 +122,10 @@ main(int argc, char **argv)
|
||||
TRY("DoHeader", ok);
|
||||
|
||||
out = fopen(argv[1], "w");
|
||||
TRY_Q("fopen", out);
|
||||
if (!out) {
|
||||
perror("FAILED: fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
XPT_GetXDRData(state, XPT_HEADER, &data, &len);
|
||||
fwrite(data, len, 1, out);
|
||||
|
||||
@@ -47,8 +47,6 @@ typedef struct XPTTypeDescriptor XPTTypeDescriptor;
|
||||
typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
|
||||
typedef struct XPTString XPTString;
|
||||
typedef struct XPTAnnotation XPTAnnotation;
|
||||
typedef struct XPTAnnotationPrefix XPTAnnotationPrefix;
|
||||
typedef struct XPTPrivateAnnotation XPTPrivateAnnotation;
|
||||
#ifndef nsID_h__
|
||||
/*
|
||||
* We can't include nsID.h, because it's full of C++ goop and we're not doing
|
||||
@@ -72,7 +70,11 @@ typedef struct nsID nsID;
|
||||
(to).m3[0] = (from).m3[0]; \
|
||||
(to).m3[1] = (from).m3[1]; \
|
||||
(to).m3[2] = (from).m3[2]; \
|
||||
(to).m3[3] = (from).m3[3];
|
||||
(to).m3[3] = (from).m3[3]; \
|
||||
(to).m3[4] = (from).m3[4]; \
|
||||
(to).m3[5] = (from).m3[5]; \
|
||||
(to).m3[6] = (from).m3[6]; \
|
||||
(to).m3[7] = (from).m3[7];
|
||||
|
||||
|
||||
/*
|
||||
@@ -151,7 +153,10 @@ struct XPTString {
|
||||
};
|
||||
|
||||
XPTString *
|
||||
XPT_NewString(char *bytes, uint16 len);
|
||||
XPT_NewString(uint16 length, char *bytes);
|
||||
|
||||
XPTString *
|
||||
XPT_NewStringZ(char *bytes);
|
||||
|
||||
/*
|
||||
* A TypeDescriptor is a variable-size record used to identify the type of a
|
||||
@@ -170,11 +175,21 @@ XPT_NewString(char *bytes, uint16 len);
|
||||
* InterfaceIsTypeDescriptor.
|
||||
*/
|
||||
|
||||
/* XXX why bother with a struct? */
|
||||
struct XPTTypeDescriptorPrefix {
|
||||
uint8 is_pointer:1, is_unique_pointer:1, is_reference:1,
|
||||
tag:5;
|
||||
uint8 flags;
|
||||
};
|
||||
|
||||
/* flag bits -- fur and jband were right, I was miserably wrong */
|
||||
#define XPT_TDP_POINTER 0x80
|
||||
#define XPT_TDP_UNIQUE_POINTER 0x40
|
||||
#define XPT_TDP_REFERENCE 0x20
|
||||
#define XPT_TDP_FLAGMASK 0xe0
|
||||
#define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK)
|
||||
#define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK)
|
||||
|
||||
/* XXX TD #defines should include required flag bits! */
|
||||
|
||||
/*
|
||||
* The following defines map mnemonic names to the different numeric values
|
||||
* of XPTTypeDescriptor->tag when XPTTypeDescriptor->is_pointer is FALSE.
|
||||
@@ -241,12 +256,11 @@ struct XPTTypeDescriptor {
|
||||
} type;
|
||||
};
|
||||
|
||||
#define XPT_COPY_TYPE(to, from) \
|
||||
(to).prefix.is_pointer = (from).prefix.is_pointer; \
|
||||
(to).prefix.is_unique_pointer = (from).prefix.is_unique_pointer; \
|
||||
(to).prefix.is_reference = (from).prefix.is_reference; \
|
||||
(to).prefix.tag = (from).prefix.tag; \
|
||||
(to).type.interface = (from).type.interface
|
||||
#define XPT_TYPEDESCRIPTOR_SIZE (1 + 4)
|
||||
|
||||
#define XPT_COPY_TYPE(to, from) \
|
||||
(to).prefix.flags = (from).prefix.flags; \
|
||||
(to).type.interface = (from).type.interface;
|
||||
|
||||
/*
|
||||
* A ConstDescriptor is a variable-size record that records the name and
|
||||
@@ -290,31 +304,44 @@ struct XPTConstDescriptor {
|
||||
* single argument to a method or a method's result.
|
||||
*/
|
||||
struct XPTParamDescriptor {
|
||||
uint8 in:1, out:1, retval:1, reserved:5;
|
||||
uint8 flags;
|
||||
XPTTypeDescriptor type;
|
||||
};
|
||||
|
||||
/* flag bits -- jband and fur were right, and I was miserably wrong */
|
||||
#define XPT_PD_IN 0x80
|
||||
#define XPT_PD_OUT 0x40
|
||||
#define XPT_PD_RETVAL 0x20
|
||||
#define XPT_PD_FLAGMASK 0x70
|
||||
|
||||
#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1)
|
||||
|
||||
PRBool
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRBool in, PRBool out,
|
||||
PRBool retval, XPTTypeDescriptor type);
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, uint8 flags,
|
||||
XPTTypeDescriptor *type);
|
||||
|
||||
/*
|
||||
* A MethodDescriptor is a variable-size record used to describe a single
|
||||
* interface method.
|
||||
*/
|
||||
struct XPTMethodDescriptor {
|
||||
uint8 is_getter:1, is_setter:1, is_varargs:1,
|
||||
is_constructor:1, is_hidden:1, reserved:3;
|
||||
uint8 flags;
|
||||
char *name;
|
||||
uint8 num_args;
|
||||
XPTParamDescriptor *params;
|
||||
XPTParamDescriptor *result;
|
||||
};
|
||||
|
||||
/* flag bits -- jband and fur were right, and I was miserably wrong */
|
||||
#define XPT_MD_GETTER 0x80
|
||||
#define XPT_MD_SETTER 0x40
|
||||
#define XPT_MD_VARARGS 0x20
|
||||
#define XPT_MD_CTOR 0x10
|
||||
#define XPT_MD_HIDDEN 0x08
|
||||
#define XPT_MD_FLAGMASK 0xf8
|
||||
|
||||
PRBool
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
PRBool is_setter, PRBool is_varargs,
|
||||
PRBool is_constructor, PRBool is_hidden, char *name,
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, uint8 flags, char *name,
|
||||
uint8 num_args);
|
||||
|
||||
/*
|
||||
@@ -335,26 +362,21 @@ XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
* indicate an array of Annotation's that's completely empty. If the tag
|
||||
* is 1, the record is a PrivateAnnotation.
|
||||
*/
|
||||
#define EMPTY_ANNOTATION 0
|
||||
#define PRIVATE_ANNOTATION 1
|
||||
|
||||
struct XPTAnnotationPrefix {
|
||||
uint8 is_last:1, tag:7;
|
||||
};
|
||||
|
||||
struct XPTPrivateAnnotation {
|
||||
struct XPTAnnotation {
|
||||
XPTAnnotation *next;
|
||||
uint8 flags;
|
||||
/* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */
|
||||
XPTString *creator;
|
||||
XPTString *private_data;
|
||||
};
|
||||
|
||||
struct XPTAnnotation {
|
||||
XPTAnnotation *next;
|
||||
XPTAnnotationPrefix prefix;
|
||||
XPTPrivateAnnotation private;
|
||||
};
|
||||
#define XPT_ANN_LAST 0x80
|
||||
#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
|
||||
#define XPT_ANN_PRIVATE 0x40
|
||||
#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
|
||||
|
||||
XPTAnnotation *
|
||||
XPT_NewAnnotation(PRBool is_last, PRBool is_empty, XPTString *creator,
|
||||
XPTString *private_data);
|
||||
XPT_NewAnnotation(uint8 flags, XPTString *creator, XPTString *private_data);
|
||||
|
||||
#endif /* __xpt_struct_h__ */
|
||||
|
||||
@@ -22,6 +22,15 @@
|
||||
#include "xpt_struct.h"
|
||||
#include <string.h>
|
||||
|
||||
#define CURS_POOL_OFFSET_RAW(cursor) \
|
||||
((cursor)->pool == XPT_HEADER \
|
||||
? (cursor)->offset \
|
||||
: (PR_ASSERT((cursor)->state->data_offset), \
|
||||
(cursor)->offset + (cursor)->state->data_offset))
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
(CURS_POOL_OFFSET_RAW(cursor) - 1)
|
||||
|
||||
uint32
|
||||
XPT_SizeOfHeader(XPTHeader *header)
|
||||
{
|
||||
@@ -31,8 +40,15 @@ XPT_SizeOfHeader(XPTHeader *header)
|
||||
2 /* num_interfaces */ + 4 /* file_length */ +
|
||||
4 /* interface_directory */ + 4 /* data_pool */;
|
||||
|
||||
/* XXX annotations */
|
||||
fprintf(stderr, "header size is %d ", size);
|
||||
ann = header->annotations;
|
||||
do {
|
||||
size += 1; /* Annotation prefix */
|
||||
if (XPT_ANN_IS_PRIVATE(ann->flags))
|
||||
size += 2 + ann->creator->length + 2 + ann->private_data->length;
|
||||
} while (!XPT_ANN_IS_LAST(ann->flags));
|
||||
|
||||
fprintf(stderr, " (%d with annotations)\n", size);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -114,19 +130,21 @@ XPT_DoHeader(XPTCursor *cursor, XPTHeader **headerp)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* XXX handle annotations */
|
||||
if (!XPT_DoAnnotation(cursor, &header->annotations))
|
||||
goto error;
|
||||
|
||||
/* shouldn't be necessary now, but maybe later */
|
||||
XPT_SeekTo(cursor, ide_offset);
|
||||
|
||||
for (i = 0; i < header->num_interfaces; i++) {
|
||||
if (!XPT_DoInterfaceDirectoryEntry(&cursor,
|
||||
if (!XPT_DoInterfaceDirectoryEntry(cursor,
|
||||
&header->interface_directory[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
/* XXX need to free child data sometimes! */
|
||||
XPT_ERROR_HANDLE(header);
|
||||
}
|
||||
|
||||
@@ -145,26 +163,20 @@ XPT_FillInterfaceDirectoryEntry(XPTInterfaceDirectoryEntry *ide,
|
||||
/* InterfaceDirectoryEntry records go in the header */
|
||||
PRBool
|
||||
XPT_DoInterfaceDirectoryEntry(XPTCursor *cursor,
|
||||
XPTInterfaceDirectoryEntry **idep)
|
||||
XPTInterfaceDirectoryEntry *ide)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTInterfaceDirectoryEntry *ide;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
ide = PR_NEWZAP(XPTInterfaceDirectoryEntry);
|
||||
else
|
||||
ide = *idep;
|
||||
|
||||
/* write the IID in our cursor space */
|
||||
if (!XPT_DoIID(cursor, &ide->iid) ||
|
||||
if (!XPT_DoIID(cursor, &(ide->iid)) ||
|
||||
|
||||
/* write the name string in the data pool, and the offset in our
|
||||
cursor space */
|
||||
!XPT_DoCString(&cursor, &ide->name) ||
|
||||
!XPT_DoCString(cursor, &(ide->name)) ||
|
||||
|
||||
/* write the namespace string in the data pool, and the offset in our
|
||||
cursor space */
|
||||
!XPT_DoCString(&cursor, &ide->namespace)) {
|
||||
!XPT_DoCString(cursor, &(ide->namespace))) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
@@ -172,7 +184,7 @@ XPT_DoInterfaceDirectoryEntry(XPTCursor *cursor,
|
||||
/* write the InterfaceDescriptor in the data pool, and the offset
|
||||
in our cursor space, but only if we're encoding. */
|
||||
if (mode == XPT_ENCODE) {
|
||||
if (!XPT_DoInterfaceDescriptor(&cursor,
|
||||
if (!XPT_DoInterfaceDescriptor(cursor,
|
||||
&ide->interface_descriptor)) {
|
||||
goto error;
|
||||
}
|
||||
@@ -224,30 +236,65 @@ XPT_NewInterfaceDescriptor(uint32 parent_interface, uint32 num_methods,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor **idp)
|
||||
uint32
|
||||
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTInterfaceDescriptor *id;
|
||||
int i;
|
||||
return 1 /* flags */ + 4 /* name */ + 1 /* num_args */
|
||||
+ ((md->num_args + 1) * XPT_PARAMDESCRIPTOR_SIZE);
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
uint32
|
||||
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32
|
||||
XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
|
||||
{
|
||||
uint32 size = 4 /* parent interface */ + 2 /* num_methods */
|
||||
+ 2 /* num_constants */, i;
|
||||
for (i = 0; i < id->num_methods; i++)
|
||||
size += XPT_SizeOfMethodDescriptor(&id->method_descriptors[i]);
|
||||
for (i = 0; i < id->num_constants; i++)
|
||||
size += XPT_SizeOfConstDescriptor(&id->const_descriptors[i]);
|
||||
return size;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoInterfaceDescriptor(XPTCursor *outer, XPTInterfaceDescriptor **idp)
|
||||
{
|
||||
XPTMode mode = outer->state->mode;
|
||||
XPTInterfaceDescriptor *id;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
uint32 i, id_sz = 0;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
id = PR_NEWZAP(XPTInterfaceDescriptor);
|
||||
else
|
||||
if (!id)
|
||||
return PR_FALSE;
|
||||
} else {
|
||||
id = *idp;
|
||||
id_sz = XPT_SizeOfInterfaceDescriptor(id);
|
||||
}
|
||||
|
||||
if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
|
||||
goto error;
|
||||
|
||||
if(!XPT_Do32(cursor, &id->parent_interface) ||
|
||||
!XPT_Do16(cursor, &id->num_methods)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
id->method_descriptors = PR_CALLOC(id->num_methods *
|
||||
if (mode == XPT_DECODE && id->num_methods) {
|
||||
id->method_descriptors = PR_CALLOC(id->num_methods *
|
||||
sizeof(XPTMethodDescriptor));
|
||||
if (!id->method_descriptors)
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < id->num_methods; i++) {
|
||||
if (!XPT_DoMethodDescriptor(&cursor, &id->method_descriptors[i]))
|
||||
if (!XPT_DoMethodDescriptor(cursor, &id->method_descriptors[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -283,60 +330,54 @@ XPT_FillConstDescriptor(XPTConstDescriptor *cd, char *name,
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor **cdp)
|
||||
XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTConstDescriptor *cd;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
cd = PR_NEWZAP(XPTConstDescriptor);
|
||||
else
|
||||
cd = *cdp;
|
||||
|
||||
if (!XPT_DoCString(&cursor, &cd->name) ||
|
||||
!XPT_DoTypeDescriptor(&cursor, &cd->type)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch(cd->type.prefix.tag) {
|
||||
case TD_INT8:
|
||||
switch(XPT_TDP_TAG(cd->type.prefix)) {
|
||||
case TD_INT8:
|
||||
XPT_Do8(cursor, &cd->value.i8);
|
||||
break;
|
||||
case TD_INT16:
|
||||
case TD_INT16:
|
||||
XPT_Do16(cursor, &cd->value.i16);
|
||||
break;
|
||||
case TD_INT32:
|
||||
case TD_INT32:
|
||||
XPT_Do32(cursor, &cd->value.i32);
|
||||
break;
|
||||
case TD_INT64:
|
||||
case TD_INT64:
|
||||
XPT_Do64(cursor, &cd->value.i64);
|
||||
break;
|
||||
case TD_UINT8:
|
||||
case TD_UINT8:
|
||||
XPT_Do8(cursor, &cd->value.ui8);
|
||||
break;
|
||||
case TD_UINT16:
|
||||
case TD_UINT16:
|
||||
XPT_Do16(cursor, &cd->value.ui16);
|
||||
break;
|
||||
case TD_UINT32:
|
||||
case TD_UINT32:
|
||||
XPT_Do32(cursor, &cd->value.ui32);
|
||||
break;
|
||||
case TD_UINT64:
|
||||
case TD_UINT64:
|
||||
XPT_Do64(cursor, &cd->value.ui64);
|
||||
break;
|
||||
case TD_CHAR:
|
||||
case TD_CHAR:
|
||||
XPT_Do8(cursor, &cd->value.ch);
|
||||
break;
|
||||
case TD_WCHAR:
|
||||
case TD_WCHAR:
|
||||
XPT_Do16(cursor, &cd->value.wch);
|
||||
break;
|
||||
case TD_PBSTR:
|
||||
if (cd->type.prefix.is_pointer == 1) {
|
||||
case TD_PBSTR:
|
||||
if (cd->type.prefix.flags & XPT_TDP_POINTER) {
|
||||
XPT_DoString(cursor, &cd->value.string);
|
||||
break;
|
||||
}
|
||||
goto error;
|
||||
default:
|
||||
default:
|
||||
fprintf(stderr, "illegal type!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -346,23 +387,21 @@ XPT_DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor **cdp)
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
PRBool is_setter, PRBool is_varargs,
|
||||
PRBool is_constructor, PRBool is_hidden, char *name,
|
||||
XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, uint8 flags, char *name,
|
||||
uint8 num_args)
|
||||
{
|
||||
meth->is_getter = is_getter;
|
||||
meth->is_setter = is_setter;
|
||||
meth->is_constructor = is_constructor;
|
||||
meth->is_hidden = is_hidden;
|
||||
meth->reserved = 0;
|
||||
meth->flags = flags & XPT_MD_FLAGMASK;
|
||||
meth->name = strdup(name);
|
||||
if (!name)
|
||||
return PR_FALSE;
|
||||
meth->num_args = num_args;
|
||||
meth->params = PR_CALLOC(num_args * sizeof(XPTParamDescriptor));
|
||||
if (!meth->params)
|
||||
goto free_name;
|
||||
if (meth->num_args) {
|
||||
meth->params = PR_CALLOC(num_args * sizeof(XPTParamDescriptor));
|
||||
if (!meth->params)
|
||||
goto free_name;
|
||||
} else {
|
||||
meth->params = NULL;
|
||||
}
|
||||
meth->result = PR_NEWZAP(XPTParamDescriptor);
|
||||
if (!meth->result)
|
||||
goto free_params;
|
||||
@@ -376,128 +415,92 @@ XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRBool is_getter,
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor **mdp)
|
||||
XPT_DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTMethodDescriptor *md;
|
||||
uintn scratch;
|
||||
int i;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
md = PR_NEWZAP(XPTMethodDescriptor);
|
||||
else
|
||||
md = *mdp;
|
||||
#ifdef DEBUG_shaver_method
|
||||
if (mode == XPT_ENCODE)
|
||||
fprintf(stderr, "wrote method \"%s\" at offset %x\n",
|
||||
md->name, CURS_POOL_OFFSET(cursor));
|
||||
#endif
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, md->is_getter, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_setter, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_varargs, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_constructor, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->is_hidden, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, md->reserved, 3, scratch) ||
|
||||
!XPT_DoCString(&cursor, &md->name) ||
|
||||
!XPT_Do8(cursor, &md->num_args)) {
|
||||
|
||||
goto error;
|
||||
if (!XPT_Do8(cursor, &md->flags) ||
|
||||
!XPT_DoCString(cursor, &md->name) ||
|
||||
!XPT_Do8(cursor, &md->num_args))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
if (md->num_args)
|
||||
md->params = PR_CALLOC(md->num_args * sizeof(XPTParamDescriptor));
|
||||
if (!md->params)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
(uint8)md->num_args = PR_CALLOC(md->num_args * (int)sizeof(XPTParamDescriptor));
|
||||
|
||||
for(i = 0; i < md->num_args; i++) {
|
||||
if (!XPT_DoParamDescriptor(&cursor, &md->params))
|
||||
if (!XPT_DoParamDescriptor(cursor, &md->params[i]))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!XPT_DoParamDescriptor(&cursor, &md->result))
|
||||
if (!XPT_DoParamDescriptor(cursor, md->result))
|
||||
goto error;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(md);
|
||||
XPT_ERROR_HANDLE(md->params);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRBool in, PRBool out,
|
||||
PRBool retval, XPTTypeDescriptor type)
|
||||
XPT_FillParamDescriptor(XPTParamDescriptor *pd, uint8 flags,
|
||||
XPTTypeDescriptor *type)
|
||||
{
|
||||
pd->in = in;
|
||||
pd->out = out;
|
||||
pd->retval = retval;
|
||||
pd->reserved = 0;
|
||||
XPT_COPY_TYPE(pd->type, type);
|
||||
pd->flags = flags & XPT_PD_FLAGMASK;
|
||||
XPT_COPY_TYPE(pd->type, *type);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor **pdp)
|
||||
XPT_DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTParamDescriptor *pd;
|
||||
uintn scratch;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
pd = PR_NEWZAP(XPTParamDescriptor);
|
||||
else
|
||||
pd = *pdp;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, pd->in, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->out, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->retval, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, pd->reserved, 5, scratch) ||
|
||||
!XPT_DoTypeDescriptor(&cursor, &pd->type)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
#ifdef DEBUG_shaver_param
|
||||
if (mode == XPT_ENCODE)
|
||||
fprintf(stderr, "wrote param %02x%02x at offset %x\n",
|
||||
pd->flags, pd->type.prefix.flags, CURS_POOL_OFFSET(cursor));
|
||||
#endif
|
||||
|
||||
if (!XPT_Do8(cursor, &pd->flags) ||
|
||||
!XPT_DoTypeDescriptor(cursor, &pd->type))
|
||||
return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
XPT_ERROR_HANDLE(pd);
|
||||
/* XXX when we lose the useless TDP wrapper struct, #define this to Do8 */
|
||||
PRBool
|
||||
XPT_DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
|
||||
{
|
||||
return XPT_Do8(cursor, &tdp->flags);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix **tdpp)
|
||||
XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTTypeDescriptorPrefix *tdp;
|
||||
uintn scratch;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
tdp = PR_NEWZAP(XPTTypeDescriptorPrefix);
|
||||
else
|
||||
tdp = *tdpp;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, tdp->is_pointer, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->is_unique_pointer, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->is_reference, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, tdp->tag, 5, scratch)) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(tdp);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor **tdp)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTTypeDescriptor *td;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
td = PR_NEWZAP(XPTTypeDescriptor);
|
||||
else
|
||||
td = *tdp;
|
||||
|
||||
if (!XPT_DoTypeDescriptorPrefix(cursor, &td->prefix)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (td->prefix.tag == TD_INTERFACE_TYPE) {
|
||||
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
|
||||
if (!XPT_Do32(cursor, &td->type.interface))
|
||||
goto error;
|
||||
} else {
|
||||
if (td->prefix.tag == TD_INTERFACE_IS_TYPE) {
|
||||
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
|
||||
if (!XPT_Do8(cursor, &td->type.argnum))
|
||||
goto error;
|
||||
}
|
||||
@@ -509,90 +512,63 @@ XPT_DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor **tdp)
|
||||
}
|
||||
|
||||
XPTAnnotation *
|
||||
XPT_NewAnnotation(PRBool is_last, PRBool is_empty, XPTString *creator,
|
||||
XPTString *private_data)
|
||||
XPT_NewAnnotation(uint8 flags, XPTString *creator, XPTString *private_data)
|
||||
{
|
||||
XPTAnnotation *ann = PR_NEWZAP(XPTAnnotation);
|
||||
if (!ann)
|
||||
return NULL;
|
||||
ann->prefix.is_last = is_last;
|
||||
ann->prefix.tag = is_empty ? 0 : 1;
|
||||
if (!is_empty) {
|
||||
ann->private.creator = creator;
|
||||
ann->private.private_data = private_data;
|
||||
ann->flags = flags;
|
||||
if (XPT_ANN_IS_PRIVATE(flags)) {
|
||||
ann->creator = creator;
|
||||
ann->private_data = private_data;
|
||||
}
|
||||
return ann;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoAnnotationPrefix(XPTCursor *cursor, XPTAnnotationPrefix **app)
|
||||
XPT_DoAnnotation(XPTCursor *cursor, XPTAnnotation **annp)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTAnnotationPrefix *ap;
|
||||
uintn scratch;
|
||||
XPTAnnotation *ann;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
ap = PR_NEWZAP(XPTAnnotationPrefix);
|
||||
else
|
||||
ap = *app;
|
||||
|
||||
if (!XPT_DO_BITS(&cursor, ap->is_last, 1, scratch) ||
|
||||
!XPT_DO_BITS(&cursor, ap->tag, 7, scratch)) {
|
||||
|
||||
goto error;
|
||||
fprintf(stderr, "DoAnnotation\n");
|
||||
if (mode == XPT_DECODE) {
|
||||
ann = PR_NEWZAP(XPTAnnotation);
|
||||
if (!ann)
|
||||
return PR_FALSE;
|
||||
*annp = ann;
|
||||
} else {
|
||||
ann = *annp;
|
||||
}
|
||||
|
||||
if (!XPT_Do8(cursor, &ann->flags))
|
||||
goto error;
|
||||
|
||||
if (XPT_ANN_IS_PRIVATE(ann->flags)) {
|
||||
if (!XPT_DoStringInline(cursor, &ann->creator) ||
|
||||
!XPT_DoStringInline(cursor, &ann->private_data))
|
||||
goto error_2;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a subsequent Annotation fails, what to do?
|
||||
* - free all annotations, return PR_FALSE? (current behaviout)
|
||||
* - free failed annotation only, return PR_FALSE (caller can check for
|
||||
* non-NULL *annp on PR_FALSE return to detect partial annotation
|
||||
* decoding)?
|
||||
*/
|
||||
if (!XPT_ANN_IS_LAST(ann->flags) &&
|
||||
!XPT_DoAnnotation(cursor, &ann->next))
|
||||
goto error_2;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(ap);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoPrivateAnnotation(XPTCursor *cursor, XPTPrivateAnnotation **pap)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTPrivateAnnotation *pa;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
pa = PR_NEWZAP(XPTPrivateAnnotation);
|
||||
else
|
||||
pa = *pap;
|
||||
|
||||
if (!XPT_DoString(cursor, &pa->creator) ||
|
||||
!XPT_DoString(cursor, &pa->private_data)) {
|
||||
|
||||
goto error;
|
||||
error_2:
|
||||
if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
|
||||
PR_FREEIF(ann->creator);
|
||||
PR_FREEIF(ann->private_data);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(pa);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoAnnotation(XPTCursor *cursor, XPTAnnotation **ap)
|
||||
{
|
||||
XPTMode mode = cursor->state->mode;
|
||||
XPTAnnotation *a;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
a = PR_NEWZAP(XPTAnnotation);
|
||||
else
|
||||
a = *ap;
|
||||
|
||||
if (!XPT_DoAnnotationPrefix(cursor, &a->prefix)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (a->prefix.tag == PRIVATE_ANNOTATION) {
|
||||
if (!XPT_DoPrivateAnnotation(cursor, &a->private)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
XPT_ERROR_HANDLE(a);
|
||||
XPT_ERROR_HANDLE(ann);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@@ -601,12 +577,6 @@ XPT_DoAnnotations(XPTCursor *cursor, XPTAnnotation **ap)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *idp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
XPTInterfaceDescriptor *
|
||||
XPT_GetDescriptorByOffset(XPTState *state, XPTHeader *header, uint32
|
||||
descriptor_num)
|
||||
|
||||
@@ -25,12 +25,15 @@
|
||||
#define ENCODING(cursor) \
|
||||
((cursor)->state->mode == XPT_ENCODE)
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
#define CURS_POOL_OFFSET_RAW(cursor) \
|
||||
((cursor)->pool == XPT_HEADER \
|
||||
? (cursor)->offset \
|
||||
: (PR_ASSERT((cursor)->state->data_offset), \
|
||||
(cursor)->offset + (cursor)->state->data_offset))
|
||||
|
||||
#define CURS_POOL_OFFSET(cursor) \
|
||||
(CURS_POOL_OFFSET_RAW(cursor) - 1)
|
||||
|
||||
/* can be used as lvalue */
|
||||
#define CURS_POINT(cursor) \
|
||||
((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
|
||||
@@ -45,7 +48,7 @@
|
||||
#define CHECK_COUNT_(cursor, space) \
|
||||
/* if we're in the header, then exceeding the data_offset is illegal */ \
|
||||
((cursor)->pool == XPT_HEADER ? \
|
||||
((cursor)->offset + (space) > (cursor)->state->data_offset \
|
||||
((cursor)->offset - 1 + (space) > (cursor)->state->data_offset \
|
||||
? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \
|
||||
(space), (cursor)->state->data_offset)), PR_FALSE) \
|
||||
: PR_TRUE) : \
|
||||
@@ -61,7 +64,8 @@
|
||||
#define CHECK_COUNT(cursor, space) \
|
||||
(CHECK_COUNT_(cursor, space) \
|
||||
? PR_TRUE \
|
||||
: (fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
|
||||
: (PR_ASSERT(0), \
|
||||
fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
|
||||
PR_FALSE))
|
||||
|
||||
/* increase the data allocation for the pool by XPT_GROW_CHUNK */
|
||||
@@ -85,7 +89,7 @@ XPT_NewXDRState(XPTMode mode, char *data, uint32 len)
|
||||
|
||||
state->mode = mode;
|
||||
state->pool = PR_NEW(XPTDatapool);
|
||||
state->next_cursor[0] = state->next_cursor[1] = 0;
|
||||
state->next_cursor[0] = state->next_cursor[1] = 1;
|
||||
if (!state->pool)
|
||||
goto err_free_state;
|
||||
|
||||
@@ -133,9 +137,10 @@ XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len)
|
||||
} else {
|
||||
*data = state->pool->data + state->data_offset;
|
||||
}
|
||||
*len = state->next_cursor[pool];
|
||||
*len = state->next_cursor[pool] - 1;
|
||||
}
|
||||
|
||||
/* All offsets are 1-based */
|
||||
void
|
||||
XPT_DataOffset(XPTState *state, uint32 *data_offsetp)
|
||||
{
|
||||
@@ -192,33 +197,80 @@ XPT_SeekTo(XPTCursor *cursor, uint32 offset)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
XPTString *
|
||||
XPT_NewString(uint16 length, char *bytes)
|
||||
{
|
||||
XPTString *str = PR_NEW(XPTString);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->length = length;
|
||||
str->bytes = malloc(length);
|
||||
if (!str->bytes) {
|
||||
PR_DELETE(str);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(str->bytes, bytes, length);
|
||||
return str;
|
||||
}
|
||||
|
||||
XPTString *
|
||||
XPT_NewStringZ(char *bytes)
|
||||
{
|
||||
uint32 length = strlen(bytes);
|
||||
if (length > 0xffff)
|
||||
return NULL; /* too long */
|
||||
return XPT_NewString((uint16)length, bytes);
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoStringInline(XPTCursor *cursor, XPTString **strp)
|
||||
{
|
||||
XPTString *str = *strp;
|
||||
XPTMode mode = cursor->state->mode;
|
||||
int i;
|
||||
|
||||
if (mode == XPT_DECODE) {
|
||||
str = PR_NEWZAP(XPTString);
|
||||
if (!str)
|
||||
return PR_FALSE;
|
||||
*strp = str;
|
||||
}
|
||||
|
||||
if (!XPT_Do16(cursor, &str->length))
|
||||
goto error;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
if (!(str->bytes = malloc(str->length + 1)))
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < str->length; i++)
|
||||
if (!XPT_Do8(cursor, &str->bytes[i]))
|
||||
goto error_2;
|
||||
|
||||
if (mode == XPT_DECODE)
|
||||
str->bytes[str->length] = 0;
|
||||
|
||||
return PR_TRUE;
|
||||
error_2:
|
||||
PR_DELETE(str->bytes);
|
||||
error:
|
||||
PR_DELETE(str);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPT_DoString(XPTCursor *cursor, XPTString **strp)
|
||||
{
|
||||
XPTCursor my_cursor;
|
||||
XPTString *str = *strp;
|
||||
PRBool already;
|
||||
XPTMode mode = cursor->state->mode;
|
||||
int i;
|
||||
|
||||
XPT_PREAMBLE(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
|
||||
already, XPTString, str);
|
||||
XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
|
||||
already);
|
||||
|
||||
if (!XPT_Do16(&my_cursor, &str->length))
|
||||
goto error;
|
||||
|
||||
if (cursor->state->mode == XPT_DECODE)
|
||||
if (!(str->bytes = malloc(str->length)))
|
||||
goto error;
|
||||
for (i = 0; i < str->length; i++)
|
||||
if (!XPT_Do8(&my_cursor, &str->bytes[i]))
|
||||
goto error_2;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
error_2:
|
||||
free(str->bytes);
|
||||
|
||||
XPT_ERROR_HANDLE(str);
|
||||
return XPT_DoStringInline(&my_cursor, strp);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@@ -332,7 +384,7 @@ XPT_CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, int len,
|
||||
|
||||
|
||||
/*
|
||||
* When we're writing an IID, we have to do it in a magic order. From the
|
||||
* IIDs are written in struct order, in the usual big-endian way. From the
|
||||
* typelib file spec:
|
||||
*
|
||||
* "For example, this IID:
|
||||
|
||||
@@ -21,14 +21,17 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = libxpt
|
||||
|
||||
SIMPLE_PROGRAMS = PrimitiveTest SimpleTypeLib
|
||||
|
||||
CSRCS = PrimitiveTest.c SimpleTypeLib.c
|
||||
CSRCS = PrimitiveTest.c SimpleTypeLib.c
|
||||
|
||||
LIBS = \
|
||||
-lxpt \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
LDFLAGS = \
|
||||
-L$(DIST)/bin \
|
||||
-lxpt \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
@@ -38,17 +38,22 @@
|
||||
#define TRY(msg, cond) TRY_(msg, cond, 0)
|
||||
#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
|
||||
|
||||
nsID iid = {
|
||||
struct nsID iid = {
|
||||
0x00112233,
|
||||
0x4455,
|
||||
0x6677,
|
||||
{0x88, 0x99, 0xaa, 0xbb} };
|
||||
{0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
|
||||
};
|
||||
|
||||
XPTTypeDescriptor td_void = { TD_VOID };
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
XPTHeader *header;
|
||||
XPTAnnotation *ann;
|
||||
XPTInterfaceDescriptor *id;
|
||||
XPTMethodDescriptor *meth;
|
||||
|
||||
XPTState *state;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
@@ -69,18 +74,41 @@ main(int argc, char **argv)
|
||||
header = XPT_NewHeader(1);
|
||||
TRY("NewHeader", header);
|
||||
|
||||
header->annotations = XPT_NewAnnotation(PR_TRUE, PR_TRUE, NULL, NULL);
|
||||
TRY("NewAnnotation", header->annotations);
|
||||
|
||||
ann = XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
|
||||
XPT_NewStringZ("SimpleTypeLib 1.0"),
|
||||
XPT_NewStringZ("See You In Rome"));
|
||||
TRY("NewAnnotation", ann);
|
||||
header->annotations = ann;
|
||||
|
||||
header_sz = XPT_SizeOfHeaderBlock(header);
|
||||
|
||||
id = XPT_NewInterfaceDescriptor(0, 0, 0);
|
||||
id = XPT_NewInterfaceDescriptor(0xdead, 2, 0);
|
||||
TRY("NewInterfaceDescriptor", id);
|
||||
|
||||
ok = XPT_FillInterfaceDirectoryEntry(header->interface_directory, &iid,
|
||||
"nsIFoo", "nsIBar", id);
|
||||
"Interface", "NS", id);
|
||||
TRY("FillInterfaceDirectoryEntry", ok);
|
||||
|
||||
/* void method1(void) */
|
||||
meth = &id->method_descriptors[0];
|
||||
ok = XPT_FillMethodDescriptor(meth, 0, "method1", 0);
|
||||
TRY("FillMethodDescriptor", ok);
|
||||
meth->result->flags = 0;
|
||||
meth->result->type.prefix.flags = TD_VOID;
|
||||
|
||||
/* wstring method2(in uint32, in bool) */
|
||||
meth = &id->method_descriptors[1];
|
||||
ok = XPT_FillMethodDescriptor(meth, 0, "method2", 2);
|
||||
TRY("FillMethodDescriptor", ok);
|
||||
|
||||
meth->result->flags = 0;
|
||||
meth->result->type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER;
|
||||
meth->params[0].type.prefix.flags = TD_UINT32;
|
||||
meth->params[0].flags = XPT_PD_IN;
|
||||
meth->params[1].type.prefix.flags = TD_BOOL;
|
||||
meth->params[1].flags = XPT_PD_IN;
|
||||
|
||||
/* serialize it */
|
||||
state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
|
||||
TRY("NewState (ENCODE)", state);
|
||||
@@ -94,7 +122,10 @@ main(int argc, char **argv)
|
||||
TRY("DoHeader", ok);
|
||||
|
||||
out = fopen(argv[1], "w");
|
||||
TRY_Q("fopen", out);
|
||||
if (!out) {
|
||||
perror("FAILED: fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
XPT_GetXDRData(state, XPT_HEADER, &data, &len);
|
||||
fwrite(data, len, 1, out);
|
||||
|
||||
Reference in New Issue
Block a user