add arrays to xpidl and typelibs. got rid of vararg support scheme

This commit is contained in:
jband%netscape.com 1999-09-11 05:20:39 +00:00
Родитель df370cde61
Коммит f673b4fa59
14 изменённых файлов: 545 добавлений и 156 удалений

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

@ -96,12 +96,14 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
// these are bitflags!
PTR_IS_DATA = 0x1, // ptr points to 'real' data in val
VAL_IS_OWNED = 0x2, // val.p holds alloc'd ptr that must be freed
VAL_IS_IFACE = 0x4 // val.p holds interface ptr that must be released
VAL_IS_IFACE = 0x4, // val.p holds interface ptr that must be released
VAL_IS_ARRAY = 0x8 // val.p holds a pointer to an array needing cleanup
};
PRBool IsPtrData() const {return (PRBool) (flags & PTR_IS_DATA);}
PRBool IsValOwned() const {return (PRBool) (flags & VAL_IS_OWNED);}
PRBool IsValInterface() const {return (PRBool) (flags & VAL_IS_IFACE);}
PRBool IsValArray() const {return (PRBool) (flags & VAL_IS_ARRAY);}
};
/***************************************************************************/

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

@ -27,6 +27,7 @@
class nsXPTMethodInfo;
class nsXPTConstant;
class nsXPTParamInfo;
class nsXPTType;
// {215DBE04-94A7-11d2-BA58-00805F8A5DD7}
#define NS_IINTERFACEINFO_IID \
@ -50,7 +51,7 @@ public:
NS_IMETHOD GetConstantCount(uint16* count) = 0;
// These include methods and constants of parents.
// There do *not* make copies ***explicit bending of XPCOM rules***
// These do *not* make copies ***explicit bending of XPCOM rules***
NS_IMETHOD GetMethodInfo(uint16 index, const nsXPTMethodInfo** info) = 0;
NS_IMETHOD GetMethodInfoForName(const char* methodName, uint16 *index,
const nsXPTMethodInfo** info) = 0;
@ -63,6 +64,22 @@ public:
// returns IAllocatator alloc'd copy
NS_IMETHOD GetIIDForParam(uint16 methodIndex, const nsXPTParamInfo* param,
nsIID** iid) = 0;
// These do *not* make copies ***explicit bending of XPCOM rules***
NS_IMETHOD GetTypeForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
nsXPTType* type) = 0;
NS_IMETHOD GetSizeIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum) = 0;
NS_IMETHOD GetLengthIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum) = 0;
};
#endif /* nsIInterfaceInfo_h___ */

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

@ -102,31 +102,37 @@ public:
{return (PRBool) (TagPart() == T_INTERFACE ||
TagPart() == T_INTERFACE_IS);}
PRBool IsArray() const
{return (PRBool) (TagPart() == T_ARRAY ||
TagPart() == T_ARRAY_WITH_LENGTH);}
uint8 TagPart() const
{return (uint8) (flags & XPT_TDP_TAGMASK);}
enum
{
T_I8 = TD_INT8 ,
T_I16 = TD_INT16 ,
T_I32 = TD_INT32 ,
T_I64 = TD_INT64 ,
T_U8 = TD_UINT8 ,
T_U16 = TD_UINT16 ,
T_U32 = TD_UINT32 ,
T_U64 = TD_UINT64 ,
T_FLOAT = TD_FLOAT ,
T_DOUBLE = TD_DOUBLE ,
T_BOOL = TD_BOOL ,
T_CHAR = TD_CHAR ,
T_WCHAR = TD_WCHAR ,
T_VOID = TD_VOID ,
T_IID = TD_PNSIID ,
T_BSTR = TD_PBSTR ,
T_CHAR_STR = TD_PSTRING ,
T_WCHAR_STR = TD_PWSTRING ,
T_INTERFACE = TD_INTERFACE_TYPE ,
T_INTERFACE_IS = TD_INTERFACE_IS_TYPE
T_I8 = TD_INT8 ,
T_I16 = TD_INT16 ,
T_I32 = TD_INT32 ,
T_I64 = TD_INT64 ,
T_U8 = TD_UINT8 ,
T_U16 = TD_UINT16 ,
T_U32 = TD_UINT32 ,
T_U64 = TD_UINT64 ,
T_FLOAT = TD_FLOAT ,
T_DOUBLE = TD_DOUBLE ,
T_BOOL = TD_BOOL ,
T_CHAR = TD_CHAR ,
T_WCHAR = TD_WCHAR ,
T_VOID = TD_VOID ,
T_IID = TD_PNSIID ,
T_BSTR = TD_PBSTR ,
T_CHAR_STR = TD_PSTRING ,
T_WCHAR_STR = TD_PWSTRING ,
T_INTERFACE = TD_INTERFACE_TYPE ,
T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
T_ARRAY = TD_ARRAY ,
T_ARRAY_WITH_LENGTH = TD_ARRAY_WITH_LENGTH
};
// NO DATA - this a flyweight wrapper
};
@ -148,7 +154,7 @@ public:
uint8 GetInterfaceIsArgNumber() const
{
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE_IS,"not an interface_is");
return type.type.argnum;
return type.argnum;
}
// NOTE: gettting the interface or interface iid is done via methods on
// nsIInterfaceInfo

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

