diff --git a/mozilla/xpcom/libxpt/public/xpt_struct.h b/mozilla/xpcom/libxpt/public/xpt_struct.h index cf17cfb3ff5..85ab90ee0fa 100644 --- a/mozilla/xpcom/libxpt/public/xpt_struct.h +++ b/mozilla/xpcom/libxpt/public/xpt_struct.h @@ -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__ */ diff --git a/mozilla/xpcom/libxpt/src/xpt_struct.c b/mozilla/xpcom/libxpt/src/xpt_struct.c index ae8abb6da28..e060920a712 100644 --- a/mozilla/xpcom/libxpt/src/xpt_struct.c +++ b/mozilla/xpcom/libxpt/src/xpt_struct.c @@ -22,6 +22,15 @@ #include "xpt_struct.h" #include +#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) diff --git a/mozilla/xpcom/libxpt/src/xpt_xdr.c b/mozilla/xpcom/libxpt/src/xpt_xdr.c index 30e02d16b8e..cdfe07aea6a 100644 --- a/mozilla/xpcom/libxpt/src/xpt_xdr.c +++ b/mozilla/xpcom/libxpt/src/xpt_xdr.c @@ -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: diff --git a/mozilla/xpcom/libxpt/tests/Makefile.in b/mozilla/xpcom/libxpt/tests/Makefile.in index 1f9db6ca729..671775ce84c 100644 --- a/mozilla/xpcom/libxpt/tests/Makefile.in +++ b/mozilla/xpcom/libxpt/tests/Makefile.in @@ -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 diff --git a/mozilla/xpcom/libxpt/tests/SimpleTypeLib.c b/mozilla/xpcom/libxpt/tests/SimpleTypeLib.c index 4755502e599..b081b003248 100644 --- a/mozilla/xpcom/libxpt/tests/SimpleTypeLib.c +++ b/mozilla/xpcom/libxpt/tests/SimpleTypeLib.c @@ -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); diff --git a/mozilla/xpcom/typelib/xpt/public/xpt_struct.h b/mozilla/xpcom/typelib/xpt/public/xpt_struct.h index cf17cfb3ff5..85ab90ee0fa 100644 --- a/mozilla/xpcom/typelib/xpt/public/xpt_struct.h +++ b/mozilla/xpcom/typelib/xpt/public/xpt_struct.h @@ -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__ */ diff --git a/mozilla/xpcom/typelib/xpt/src/xpt_struct.c b/mozilla/xpcom/typelib/xpt/src/xpt_struct.c index ae8abb6da28..e060920a712 100644 --- a/mozilla/xpcom/typelib/xpt/src/xpt_struct.c +++ b/mozilla/xpcom/typelib/xpt/src/xpt_struct.c @@ -22,6 +22,15 @@ #include "xpt_struct.h" #include +#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) diff --git a/mozilla/xpcom/typelib/xpt/src/xpt_xdr.c b/mozilla/xpcom/typelib/xpt/src/xpt_xdr.c index 30e02d16b8e..cdfe07aea6a 100644 --- a/mozilla/xpcom/typelib/xpt/src/xpt_xdr.c +++ b/mozilla/xpcom/typelib/xpt/src/xpt_xdr.c @@ -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: diff --git a/mozilla/xpcom/typelib/xpt/tests/Makefile.in b/mozilla/xpcom/typelib/xpt/tests/Makefile.in index 1f9db6ca729..671775ce84c 100644 --- a/mozilla/xpcom/typelib/xpt/tests/Makefile.in +++ b/mozilla/xpcom/typelib/xpt/tests/Makefile.in @@ -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 diff --git a/mozilla/xpcom/typelib/xpt/tests/SimpleTypeLib.c b/mozilla/xpcom/typelib/xpt/tests/SimpleTypeLib.c index 4755502e599..b081b003248 100644 --- a/mozilla/xpcom/typelib/xpt/tests/SimpleTypeLib.c +++ b/mozilla/xpcom/typelib/xpt/tests/SimpleTypeLib.c @@ -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);