@ -250,6 +250,130 @@ nsInterfaceInfo::GetIIDForParam(uint16 methodIndex,
return paramRecord->GetIID(iid);
}
NS_IMETHODIMP
nsInterfaceInfo::GetTypeForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
nsXPTType* type)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(type, "bad pointer");
if (methodIndex < mMethodBaseIndex)
return mParent->GetTypeForParam(methodIndex, param, dimension, type);
if (methodIndex >= mMethodBaseIndex + mMethodCount) {
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
const XPTTypeDescriptor *additional_types =
this->mInterfaceRecord->interfaceDescriptor->additional_types;
for(uint16 i = 0; i < dimension; i++) {
uint8 tag = XPT_TDP_TAG(td->prefix);
if (tag != TD_ARRAY && tag != TD_ARRAY_WITH_LENGTH) {
NS_ASSERTION(0, "bad dimension");
return NS_ERROR_INVALID_ARG;
}
td = &additional_types[td->type.additional_type];
}
*type = nsXPTType(td->prefix);
return NS_OK;
}
NS_IMETHODIMP
nsInterfaceInfo::GetSizeIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(argnum, "bad pointer");
NS_PRECONDITION(dimension > 0, "arrays have no size_is for dimension 0");
if (methodIndex < mMethodBaseIndex)
return mParent->GetSizeIsArgNumberForParam(methodIndex, param,
dimension, argnum);
if (methodIndex >= mMethodBaseIndex + mMethodCount) {
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
const XPTTypeDescriptor *additional_types =
this->mInterfaceRecord->interfaceDescriptor->additional_types;
uint16 depth = dimension;
while (1)
{
uint8 tag = XPT_TDP_TAG(td->prefix);
if (tag != TD_ARRAY && tag != TD_ARRAY_WITH_LENGTH) {
NS_ASSERTION(0, "bad dimension");
return NS_ERROR_INVALID_ARG;
}
if (0 == --depth)
break;
td = &additional_types[td->type.additional_type];
}
*argnum = td->argnum;
return NS_OK;
}
NS_IMETHODIMP
nsInterfaceInfo::GetLengthIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(argnum, "bad pointer");
NS_PRECONDITION(dimension > 0, "arrays have no length_is for dimension 0");
if (methodIndex < mMethodBaseIndex)
return mParent->GetLengthIsArgNumberForParam(methodIndex, param,
dimension, argnum);
if (methodIndex >= mMethodBaseIndex + mMethodCount) {
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
const XPTTypeDescriptor *additional_types =
this->mInterfaceRecord->interfaceDescriptor->additional_types;
uint16 depth = dimension;
while (1)
{
uint8 tag = XPT_TDP_TAG(td->prefix);
if (tag != TD_ARRAY && tag != TD_ARRAY_WITH_LENGTH) {
NS_ASSERTION(0, "bad dimension");
return NS_ERROR_INVALID_ARG;
}
if (0 == --depth) {
if (tag != TD_ARRAY_WITH_LENGTH) {
NS_ASSERTION(0, "asked for length_is for dimension without one");
return NS_ERROR_INVALID_ARG;
}
break;
}
td = &additional_types[td->type.additional_type];
}
*argnum = td->argnum2;
return NS_OK;
}
#ifdef DEBUG
#include <stdio.h>
void

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

@ -61,6 +61,21 @@ class nsInterfaceInfo : public nsIInterfaceInfo
NS_IMETHOD GetIIDForParam(uint16 methodIndex, const nsXPTParamInfo* param,
nsIID** iid);
// These do *not* make copies ***explicit bending of XPCOM rules***
NS_IMETHOD GetTypeForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
nsXPTType* type);
NS_IMETHOD GetSizeIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum);
NS_IMETHOD GetLengthIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum);
public:
virtual ~nsInterfaceInfo();

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

@ -47,7 +47,7 @@ LLIBS= \
$(MOZ_TOOLS)\lib\libidl-0.6.lib \
$(NULL)
LLFLAGS= $(LLFLAGS) -SUBSYSTEM:CONSOLE
LLFLAGS= $(LLFLAGS) -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRTD
include <$(DEPTH)\config\rules.mak>

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

@ -41,12 +41,14 @@ FindMode(char *mode)
return NULL;
}
gboolean enable_debug = FALSE;
gboolean enable_warnings = FALSE;
gboolean verbose_mode = FALSE;
gboolean enable_debug = FALSE;
gboolean enable_warnings = FALSE;
gboolean verbose_mode = FALSE;
gboolean emit_typelib_annotations = FALSE;
static char xpidl_usage_str[] =
"Usage: %s [-m mode] [-w] [-v] [-I path] [-o basename] filename.idl\n"
" -a emit annotaions to typelib\n"
" -w turn on warnings (recommended)\n"
" -v verbose mode (NYI)\n"
" -I add entry to start of include path for ``#include \"nsIThing.idl\"''\n"
@ -133,6 +135,9 @@ int main(int argc, char *argv[])
/* fall through */
case 0: /* - is a legal input filename (stdin) */
goto done_options;
case 'a':
emit_typelib_annotations = TRUE;
break;
case 'w':
enable_warnings = TRUE;
break;

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

@ -62,6 +62,7 @@
extern gboolean enable_debug;
extern gboolean enable_warnings;
extern gboolean verbose_mode;
extern gboolean emit_typelib_annotations;
typedef struct TreeState TreeState;

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

@ -616,7 +616,13 @@ write_param(IDL_tree param_tree, FILE *outfile)
if (IDL_PARAM_DCL(param_tree).attr != IDL_PARAM_IN)
fputc('*', outfile);
/* arrays get a bonus * too */
/* XXX Should this be a leading '*' or a trailing "[]" ?*/
if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator, "array"))
fputc('*', outfile);
fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile);
return TRUE;
}

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

@ -33,6 +33,7 @@ struct priv_data {
XPTInterfaceDescriptor *current;
uint16 next_method;
uint16 next_const;
uint16 next_type; /* used for 'additional_types' for idl arrays */
};
#define HEADER(state) (((struct priv_data *)state->priv)->header)
@ -41,6 +42,7 @@ struct priv_data {
#define CURRENT(state) (((struct priv_data *)state->priv)->current)
#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
#define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const)
#define NEXT_TYPE(state) (((struct priv_data *)state->priv)->next_type)
#ifdef DEBUG_shaver
/* #define DEBUG_shaver_sort */
@ -377,51 +379,65 @@ pass_1(TreeState *state)
ok = TRUE;
} else {
/* write the typelib */
time_t now;
char *annotate_val, *data, *timestr;
PRUint32 i, len, header_sz, annotation_len, written_so_far;
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
XPTCursor curs, *cursor = &curs;
static char *annotation_format = "Created from %s.idl\nCreation date: %s"
"Interfaces:";
PRUint32 i, len, header_sz;
char *data;
/* fill in the annotations, listing resolved interfaces in order */
if(emit_typelib_annotations) {
PRUint32 annotation_len, written_so_far;
char *annotate_val, *timestr;
time_t now;
static char *annotation_format =
"Created from %s.idl\nCreation date: %sInterfaces:";
(void)time(&now);
timestr = ctime(&now);
/* fill in the annotations, listing resolved interfaces in order */
/* Avoid dependence on nspr; no PR_smprintf and friends. */
(void)time(&now);
timestr = ctime(&now);
/* How large should the annotation string be? */
annotation_len = strlen(annotation_format) + strlen(state->basename) +
strlen(timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
annotation_len += strlen(ide->name) + 1;
/* Avoid dependence on nspr; no PR_smprintf and friends. */
/* How large should the annotation string be? */
annotation_len = strlen(annotation_format) +
strlen(state->basename) +
strlen(timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
annotation_len += strlen(ide->name) + 1;
}
}
annotate_val = (char *) malloc(annotation_len);
written_so_far = sprintf(annotate_val, annotation_format,
state->basename, timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
written_so_far += sprintf(annotate_val + written_so_far,
" %s", ide->name);
}
}
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.9"),
XPT_NewStringZ(annotate_val));
free(annotate_val);
} else {
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST, NULL, NULL);
}
annotate_val = (char *) malloc(annotation_len);
written_so_far = sprintf(annotate_val, annotation_format,
state->basename, timestr);
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
XPTInterfaceDirectoryEntry *ide;
ide = &HEADER(state)->interface_directory[i];
if (ide->interface_descriptor) {
written_so_far += sprintf(annotate_val + written_so_far,
" %s", ide->name);
}
if (!HEADER(state)->annotations) {
/* XXX report out of memory error */
return FALSE;
}
HEADER(state)->annotations =
XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpidl 0.99.9"),
XPT_NewStringZ(annotate_val));
free(annotate_val);
#ifdef DEBUG_shaver_misc
fprintf(stderr, "writing the typelib\n");
#endif
@ -479,9 +495,10 @@ typelib_interface(TreeState *state)
XPTInterfaceDirectoryEntry *ide;
XPTInterfaceDescriptor *id;
uint16 parent_id = 0;
PRUint8 interface_flags =
IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") ?
XPT_ID_SCRIPTABLE : 0;
PRUint8 interface_flags = 0;
if(IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
interface_flags |= XPT_ID_SCRIPTABLE;
ide = FindInterfaceByName(HEADER(state)->interface_directory,
HEADER(state)->num_interfaces, name);
@ -521,6 +538,7 @@ typelib_interface(TreeState *state)
NEXT_METH(state) = 0;
NEXT_CONST(state) = 0;
NEXT_TYPE(state) = 0;
state->tree = IDL_INTERFACE(iface).body;
if (state->tree && !xpidl_process_node(state))
@ -531,12 +549,98 @@ typelib_interface(TreeState *state)
return TRUE;
}
static gboolean
find_arg_with_name(TreeState *state, const char *name, int16 *argnum)
{
int16 count;
IDL_tree params;
XPT_ASSERT(state);
XPT_ASSERT(name);
XPT_ASSERT(argnum);
params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
for (count = 0;
params != NULL && IDL_LIST(params).data != NULL;
params = IDL_LIST(params).next, count++)
{
const char *cur_name = IDL_IDENT(
IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
if (!strcmp(cur_name, name)) {
/* XXX ought to verify that this is the right type here */
*argnum = count;
return TRUE;
}
}
return FALSE;
}
static gboolean
fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type)
{
IDL_tree up;
if (type) {
/* deal with array */
if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
if(IDL_tree_property_get(sd, "array")) {
const char *size_is;
const char *length_is;
int16 size_is_argnum;
int16 length_is_argnum;
/* size_is is required! */
size_is = IDL_tree_property_get(sd, "size_is");
if (!size_is) {
IDL_tree_error(type, "[array] requires [size_is()]\n");
return FALSE;
}
if (!find_arg_with_name(state, size_is, &size_is_argnum)) {
IDL_tree_error(type, "can't find matching argument for "
"[size_is(%s)]\n", size_is);
return FALSE;
}
/* length_is is optional */
length_is = IDL_tree_property_get(sd, "length_is");
if (length_is &&
!find_arg_with_name(state, length_is, &length_is_argnum)) {
IDL_tree_error(type, "can't find matching argument for "
"[length_is(%s)]\n", length_is);
return FALSE;
}
td->argnum = size_is_argnum;
if (length_is) {
td->prefix.flags = TD_ARRAY_WITH_LENGTH | XPT_TDP_POINTER;
td->argnum2 = length_is_argnum;
} else {
td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
}
/*
* XXX - NOTE - this will be broken for multidimensional
* arrays because of the realloc XPT_InterfaceDescriptorAddTypes
* uses. The underlying 'td' can change as we recurse in to get
* additional dimensions. Luckily, we don't yet support more
* than on dimension in the arrays
*/
/* setup the additional_type */
if (!XPT_InterfaceDescriptorAddTypes(CURRENT(state), 1)) {
g_error("out of memory\n");
return FALSE;
}
td->type.additional_type = NEXT_TYPE(state);
td = &CURRENT(state)->additional_types[NEXT_TYPE(state)];
NEXT_TYPE(state)++ ;
}
}
handle_typedef:
switch (IDL_NODE_TYPE(type)) {
case IDLN_TYPE_INTEGER: {
gboolean sign = IDL_TYPE_INTEGER(type).f_signed;
@ -617,27 +721,14 @@ handle_iid_is:
"iid_is");
}
if (iid_is) {
int16 argnum = -1, count;
IDL_tree params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
for (count = 0;
params != NULL && IDL_LIST(params).data != NULL;
params = IDL_LIST(params).next, count++)
{
char *name;
name = IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
if (!strcmp(name, iid_is)) {
/* XXX verify that this is an nsid here */
argnum = count;
break;
}
}
if (argnum < 0) {
int16 argnum;
if (!find_arg_with_name(state, iid_is, &argnum)) {
IDL_tree_error(type, "can't find matching argument for "
"[iid_is(%s)]\n", iid_is);
return FALSE;
}
}
td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER;
td->type.argnum = argnum;
td->argnum = argnum;
} else {
td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
ide = FindInterfaceByName(ides, num_ifaces, className);
@ -714,7 +805,19 @@ handle_iid_is:
fprintf(stderr, "following %s typedef to %s\n",
IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type));
#endif
return fill_td_from_type(state, td, new_type);
/*
* Do a nice messy goto rather than recursion so that
* we can avoid screwing up the *array* information.
*/
/* return fill_td_from_type(state, td, new_type); */
if (new_type) {
type = new_type;
goto handle_typedef;
} else {
/* do what we would do in recursion if !type */
td->prefix.flags = TD_VOID;
return TRUE;
}
}
IDL_tree_error(type, "can't handle %s ident in param list\n",
#ifdef DEBUG_shaver
@ -881,10 +984,7 @@ typelib_op_dcl(TreeState *state)
op_flags |= XPT_MD_HIDDEN;
if (op_notxpcom)
op_flags |= XPT_MD_NOTXPCOM;
/*
if (op->f_varargs)
op_flags |= XPT_MD_VARARGS;
*/
/* XXXshaver constructor? */
#ifdef DEBUG_shaver_method

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

@ -183,6 +183,25 @@ struct XPTInterfaceDescriptor {
PRUint16 num_constants;
XPTConstDescriptor *const_descriptors;
PRUint8 flags;
/* additional_types are used for arrays where we may need multiple
* XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still
* want to have a simple array of XPTMethodDescriptor (each with a single
* embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference
* to an 'additional_type'. That reference is an index in this
* "additional_types" array. So a given XPTMethodDescriptor might have
* a whole chain of these XPTTypeDescriptors to represent, say, a multi
* dimensional array.
*
* Note that in the typelib file these additional types are stored 'inline'
* in the MethodDescriptor. But, in the typelib MethodDescriptors can be
* of varying sizes, where in XPT's in memory mapping of the data we want
* them to be of fixed size. This additional_types scheme is here to allow
* for that.
*/
XPTTypeDescriptor *additional_types;
PRUint16 num_additional_types;
};
#define XPT_ID_SCRIPTABLE 0x80
@ -201,6 +220,9 @@ extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
XPT_NewInterfaceDescriptor(PRUint16 parent_interface, PRUint16 num_methods,
PRUint16 num_constants, PRUint8 flags);
extern XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddTypes(XPTInterfaceDescriptor *id, PRUint16 num);
extern XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddMethods(XPTInterfaceDescriptor *id, PRUint16 num);
@ -280,22 +302,30 @@ enum XPTTypeDescriptorTags {
TD_PSTRING = 16,
TD_PWSTRING = 17,
TD_INTERFACE_TYPE = 18,
TD_INTERFACE_IS_TYPE = 19
TD_INTERFACE_IS_TYPE = 19,
TD_ARRAY = 20,
TD_ARRAY_WITH_LENGTH = 21
};
struct XPTTypeDescriptor {
XPTTypeDescriptorPrefix prefix;
PRUint8 argnum;
PRUint8 argnum2;
union {
PRUint16 interface;
PRUint8 argnum;
PRUint16 additional_type;
} type;
};
/* this is bogus
#define XPT_TYPEDESCRIPTOR_SIZE (1 + 2)
*/
#define XPT_COPY_TYPE(to, from) \
(to).prefix.flags = (from).prefix.flags; \
(to).type.interface = (from).type.interface;
(to).argnum = (from).argnum; \
(to).argnum2 = (from).argnum2; \
(to).type.additional_type = (from).type.additional_type;
/*
* A ConstDescriptor is a variable-size record that records the name and
@ -361,7 +391,9 @@ struct XPTParamDescriptor {
#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
/* this is bogus
#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1)
*/
extern XPT_PUBLIC_API(PRBool)
XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRUint8 flags,
@ -438,13 +470,13 @@ XPT_NewAnnotation(PRUint8 flags, XPTString *creator, XPTString *private_data);
*/
extern XPT_PUBLIC_API(PRUint32)
XPT_SizeOfTypeDescriptor(XPTTypeDescriptor *td);
XPT_SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
extern XPT_PUBLIC_API(PRUint32)
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md);
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
extern XPT_PUBLIC_API(PRUint32)
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd);
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
extern XPT_PUBLIC_API(PRUint32)
XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id);

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

@ -47,10 +47,12 @@ DoInterfaceDirectoryEntryIndex(XPTCursor *cursor,
#endif
static PRBool
DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd);
DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id);
static PRBool
DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md);
DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id);
static PRBool
DoAnnotation(XPTCursor *cursor, XPTAnnotation **annp);
@ -62,10 +64,12 @@ static PRBool
DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
static PRBool
DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td);
DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id);
static PRBool
DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd);
DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id);
XPT_PUBLIC_API(PRUint32)
XPT_SizeOfHeader(XPTHeader *header)
@ -81,10 +85,10 @@ XPT_SizeOfHeader(XPTHeader *header)
size += 1; /* Annotation prefix */
if (XPT_ANN_IS_PRIVATE(ann->flags))
size += 2 + ann->creator->length + 2 + ann->private_data->length;
last = ann;
ann = ann->next;
last = ann;
ann = ann->next;
} while (!XPT_ANN_IS_LAST(last->flags));
return size;
}
@ -360,6 +364,23 @@ XPT_NewInterfaceDescriptor(PRUint16 parent_interface, PRUint16 num_methods,
return NULL;
}
XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddTypes(XPTInterfaceDescriptor *id, PRUint16 num)
{
XPTTypeDescriptor *old = id->additional_types, *new;
/* XXX should grow in chunks to minimize realloc overhead */
new = XPT_REALLOC(old,
(id->num_additional_types + num) * sizeof(XPTTypeDescriptor));
if (!new)
return PR_FALSE;
memset(new + id->num_additional_types, 0, sizeof(XPTTypeDescriptor) * num);
id->additional_types = new;
id->num_additional_types += num;
return PR_TRUE;
}
XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddMethods(XPTInterfaceDescriptor *id, PRUint16 num)
{
@ -395,32 +416,38 @@ XPT_InterfaceDescriptorAddConsts(XPTInterfaceDescriptor *id, PRUint16 num)
}
XPT_PUBLIC_API(PRUint32)
XPT_SizeOfTypeDescriptor(XPTTypeDescriptor *td)
XPT_SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
{
PRUint32 size = 1; /* prefix */
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE)
size += 2; /* interface_index */
else if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE)
size += 1; /* arg_num */
else if (XPT_TDP_TAG(td->prefix) == TD_ARRAY)
size += 1 + XPT_SizeOfTypeDescriptor(
&id->additional_types[td->type.additional_type], id);
else if (XPT_TDP_TAG(td->prefix) == TD_ARRAY_WITH_LENGTH)
size += 2 + XPT_SizeOfTypeDescriptor(
&id->additional_types[td->type.additional_type], id);
return size;
}
XPT_PUBLIC_API(PRUint32)
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md)
XPT_SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
{
PRUint32 i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */;
for (i = 0; i < md->num_args; i++)
size += 1 + XPT_SizeOfTypeDescriptor(&md->params[i].type);
size += 1 + XPT_SizeOfTypeDescriptor(&md->params[i].type, id);
size += 1 + XPT_SizeOfTypeDescriptor(&md->result->type);
size += 1 + XPT_SizeOfTypeDescriptor(&md->result->type, id);
return size;
}
XPT_PUBLIC_API(PRUint32)
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd)
XPT_SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
{
PRUint32 size = 4 /* name */ + XPT_SizeOfTypeDescriptor(&cd->type);
PRUint32 size = 4 /* name */ + XPT_SizeOfTypeDescriptor(&cd->type, id);
switch (XPT_TDP_TAG(cd->type.prefix)) {
case TD_INT8:
@ -458,9 +485,9 @@ XPT_SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
PRUint32 size = 2 /* parent interface */ + 2 /* num_methods */
+ 2 /* num_constants */ + 1 /* flags */, i;
for (i = 0; i < id->num_methods; i++)
size += XPT_SizeOfMethodDescriptor(&id->method_descriptors[i]);
size += XPT_SizeOfMethodDescriptor(&id->method_descriptors[i], id);
for (i = 0; i < id->num_constants; i++)
size += XPT_SizeOfConstDescriptor(&id->const_descriptors[i]);
size += XPT_SizeOfConstDescriptor(&id->const_descriptors[i], id);
return size;
}
@ -508,7 +535,7 @@ DoInterfaceDescriptor(XPTCursor *outer, XPTInterfaceDescriptor **idp)
}
for (i = 0; i < id->num_methods; i++) {
if (!DoMethodDescriptor(cursor, &id->method_descriptors[i]))
if (!DoMethodDescriptor(cursor, &id->method_descriptors[i], id))
goto error;
}
@ -524,7 +551,7 @@ DoInterfaceDescriptor(XPTCursor *outer, XPTInterfaceDescriptor **idp)
}
for (i = 0; i < id->num_constants; i++) {
if (!DoConstDescriptor(cursor, &id->const_descriptors[i])) {
if (!DoConstDescriptor(cursor, &id->const_descriptors[i], id)) {
goto error;
}
}
@ -551,12 +578,13 @@ XPT_FillConstDescriptor(XPTConstDescriptor *cd, char *name,
}
PRBool
DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd)
DoConstDescriptor(XPTCursor *cursor, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id)
{
PRBool ok = PR_FALSE;
if (!XPT_DoCString(cursor, &cd->name) ||
!DoTypeDescriptor(cursor, &cd->type)) {
!DoTypeDescriptor(cursor, &cd->type, id)) {
return PR_FALSE;
}
@ -636,7 +664,8 @@ XPT_FillMethodDescriptor(XPTMethodDescriptor *meth, PRUint8 flags, char *name,
}
PRBool
DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md)
DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id)
{
XPTMode mode = cursor->state->mode;
int i;
@ -653,7 +682,7 @@ DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md)
}
for(i = 0; i < md->num_args; i++) {
if (!DoParamDescriptor(cursor, &md->params[i]))
if (!DoParamDescriptor(cursor, &md->params[i], id))
goto error;
}
@ -664,7 +693,7 @@ DoMethodDescriptor(XPTCursor *cursor, XPTMethodDescriptor *md)
}
if (!md->result ||
!DoParamDescriptor(cursor, md->result))
!DoParamDescriptor(cursor, md->result, id))
goto error;
return PR_TRUE;
@ -682,10 +711,11 @@ XPT_FillParamDescriptor(XPTParamDescriptor *pd, PRUint8 flags,
}
PRBool
DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd)
DoParamDescriptor(XPTCursor *cursor, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id)
{
if (!XPT_Do8(cursor, &pd->flags) ||
!DoTypeDescriptor(cursor, &pd->type))
!DoTypeDescriptor(cursor, &pd->type, id))
return PR_FALSE;
return PR_TRUE;
@ -699,7 +729,8 @@ DoTypeDescriptorPrefix(XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
}
PRBool
DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td)
DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id)
{
if (!DoTypeDescriptorPrefix(cursor, &td->prefix)) {
goto error;
@ -708,13 +739,31 @@ DoTypeDescriptor(XPTCursor *cursor, XPTTypeDescriptor *td)
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
if (!XPT_Do16(cursor, &td->type.interface))
goto error;
} else {
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
if (!XPT_Do8(cursor, &td->type.argnum))
goto error;
}
}
else if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
if (!XPT_Do8(cursor, &td->argnum))
goto error;
}
else if (XPT_TDP_TAG(td->prefix) == TD_ARRAY ||
XPT_TDP_TAG(td->prefix) == TD_ARRAY_WITH_LENGTH) {
if (!XPT_Do8(cursor, &td->argnum))
goto error;
if (XPT_TDP_TAG(td->prefix) == TD_ARRAY_WITH_LENGTH)
if (!XPT_Do8(cursor, &td->argnum2))
goto error;
if (cursor->state->mode == XPT_DECODE) {
if(!XPT_InterfaceDescriptorAddTypes(id, 1))
goto error;
td->type.additional_type = id->num_additional_types - 1;
}
if (!DoTypeDescriptor(cursor,
&id->additional_types[td->type.additional_type],
id))
goto error;
}
return PR_TRUE;
XPT_ERROR_HANDLE(td);

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

@ -55,7 +55,6 @@ static char *rtype_array[20] = {"int8 &", "int16 &", "int32 &", "int64 &",
"string", "wstring", "Interface &",
"InterfaceIs &"};
PRBool param_problems = PR_FALSE;
PRBool
@ -78,9 +77,11 @@ XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
PRBool
XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode);
PRBool
XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id,
char **type_string);
PRBool
@ -88,15 +89,18 @@ XPT_DumpXPTString(XPTString *str);
PRBool
XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode,
PRBool is_result);
PRBool
XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, int indent,
PRBool verbose_mode);
XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id,
int indent, PRBool verbose_mode);
PRBool
XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode);
static void
@ -463,13 +467,13 @@ XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
if (verbose_mode) {
fprintf(stdout, "%*sMethod #%d:\n", new_indent, " ", i);
if (!XPT_DumpMethodDescriptor(header,
&id->method_descriptors[i],
&id->method_descriptors[i], id,
more_indent, verbose_mode)) {
return PR_FALSE;
}
} else {
if (!XPT_DumpMethodDescriptor(header,
&id->method_descriptors[i],
&id->method_descriptors[i], id,
new_indent, verbose_mode)) {
return PR_FALSE;
}
@ -493,12 +497,12 @@ XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
if (verbose_mode) {
fprintf(stdout, "%*sConstant #%d:\n", new_indent, " ", i);
if (!XPT_DumpConstDescriptor(header,
&id->const_descriptors[i],
&id->const_descriptors[i], id,
more_indent, verbose_mode))
return PR_FALSE;
} else {
if (!XPT_DumpConstDescriptor(header,
&id->const_descriptors[i],
&id->const_descriptors[i], id,
new_indent, verbose_mode)) {
return PR_FALSE;
}
@ -514,6 +518,7 @@ XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
PRBool
XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode)
{
int i;
@ -558,13 +563,13 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
for (i=0; i<md->num_args; i++) {
fprintf(stdout, "%*sParameter #%d:\n", new_indent, " ", i);
if (!XPT_DumpParamDescriptor(header, &md->params[i], more_indent,
verbose_mode, PR_FALSE))
if (!XPT_DumpParamDescriptor(header, &md->params[i], id,
more_indent, verbose_mode, PR_FALSE))
return PR_FALSE;
}
fprintf(stdout, "%*sResult:\n", indent, " ");
if (!XPT_DumpParamDescriptor(header, md->result, new_indent,
if (!XPT_DumpParamDescriptor(header, md->result, id, new_indent,
verbose_mode, PR_TRUE)) {
return PR_FALSE;
}
@ -572,7 +577,7 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
char *param_type;
XPTParamDescriptor *pd;
if (!XPT_GetStringForType(header, &md->result->type, &param_type)) {
if (!XPT_GetStringForType(header, &md->result->type, id, &param_type)) {
return PR_FALSE;
}
fprintf(stdout, "%*s%c%c%c%c%c %s %s(", indent - 6, " ",
@ -590,7 +595,7 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
if (XPT_PD_IS_IN(pd->flags)) {
fprintf(stdout, "in");
if (XPT_PD_IS_OUT(pd->flags)) {
fprintf(stdout, "/out ");
fprintf(stdout, "out ");
if (XPT_PD_IS_RETVAL(pd->flags)) {
fprintf(stdout, "retval ");
}
@ -614,7 +619,7 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
fprintf(stdout, "XXX ");
}
}
if (!XPT_GetStringForType(header, &pd->type, &param_type)) {
if (!XPT_GetStringForType(header, &pd->type, id, &param_type)) {
return PR_FALSE;
}
fprintf(stdout, "%s", param_type);
@ -626,10 +631,20 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
PRBool
XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id,
char **type_string)
{
static char buf[128]; /* ugly non-reentrant use of static buffer! */
PRBool isArray = PR_FALSE;
int tag = XPT_TDP_TAG(td->prefix);
if (tag == TD_ARRAY || tag == TD_ARRAY_WITH_LENGTH) {
isArray = PR_TRUE;
td = &id->additional_types[td->type.additional_type];
tag = XPT_TDP_TAG(td->prefix);
}
if (tag == TD_INTERFACE_TYPE) {
int idx = td->type.interface;
if (!idx || idx > header->num_interfaces)
@ -645,6 +660,11 @@ XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
*type_string = type_array[tag];
}
if(isArray) {
sprintf(buf, "%s []", *type_string);
*type_string = buf;
}
return PR_TRUE;
}
@ -660,6 +680,7 @@ XPT_DumpXPTString(XPTString *str)
PRBool
XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode,
PRBool is_result)
{
@ -711,16 +732,32 @@ XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
fprintf(stdout, "FALSE\n");
fprintf(stdout, "%*sType Descriptor:\n", indent, " ");
if (!XPT_DumpTypeDescriptor(&pd->type, new_indent, verbose_mode))
if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))
return PR_FALSE;
return PR_TRUE;
}
PRBool
XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, int indent, PRBool verbose_mode)
XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id,
int indent, PRBool verbose_mode)
{
int new_indent = indent + BASE_INDENT;
int new_indent;
if (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
fprintf(stdout, "%*sArray (size in arg %d) of...\n",
indent, " ", td->argnum);
td = &id->additional_types[td->type.additional_type];
indent += BASE_INDENT;
} else if (XPT_TDP_TAG(td->prefix) == TD_ARRAY_WITH_LENGTH) {
fprintf(stdout, "%*sArray (size in arg %d and length in arg %d) of...\n",
indent, " ", td->argnum, td->argnum2);
td = &id->additional_types[td->type.additional_type];
indent += BASE_INDENT;
}
new_indent = indent + BASE_INDENT;
fprintf(stdout, "%*sIs Pointer? ", indent, " ");
if (XPT_TDP_IS_POINTER(td->prefix.flags))
@ -752,7 +789,7 @@ XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, int indent, PRBool verbose_mode)
if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " ");
fprintf(stdout, "%*sIndex of Method Argument: %d\n", new_indent, " ",
td->type.argnum);
td->argnum);
}
return PR_TRUE;
@ -760,6 +797,7 @@ XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, int indent, PRBool verbose_mode)
PRBool
XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id,
const int indent, PRBool verbose_mode)
{
int new_indent = indent + BASE_INDENT;
@ -771,11 +809,11 @@ XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
if (verbose_mode) {
fprintf(stdout, "%*sName: %s\n", indent, " ", cd->name);
fprintf(stdout, "%*sType Descriptor: \n", indent, " ");
if (!XPT_DumpTypeDescriptor(&cd->type, new_indent, verbose_mode))
if (!XPT_DumpTypeDescriptor(&cd->type, id, new_indent, verbose_mode))
return PR_FALSE;
fprintf(stdout, "%*sValue: ", indent, " ");
} else {
if (!XPT_GetStringForType(header, &cd->type, &const_type)) {
if (!XPT_GetStringForType(header, &cd->type, id, &const_type)) {
return PR_FALSE;
}
fprintf(stdout, "%*s%s %s = ", indent, " ", const_type, cd->name);

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

@ -118,14 +118,7 @@ main(int argc, char **argv)
return 1;
}
/* We're going to keep annotations now, so we'll start off with one
* that will let people know that the resultant type library file
* was generated by this tool (xpt_link).
*/
first_ann = XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ("xpt_link"),
XPT_NewStringZ("This is a linked type library file created by xpt_link."));
first_ann = XPT_NewAnnotation(XPT_ANN_LAST, NULL, NULL);
for (i=2; i<argc; i++) {
char *name = argv[i];
@ -205,13 +198,14 @@ main(int argc, char **argv)
}
}
/* Copy the annotations.
/* Copy the annotations if they are not 'empty'
*/
ann = first_ann;
while (ann->next != NULL) {
ann = ann->next;
}
if (header->annotations != NULL) {
if (header->annotations != NULL &&
header->annotations->flags != XPT_ANN_LAST) {
ann = first_ann;
while (ann->next != NULL) {
ann = ann->next;
}
ann->next = header->annotations;
}