From 8e761289a2446367267c6c0d9a26e734f0f78306 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 16 Dec 2020 20:29:05 +0300 Subject: Get rid of legacy build systems and rename cutl/ to libcutl/ --- cutl/details/genx/genx.c | 2324 ---------------------------------------------- 1 file changed, 2324 deletions(-) delete mode 100644 cutl/details/genx/genx.c (limited to 'cutl/details/genx/genx.c') diff --git a/cutl/details/genx/genx.c b/cutl/details/genx/genx.c deleted file mode 100644 index 36279b3..0000000 --- a/cutl/details/genx/genx.c +++ /dev/null @@ -1,2324 +0,0 @@ -/* - * Copyright (c) 2004 by Tim Bray and Sun Microsystems. - * Copyright (c) Code Synthesis Tools CC (see the LICENSE file). - * - * For copying permission, see the accompanying COPYING file. - */ - -#define GENX_VERSION "cs-1" - -#include -#include -#include - -#include - -#define Boolean int -#define True 1 -#define False 0 -#define STRLEN_XMLNS_COLON 6 - - -/******************************* - * writer state - */ -typedef enum -{ - SEQUENCE_NO_DOC, - SEQUENCE_PRE_DOC, - SEQUENCE_POST_DOC, - SEQUENCE_START_TAG, - SEQUENCE_ATTRIBUTES, - SEQUENCE_START_ATTR, - SEQUENCE_CONTENT -} writerSequence; - -/******************************* - * generic pointer list - */ -typedef struct -{ - genxWriter writer; - int count; - int space; - void * * pointers; -} plist; - -/******************************* - * text collector, for attribute values - */ -typedef struct -{ - utf8 buf; - int used; - int space; -} collector; - -/******************************* - * Structs with opaquely-exposed handles - */ - -/* - * This one's tricky, to handle stacking namespaces - * 'declaration' is the current attribute which would be used to - * declare the currently-effective prefix - * 'defDeclaration' is a appropriate declaration when this is being - * used with the default prefix as passed to genxDeclareNamespace - * baroque is true if this namespace has been used with more than one - * prefix, or is the default namespace but has been unset - */ -struct genxNamespace_rec -{ - genxWriter writer; - utf8 name; - int declCount; - Boolean baroque; - genxAttribute declaration; - genxAttribute defaultDecl; -}; - -struct genxElement_rec -{ - genxWriter writer; - utf8 type; - genxNamespace ns; -}; - -typedef enum -{ - ATTR_NSDECL, - ATTR_NAKED, - ATTR_PREFIXED -} attrType; - -struct genxAttribute_rec -{ - genxWriter writer; - utf8 name; - genxNamespace ns; - collector value; - int provided; /* provided for current element? */ - attrType atype; - genxAttribute next; /* Attribute order chain if not canonical. */ -}; - -/******************************* - * genx's sandbox - */ -struct genxWriter_rec -{ - genxSender * sender; - genxStatus status; - writerSequence sequence; - char xmlChars[GENX_CHAR_TABLE_SIZE]; - void * userData; - int nextPrefix; - utf8 empty; - Boolean defaultNsDeclared; - genxAttribute xmlnsEquals; - genxElement nowStarting; - genxAttribute nowStartingAttr; - plist namespaces; - plist elements; - plist attributes; - plist prefixes; - plist stack; - struct genxAttribute_rec arec; /* Dummy attribute used for lookup. */ - char * etext[100]; - genxAlloc alloc; - genxDealloc dealloc; - - /* Pretty-printing state */ - int ppIndent; - int ppDepth; - Boolean ppSimple; - - /* Canonicalization. */ - Boolean canonical; - - /* Attrbute order when not canonical. */ - genxAttribute firstAttribute; - genxAttribute lastAttribute; -}; - -/******************************* - * Forward declarations - */ -static genxAttribute declareAttribute(genxWriter w, genxNamespace ns, - constUtf8 name, constUtf8 valuestr, - genxStatus * statusP); -static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix); -static genxStatus unsetDefaultNamespace(genxWriter w); -static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr); -void genxSetCharProps(char * p); - -/******************************* - * End of declarations - */ - -/******************************* - * private memory utilities - */ -static void * allocate(genxWriter w, int bytes) -{ - if (w->alloc) - return (void *) (*w->alloc)(w->userData, bytes); - else - return (void *) malloc(bytes); -} - -static void deallocate(genxWriter w, void * data) -{ - if (w->dealloc) - (*w->dealloc)(w->userData, data); - else if (w->alloc == NULL) - free(data); -} - -static utf8 copy(genxWriter w, constUtf8 from) -{ - utf8 temp; - - if ((temp = (utf8) allocate(w, strlen((const char *) from) + 1)) == NULL) - return NULL; - strcpy((char *) temp, (const char *) from); - return temp; -} - -static genxStatus initCollector(genxWriter w, collector * c) -{ - c->space = 100; - if ((c->buf = (utf8) allocate(w, c->space)) == NULL) - return GENX_ALLOC_FAILED; - c->used = 0; - return GENX_SUCCESS; -} - -static genxStatus growCollector(genxWriter w, collector * c, int size) -{ - utf8 newSpace; - - c->space = size * 2; - if ((newSpace = (utf8) allocate(w, c->space)) == NULL) - return GENX_ALLOC_FAILED; - - strncpy((char *) newSpace, (const char *) c->buf, c->used); - newSpace[c->used] = 0; - deallocate(w, c->buf); - c->buf = newSpace; - return GENX_SUCCESS; -} - -static void startCollect(collector * c) -{ - c->used = 0; -} -static void endCollect(collector * c) -{ - c->buf[c->used] = 0; -} - -static genxStatus collectString(genxWriter w, collector * c, constUtf8 string) -{ - int sl = strlen((const char *) string); - - if (sl >= c->space) - if ((w->status = growCollector(w, c, sl)) != GENX_SUCCESS) - return GENX_ALLOC_FAILED; - - strcpy((char *) c->buf, (const char *) string); - return GENX_SUCCESS; -} - -#define collectPiece(w,c,d,size) {if (((c)->used+(size))>=(c)->space){if (((w)->status=growCollector(w,c,(c)->used+(size)))!=GENX_SUCCESS) return (w)->status;}strncpy((char *)(c)->buf+(c)->used,d,size);(c)->used+=size;} - -/******************************* - * private list utilities - */ -static genxStatus initPlist(genxWriter w, plist * pl) -{ - pl->writer = w; - pl->count = 0; - pl->space = 10; - pl->pointers = (void * *) allocate(w, pl->space * sizeof(void *)); - if (pl->pointers == NULL) - return GENX_ALLOC_FAILED; - - return GENX_SUCCESS; -} - -/* - * make room in a plist - */ -static Boolean checkExpand(plist * pl) -{ - void * * newlist; - int i; - - if (pl->count < pl->space) - return True; - - pl->space *= 2; - newlist = (void * *) allocate(pl->writer, pl->space * sizeof(void *)); - if (newlist == NULL) - return False; - for (i = 0; i < pl->count; i++) - newlist[i] = pl->pointers[i]; - deallocate(pl->writer, pl->pointers); - pl->pointers = newlist; - - return True; -} - -/* - * stick something on the end of a plist - */ -static genxStatus listAppend(plist * pl, void * pointer) -{ - if (!checkExpand(pl)) - return GENX_ALLOC_FAILED; - - pl->pointers[pl->count++] = pointer; - return GENX_SUCCESS; -} - -/* - * insert in place, shuffling up - */ -static genxStatus listInsert(plist * pl, void * pointer, int at) -{ - int i; - - if (!checkExpand(pl)) - return GENX_ALLOC_FAILED; - - for (i = pl->count; i > at; i--) - pl->pointers[i] = pl->pointers[i - 1]; - pl->count++; - - pl->pointers[at] = pointer; - return GENX_SUCCESS; -} - -/******************************* - * list lookups - */ - -static genxNamespace findNamespace(plist * pl, constUtf8 uri) -{ - int i; - genxNamespace * nn = (genxNamespace *) pl->pointers; - - for (i = 0; i < pl->count; i++) - if (strcmp((char *) uri, (const char *) nn[i]->name) == 0) - return nn[i]; - - return NULL; -} - -static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 type) -{ - int i; - genxElement * ee = (genxElement *) pl->pointers; - - for (i = 0; i < pl->count; i++) - { - if (xmlns == NULL) - { - if (ee[i]->ns == NULL && strcmp((const char *) type, - (const char *) ee[i]->type) == 0) - return ee[i]; - } - else - { - if (ee[i]->ns != NULL && - strcmp((const char *) xmlns, (const char *) ee[i]->ns->name) == 0 && - strcmp((const char *) type, (const char *) ee[i]->type) == 0) - return ee[i]; - } - } - - return NULL; -} - -/* - * store & intern a prefix, after giving it the - * "xmlns:" prefix. Don't allow storing the same one twice unless 'force' - * is set. - */ -static utf8 storePrefix(genxWriter w, constUtf8 prefix, Boolean force) -{ - int high, low; - utf8 * pp = (utf8 *) w->prefixes.pointers; - unsigned char buf[1024]; - - if (prefix[0] == 0) - prefix = (utf8) "xmlns"; - else - { - sprintf((char *) buf, "xmlns:%s", prefix); - prefix = buf; - } - - high = w->prefixes.count; low = -1; - while (high - low > 1) - { - int probe = (high + low) / 2; - if (strcmp((const char *) prefix, (const char *) pp[probe]) < 0) - high = probe; - else - low = probe; - } - - /* already there? */ - if (low != -1 && strcmp((const char *) prefix, (const char *) pp[low]) == 0) - { - if (force) - return pp[low]; - - w->status = GENX_DUPLICATE_PREFIX; - return NULL; - } - - /* copy & insert */ - if ((prefix = copy(w, prefix)) == NULL) - { - w->status = GENX_ALLOC_FAILED; - return NULL; - } - - w->status = listInsert(&w->prefixes, (void *) prefix, high); - if (w->status != GENX_SUCCESS) - return NULL; - - return (utf8) prefix; -} - -/******************************* - * UTF8 bit-banging - */ - -/* - * Retrieve the character pointed at, and advance the pointer; return -1 on - * error - */ -int genxNextUnicodeChar(constUtf8 * sp) -{ - utf8 s = (utf8) *sp; - int c; - - if (*s == 0) - return -1; - - if (*s < 0x80) - c = *s++; - - /* all this encoding sanity-checking taken from section 3.10 of Unicode 4 */ - else if (*s < 0xc2) - goto malformed; - - /* 2-byte encodings, first byte c2 .. df */ - else if (*s < 0xe0) - { - c = (*s++ & 0x1f) << 6; - - /* - * for this common idiom, if ((c & 0xc0) != 0x80) is slightly faster - * on MacOS (PPC) - */ - if (*s < 0x80 || *s > 0xbf) - goto malformed; - - c |= *s++ & 0x3f; - } - - /* 3-byte encodings, first byte e0 .. ef */ - else if (*s < 0xf0) - { - int b0 = *s; - c = (*s++ & 0x0f) << 12; - - if ((b0 == 0xe0 && (*s < 0xa0 || *s > 0xbf)) || - (b0 < 0xed && (*s < 0x80 || *s > 0xbf)) || - (b0 == 0xed && (*s < 0x80 || *s > 0x9f)) || - (b0 > 0xed && (*s < 0x80 || *s > 0xbf))) - goto malformed; - - c |= (*s++ & 0x3f) << 6; - - if (*s < 0x80 || *s > 0xbf) - goto malformed; - - c |= *s++ & 0x3f; - } - - /* 4-byte encodings, first byte f0 .. f4 */ - else if (*s < 0xf5) - { - int b0 = *s; - c = (*s++ & 0x07) << 18; - - if ((b0 == 0xf0 && (*s < 0x90 || *s > 0xbf)) || - (b0 < 0xf4 && (*s < 0x80 || *s > 0xbf)) || - (b0 >= 0xf4 && (*s < 0x80 || *s > 0x8f))) - goto malformed; - - c |= (*s++ & 0x3f) << 12; - - if (*s < 0x80 || *s > 0xbf) - goto malformed; - - c |= (*s++ & 0x3f) << 6; - - if (*s < 0x80 || *s > 0xbf) - goto malformed; - - c |= *s++ & 0x3f; - } - else - goto malformed; - - *sp = s; - return c; - - /* - * this is needed by scrubText, which wants to get the pointer moved - * past the problem area. - */ -malformed: - if (*s) - ++s; - *sp = s; - return -1; -} - -static Boolean isXMLChar(genxWriter w, int c) -{ - if (c < 0) - return False; - else if (c < GENX_CHAR_TABLE_SIZE) - return (int) w->xmlChars[c]; - else - return (c <= 0x10ffff); -} - -static Boolean isLetter(genxWriter w, int c) -{ - if (c < 0 || c > 0xffff) - return False; - else - { -#if GENX_CHAR_TABLE_SIZE == 0x10000 - return w->xmlChars[c] & GENX_LETTER; -#else - return c < GENX_CHAR_TABLE_SIZE ? (w->xmlChars[c] & GENX_LETTER) : True; -#endif - } -} - -static Boolean isNameChar(genxWriter w, int c) -{ - if (c < 0 || c > 0xffff) - return False; - else - { -#if GENX_CHAR_TABLE_SIZE == 0x10000 - return w->xmlChars[c] & GENX_NAMECHAR; -#else - return c < GENX_CHAR_TABLE_SIZE ? (w->xmlChars[c] & GENX_NAMECHAR) : True; -#endif - } -} - -/******************************* - * Constructors, setters/getters - */ - -/* - * Construct a new genxWriter - */ -genxWriter genxNew(genxAlloc alloc, genxDealloc dealloc, void * userData) -{ - genxWriter w; - genxNamespace xml; - - if (alloc) - w = (genxWriter) (*alloc)(userData, sizeof(struct genxWriter_rec)); - else - w = (genxWriter) malloc(sizeof(struct genxWriter_rec)); - - if (w == NULL) - return NULL; - - w->status = GENX_SUCCESS; - w->alloc = alloc; - w->dealloc = dealloc; - w->userData = userData; - w->sequence = SEQUENCE_NO_DOC; - - if (initPlist(w, &w->namespaces) != GENX_SUCCESS || - initPlist(w, &w->elements) != GENX_SUCCESS || - initPlist(w, &w->attributes) != GENX_SUCCESS || - initPlist(w, &w->prefixes) != GENX_SUCCESS || - initPlist(w, &w->stack) != GENX_SUCCESS) - return NULL; - - if ((w->status = initCollector(w, &w->arec.value)) != GENX_SUCCESS) - return NULL; - - if ((w->empty = copy(w, (utf8) "")) == NULL) - { - w->status = GENX_ALLOC_FAILED; - return NULL; - } - - w->xmlnsEquals = declareAttribute(w, NULL, (utf8) "xmlns", NULL, &w->status); - if (w->xmlnsEquals == NULL || w->status != GENX_SUCCESS) - return NULL; - w->defaultNsDeclared = False; - - w->nextPrefix = 1; - - genxSetCharProps(w->xmlChars); - - w->etext[GENX_SUCCESS] = "success"; - w->etext[GENX_BAD_UTF8] = "invalid UTF-8"; - w->etext[GENX_NON_XML_CHARACTER] = "non-XML character"; - w->etext[GENX_BAD_NAME] = "invalid name"; - w->etext[GENX_ALLOC_FAILED] = "memory allocation failed"; - w->etext[GENX_BAD_NAMESPACE_NAME] = "invalid namespace name"; - w->etext[GENX_INTERNAL_ERROR] = "internal error"; - w->etext[GENX_DUPLICATE_PREFIX] = "duplicate prefix"; - w->etext[GENX_SEQUENCE_ERROR] = "call out of sequence"; - w->etext[GENX_NO_START_TAG] = "no start tag for end element call"; - w->etext[GENX_IO_ERROR] = "io error"; - w->etext[GENX_MISSING_VALUE] = "missing attribute value"; - w->etext[GENX_MALFORMED_COMMENT] = "malformed comment body"; - w->etext[GENX_MALFORMED_PI] = "?> in PI"; - w->etext[GENX_XML_PI_TARGET] = "target of PI matches [xX][mM][lL]"; - w->etext[GENX_DUPLICATE_ATTRIBUTE] = "duplicate attribute"; - w->etext[GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE] = - "attribute is default namespace"; - w->etext[GENX_DUPLICATE_NAMESPACE] = - "namespace declared twice with different prefixes"; - w->etext[GENX_BAD_DEFAULT_DECLARATION] = - "default namespace declared on an element which is not in a namespace"; - - /* the xml: namespace is pre-wired */ - xml = genxDeclareNamespace(w, (utf8) "http://www.w3.org/XML/1998/namespace", - (utf8) "xml", &w->status); - if (xml == NULL) - return NULL; - xml->declCount = 1; - xml->declaration = xml->defaultDecl; - - w->ppIndent = 0; /* Pretty-printing is disabled by default. */ - w->canonical = False; /* No canonicalization by default. */ - - w->firstAttribute = NULL; - w->lastAttribute = NULL; - return w; -} - -genxStatus genxReset (genxWriter w) -{ - int i; - - /* Clean up the stack. */ - w->stack.count = 0; - - /* Reset namespace declaration counts. The first entry is the pre-wired - xml namespace. */ - ((genxNamespace) w->namespaces.pointers[0])->declCount = 1; - - for (i = 1; i < w->namespaces.count; i++) - { - ((genxNamespace) w->namespaces.pointers[i])->declCount = 0; - ((genxNamespace) w->namespaces.pointers[i])->baroque = False; - } - - /* Clear provided attributes. */ - for (i = 0; i < w->attributes.count; i++) - ((genxAttribute) w->attributes.pointers[i])->provided = False; - - /* Clear attribute list. */ - if (!w->canonical) - { - while (w->firstAttribute != NULL) - { - genxAttribute t = w->firstAttribute->next; - w->firstAttribute->next = NULL; - w->firstAttribute = t; - } - - w->lastAttribute = NULL; - } - - w->status = GENX_SUCCESS; - w->sequence = SEQUENCE_NO_DOC; - - return w->status; -} - - -/* - * get/set userData - */ -void genxSetUserData(genxWriter w, void * userData) -{ - w->userData = userData; -} -void * genxGetUserData(genxWriter w) -{ - return w->userData; -} - -/* - * get/set pretty-printing - */ -genxStatus genxSetPrettyPrint(genxWriter w, int ind) -{ - if (w->sequence == SEQUENCE_NO_DOC) - w->ppIndent = ind; - else - w->status = GENX_SEQUENCE_ERROR; - - return w->status; -} - -int genxGetPrettyPrint(genxWriter w) -{ - return w->ppIndent; -} - -/* - * get/set canonicalization. - */ -genxStatus genxSetCanonical(genxWriter w, int flag) -{ - if (w->sequence == SEQUENCE_NO_DOC) - w->canonical = flag; - else - w->status = GENX_SEQUENCE_ERROR; - - return w->status; -} - -int genxGetCanonical(genxWriter w) -{ - return w->canonical; -} - -/* - * get/set allocator - */ -void genxSetAlloc(genxWriter w, genxAlloc alloc) -{ - w->alloc = alloc; -} - -void genxSetDealloc(genxWriter w, genxDealloc dealloc) -{ - w->dealloc = dealloc; -} - -genxAlloc genxGetAlloc(genxWriter w) -{ - return w->alloc; -} - -genxDealloc genxGetDealloc(genxWriter w) -{ - return w->dealloc; -} - -/* - * Clean up - */ -void genxDispose(genxWriter w) -{ - int i; - genxNamespace * nn = (genxNamespace *) w->namespaces.pointers; - genxElement * ee = (genxElement *) w->elements.pointers; - genxAttribute * aa = (genxAttribute *) w->attributes.pointers; - utf8 * pp = (utf8 *) w->prefixes.pointers; - - for (i = 0; i < w->namespaces.count; i++) - { - deallocate(w, nn[i]->name); - deallocate(w, nn[i]); - } - - for (i = 0; i < w->elements.count; i++) - { - deallocate(w, ee[i]->type); - deallocate(w, ee[i]); - } - - for (i = 0; i < w->attributes.count; i++) - { - deallocate(w, aa[i]->name); - deallocate(w, aa[i]->value.buf); - deallocate(w, aa[i]); - } - - for(i = 0; i < w->prefixes.count; i++) - deallocate(w, pp[i]); - - deallocate(w, w->namespaces.pointers); - deallocate(w, w->elements.pointers); - deallocate(w, w->attributes.pointers); - deallocate(w, w->prefixes.pointers); - deallocate(w, w->stack.pointers); - - deallocate(w, w->arec.value.buf); - - deallocate(w, w->empty); - - /* how Oscar dealt with Igli */ - deallocate(w, w); -} - -/******************************* - * External utility routines - */ - -/* - * scan a buffer and report problems with UTF-8 encoding or non-XML characters - */ -genxStatus genxCheckText(genxWriter w, constUtf8 s) -{ - while (*s) - { - int c = genxNextUnicodeChar(&s); - if (c == -1) - return GENX_BAD_UTF8; - - if (!isXMLChar(w, c)) - return GENX_NON_XML_CHARACTER; - } - return GENX_SUCCESS; -} - -/* - * Purify some text - */ -int genxScrubText(genxWriter w, constUtf8 in, utf8 out) -{ - int problems = 0; - constUtf8 last = in; - - while (*in) - { - int c = genxNextUnicodeChar(&in); - if (c == -1) - { - problems++; - last = in; - continue; - } - - if (!isXMLChar(w, c)) - { - problems++; - last = in; - continue; - } - - while (last < in) - *out++ = *last++; - } - *out = 0; - return problems; -} - -/* - * check one character - */ -int genxCharClass(genxWriter w, int c) -{ - int ret = 0; - - if (isXMLChar(w, c)) - ret |= GENX_XML_CHAR; - if (isNameChar(w, c)) - ret |= GENX_NAMECHAR; - if (isLetter(w, c)) - ret |= GENX_LETTER; - return ret; -} - -static genxStatus checkNCName(genxWriter w, constUtf8 name) -{ - int c; - - if (name == NULL || *name == 0) - return GENX_BAD_NAME; - - c = genxNextUnicodeChar(&name); - if (!isLetter(w, c) && c != ':' && c != '_') - return GENX_BAD_NAME; - - while (*name) - { - c = genxNextUnicodeChar(&name); - if (c == -1) - return GENX_BAD_UTF8; - if (!isNameChar(w, c)) - return GENX_BAD_NAME; - } - return GENX_SUCCESS; -} - -char * genxGetErrorMessage(genxWriter w, genxStatus status) -{ - return w->etext[status]; -} -char * genxLastErrorMessage(genxWriter w) -{ - return w->etext[w->status]; -} - -/******************************* - * Declarations: namespace/element/attribute - */ - -/* - * DeclareNamespace - by far the most complex routine in Genx - */ -genxNamespace genxDeclareNamespace(genxWriter w, constUtf8 uri, - constUtf8 defaultPref, - genxStatus * statusP) -{ - genxNamespace ns; - genxAttribute defaultDecl; - unsigned char newPrefix[100]; - - if (uri == NULL || uri[0] == 0) - { - w->status = GENX_BAD_NAMESPACE_NAME; - goto busted; - } - - if ((w->status = genxCheckText(w, uri)) != GENX_SUCCESS) - goto busted; - - /* if a prefix is provided, it has to be an NCname */ - if (defaultPref != NULL && defaultPref[0] != 0 && - (w->status = checkNCName(w, defaultPref)) != GENX_SUCCESS) - goto busted; - - /* previously declared? */ - if ((ns = findNamespace(&w->namespaces, uri))) - { - /* just a lookup, really */ - if ((defaultPref == NULL) || - (defaultPref[0] == 0 && ns->defaultDecl == w->xmlnsEquals) || - (strcmp((const char *) ns->defaultDecl->name + STRLEN_XMLNS_COLON, - (const char *) defaultPref) == 0)) - { - w->status = *statusP = GENX_SUCCESS; - return ns; - } - } - - /* wasn't already declared */ - else - { - - /* make a default prefix if none provided */ - if (defaultPref == NULL) - { - sprintf((char *) newPrefix, "g%d", w->nextPrefix++); - defaultPref = newPrefix; - } - - ns = (genxNamespace) allocate(w, sizeof(struct genxNamespace_rec)); - if (ns == NULL) - { - w->status = GENX_ALLOC_FAILED; - goto busted; - } - ns->writer = w; - ns->baroque = False; - - if ((ns->name = copy(w, uri)) == NULL) - { - w->status = GENX_ALLOC_FAILED; - goto busted; - } - - if ((w->status = listAppend(&w->namespaces, ns)) != GENX_SUCCESS) - goto busted; - ns->defaultDecl = ns->declaration = NULL; - ns->declCount = 0; - } - - if (defaultPref[0] == 0) - { - if (w->defaultNsDeclared) - { - w->status = GENX_DUPLICATE_PREFIX; - goto busted; - } - defaultDecl = w->xmlnsEquals; - w->defaultNsDeclared = True; - } - else - { - /* this catches dupes too */ - if ((defaultPref = storePrefix(w, defaultPref, False)) == NULL) - goto busted; - - defaultDecl = declareAttribute(w, NULL, defaultPref, ns->name, statusP); - if (defaultDecl == NULL || *statusP != GENX_SUCCESS) - { - w->status = *statusP; - return NULL; - } - } - - if (ns->defaultDecl != NULL && defaultDecl != ns->defaultDecl) - ns->baroque = True; - ns->defaultDecl = defaultDecl; - - *statusP = GENX_SUCCESS; - return ns; - -busted: - *statusP = w->status; - return NULL; -} - -/* - * get namespace prefix - */ -utf8 genxGetNamespacePrefix(genxNamespace ns) -{ - if (ns->declaration == NULL) - return NULL; - - if (ns->declaration == ns->writer->xmlnsEquals) - return ns->writer->empty; - - return ns->declaration->name + STRLEN_XMLNS_COLON; -} - -/* - * DeclareElement - see genx.h for details - */ -genxElement genxDeclareElement(genxWriter w, - genxNamespace ns, constUtf8 type, - genxStatus * statusP) -{ - genxElement old; - genxElement el; - - if ((w->status = checkNCName(w, type)) != GENX_SUCCESS) - { - *statusP = w->status; - return NULL; - } - - /* already declared? */ - old = findElement(&w->elements, (ns == NULL) ? NULL : ns->name, type); - if (old) - return old; - - if ((el = (genxElement) allocate(w, sizeof(struct genxElement_rec))) == NULL) - { - w->status = *statusP = GENX_ALLOC_FAILED; - return NULL; - } - - el->writer = w; - el->ns = ns; - if ((el->type = copy(w, type)) == NULL) - { - w->status = *statusP = GENX_ALLOC_FAILED; - return NULL; - } - - if ((w->status = listAppend(&w->elements, el)) != GENX_SUCCESS) - { - *statusP = w->status; - return NULL; - } - - *statusP = GENX_SUCCESS; - return el; -} - -/* - * C14n ordering for attributes: - * - first, namespace declarations by the prefix being declared - * - second, unprefixed attributes by attr name - * - third, prefixed attrs by ns uri then local part - */ -static int orderAttributes(genxAttribute a1, genxAttribute a2) -{ - if (a1->atype == a2->atype) - { - if (a1->atype == ATTR_PREFIXED && a1->ns != a2->ns) - return strcmp((const char *) a1->ns->name, (const char *) a2->ns->name); - else - return strcmp((const char *) a1->name, (const char *) a2->name); - } - - else if (a1->atype == ATTR_NSDECL) - return -1; - - else if (a1->atype == ATTR_NAKED) - { - if (a2->atype == ATTR_NSDECL) - return 1; - else - return -1; - } - - else - return 1; -} - -/* - * internal declare-attribute. This one allows colonized values for - * names, so that you can declare xmlns:-type attributes - */ -static genxAttribute declareAttribute(genxWriter w, genxNamespace ns, - constUtf8 name, constUtf8 valuestr, - genxStatus * statusP) -{ - int high, low; - genxAttribute * aa = (genxAttribute *) w->attributes.pointers; - genxAttribute a; - - w->arec.ns = ns; - w->arec.name = (utf8) name; - - if (ns) - w->arec.atype = ATTR_PREFIXED; - else if (strncmp((const char *) name, "xmlns", STRLEN_XMLNS_COLON - 1) == 0) - w->arec.atype = ATTR_NSDECL; - else - w->arec.atype = ATTR_NAKED; - - if (ns && (ns->defaultDecl == w->xmlnsEquals)) - { - w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE; - goto busted; - } - - /* attribute list has to be kept sorted per c14n rules */ - high = w->attributes.count; low = -1; - while (high - low > 1) - { - int probe = (high + low) / 2; - if (orderAttributes(&w->arec, aa[probe]) < 0) - high = probe; - else - low = probe; - } - - /* if it was already there */ - if (low != -1 && orderAttributes(&w->arec, aa[low]) == 0) - return aa[low]; - - /* not there, build it */ - a = (genxAttribute) allocate(w, sizeof(struct genxAttribute_rec)); - if (a == NULL) - { - w->status = GENX_ALLOC_FAILED; - goto busted; - } - - a->writer = w; - a->ns = ns; - a->provided = False; - a->atype = w->arec.atype; - a->next = NULL; - - if ((a->name = copy(w, name)) == NULL) - { - w->status = GENX_ALLOC_FAILED; - goto busted; - } - - if ((w->status = initCollector(w, &a->value)) != GENX_SUCCESS) - goto busted; - - if (valuestr) - if ((w->status = collectString(w, &a->value, valuestr)) != GENX_SUCCESS) - goto busted; - - w->status = listInsert(&w->attributes, a, high); - if (w->status != GENX_SUCCESS) - goto busted; - - *statusP = GENX_SUCCESS; - return a; - -busted: - *statusP = w->status; - return NULL; -} - -/* - * genxDeclareAttribute - see genx.h for details - */ -genxAttribute genxDeclareAttribute(genxWriter w, - genxNamespace ns, constUtf8 name, - genxStatus * statusP) -{ - if ((w->status = checkNCName(w, name)) != GENX_SUCCESS) - { - *statusP = w->status; - return NULL; - } - - return declareAttribute(w, ns, name, NULL, statusP); -} - -/******************************* - * I/O - */ -static genxStatus sendx(genxWriter w, constUtf8 s) -{ - if (w->sender) - return (*w->sender->send)(w->userData, s); - else - return GENX_IO_ERROR; -} - -static genxStatus sendxBounded(genxWriter w, constUtf8 start, constUtf8 end) -{ - if (w->sender) - return (*w->sender->sendBounded)(w->userData, start, end); - else - return GENX_IO_ERROR; -} - -#define SendCheck(w,s) if ((w->status=sendx(w,(constUtf8)s))!=GENX_SUCCESS) return w->status - -/******************************* - * XML writing routines. The semantics of the externally-facing ones are - * written up in genx.h. Commentary here is implementation notes and - * for internal routines. - */ - -genxStatus genxStartDocSender(genxWriter w, genxSender * sender) -{ - if (w->sequence != SEQUENCE_NO_DOC) - return w->status = GENX_SEQUENCE_ERROR; - - w->sequence = SEQUENCE_PRE_DOC; - w->sender = sender; - - if (w->ppIndent) - { - w->ppSimple = True; - w->ppDepth = 0; - } - - return GENX_SUCCESS; -} - -/* - * Output new line and indentation. - */ -static genxStatus writeIndentation(genxWriter w) -{ - int i, n; - SendCheck(w, "\n"); - n = w->ppDepth * w->ppIndent; - - for (i = 0; i < n; i++) - SendCheck(w, " "); - - return w->status; -} - -/* - * Output attribute. - */ -static genxStatus writeAttribute(genxAttribute a) -{ - genxWriter w = a->writer; - - if (a->ns && a->ns->baroque && a->ns->declaration == w->xmlnsEquals) - return w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE; - - SendCheck(w, " "); - - if (a->ns) - { - SendCheck(w, a->ns->declaration->name + STRLEN_XMLNS_COLON); - SendCheck(w, ":"); - } - - SendCheck(w, a->name); - SendCheck(w, "=\""); - SendCheck(w, a->value.buf); - SendCheck(w, "\""); - - return w->status; -} - -/* - * Write out the attributes we've been gathering up for an element. We save - * them until we've gathered them all so they can be writen in canonical - * order. - * Also, we end the start-tag. - * The trick here is that we keep the attribute list properly sorted as - * we build it, then as each attribute is added, we fill in its value and - * mark the fact that it's been added, in the "provided" field. - */ -static genxStatus writeStartTag(genxWriter w, Boolean close) -{ - int i; - genxAttribute * aa = (genxAttribute *) w->attributes.pointers; - genxElement e = w->nowStarting; - - /* - * make sure the right namespace decls are in effect; - * if they are these might create an error, so ignore it - */ - if (e->ns) - addNamespace(e->ns, NULL); - else - unsetDefaultNamespace(w); - w->status = GENX_SUCCESS; - - if (w->ppIndent) - { - if (w->ppDepth) - if (writeIndentation (w) != GENX_SUCCESS) - return w->status; - - if (!close) - { - w->ppDepth++; - w->ppSimple = True; - } - } - - SendCheck(w, "<"); - if (e->ns && (e->ns->declaration != w->xmlnsEquals)) - { - SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); - SendCheck(w, ":"); - } - SendCheck(w, e->type); - - /* If we are canonicalizing, then write sorted attributes. Otherwise - write them in the order specified. */ - if (w->canonical) - { - for (i = 0; i < w->attributes.count; i++) - { - if (aa[i]->provided) - { - if (writeAttribute (aa[i]) != GENX_SUCCESS) - return w->status; - - aa[i]->provided = False; - } - } - } - else - { - /* Keep the chain consistent even if we bail out mid way because of - an error. This way we will still be able to clear it in reset().*/ - while (w->firstAttribute != NULL) - { - genxAttribute t = w->firstAttribute->next; - - if (writeAttribute (w->firstAttribute) != GENX_SUCCESS) - return w->status; - - w->firstAttribute->provided = False; - w->firstAttribute->next = NULL; - w->firstAttribute = t; - } - - w->lastAttribute = NULL; - } - - if (close) - SendCheck(w, "/"); - SendCheck(w, ">"); - return GENX_SUCCESS; -} - -/* - * internal clear-er; no sequence checking - */ -static genxStatus unsetDefaultNamespace(genxWriter w) -{ - int i; - Boolean found = False; - - /* don't put it in if not needed */ - i = w->stack.count - 1; - while (found == False && i > 0) - { - while (w->stack.pointers[i] != NULL) - { - genxAttribute decl = (genxAttribute) w->stack.pointers[i--]; - genxNamespace ns = (genxNamespace) w->stack.pointers[i--]; - - /* if already unset */ - if (ns == NULL) - return w->status = GENX_SUCCESS; - - /* - * the default namespace was declared. This namespace now - * becomes baroque - */ - if (decl == w->xmlnsEquals) - { - ns->baroque = True; - found = True; - break; - } - } - i -= 2; - } - - if (!found) - return GENX_SUCCESS; - - /* - * push a signal on the stack - */ - if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS) - return w->status; - w->status = listAppend(&w->stack, w->xmlnsEquals); - if (w->status != GENX_SUCCESS) - return w->status; - - /* add the xmlns= attribute, it must be the first one */ - return addAttribute(w->xmlnsEquals, w->empty); -} - -/* - * clear the default namespace declaration - */ -genxStatus genxUnsetDefaultNamespace(genxWriter w) -{ - - /* can only do this while in start-tag mode */ - if (w->sequence != SEQUENCE_START_TAG) - return w->status = GENX_SEQUENCE_ERROR; - - return unsetDefaultNamespace(w); -} - -genxStatus genxStartElement(genxElement e) -{ - genxWriter w = e->writer; - - switch (w->sequence) - { - case SEQUENCE_NO_DOC: - case SEQUENCE_POST_DOC: - case SEQUENCE_START_ATTR: - return w->status = GENX_SEQUENCE_ERROR; - case SEQUENCE_START_TAG: - case SEQUENCE_ATTRIBUTES: - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - break; - case SEQUENCE_PRE_DOC: - case SEQUENCE_CONTENT: - break; - } - - w->sequence = SEQUENCE_START_TAG; - - /* - * push the stack. We push a NULL after a pointer to this element - * because the stack will also contain pointers to the namespace - * attributes that got declared here, so we can keep track of what's - * in effect. I.e. a single stack entry consists logically of a pointer - * to an element object, a NULL, then zero or more pairs of pointers to - * namespace objects/declarations - */ - if ((w->status = listAppend(&w->stack, e)) != GENX_SUCCESS) - return w->status; - if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS) - return w->status; - - w->nowStarting = e; - - return GENX_SUCCESS; -} - -/* - * internal namespace adder; no sequence checking - */ -static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix) -{ - genxWriter w = ns->writer; - genxAttribute decl; - int i; - genxElement e; - - /* - * first, we'll find the declaring attribute - */ - if (prefix == NULL) - decl = ns->defaultDecl; - else - { - if (prefix[0] == 0) - decl = w->xmlnsEquals; - else - { - if ((prefix = storePrefix(w, prefix, True)) == NULL) - return w->status; - decl = declareAttribute(w, NULL, prefix, ns->name, &w->status); - if (decl == NULL || w->status != GENX_SUCCESS) - return w->status; - } - } - - if (decl != ns->defaultDecl) - ns->baroque = True; - - /* - * avoid doing anything if this namespace is already declared. If - * they've shown good taste we can do this cheaply - */ - if (!ns->baroque) - { - if (ns->declCount > 0) - return w->status = GENX_SUCCESS; - } - else - { - - /* - * First, we'll run all the way up the stack to see if there is - * another declaration for this namespace/prefix in scope, in which - * case it's a no-op; or, if there's another declaration for this - * prefix on another namespace, in which case we have to over-ride - */ - i = w->stack.count - 1; - while (i > 0) - { - while (w->stack.pointers[i] != NULL) - { - genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--]; - genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--]; - - if (ns == otherNs) - { - if (decl == otherDecl) - return w->status = GENX_SUCCESS; - else - { - i = 0; - break; - } - } - else - { - /* different namespace, same prefix? */ - if (decl == otherDecl) - { - i = 0; - break; - } - } - } - i -= 2; - } - } - - /* - * If this namespace is already declared on - * this element (with different prefix/decl) which is an error. - */ - i = w->stack.count - 1; - while (w->stack.pointers[i] != NULL) - { - genxNamespace otherNs; - i--; /* don't need declaration */ - otherNs = (genxNamespace) w->stack.pointers[i--]; - - if (ns == otherNs) - return w->status = GENX_DUPLICATE_NAMESPACE; - } - - /* move pointer from NULL to element */ - --i; - - /* - * It's also an error if this is a default-namespace declaration and the - * element is in no namespace. - */ - e = (genxElement) w->stack.pointers[i]; - if (e->ns == NULL && decl == w->xmlnsEquals) - return w->status = GENX_BAD_DEFAULT_DECLARATION; - - if ((w->status = listAppend(&w->stack, ns)) != GENX_SUCCESS) - return w->status; - if ((w->status = listAppend(&w->stack, decl)) != GENX_SUCCESS) - return w->status; - - ns->declaration = decl; - ns->declCount++; - return addAttribute(decl, ns->name); -} - -/* - * Add a namespace declaration - */ -genxStatus genxAddNamespace(genxNamespace ns, constUtf8 prefix) -{ - if (ns->writer->sequence != SEQUENCE_START_TAG) - return ns->writer->status = GENX_SEQUENCE_ERROR; - - return addNamespace(ns, prefix); -} - -/* - * Private attribute-adding code - * most of the work here is normalizing the value, which is the same - * as regular normalization except for " is replaced by """ - */ -static genxStatus collectAttributeValue (genxWriter w, collector* value, - constUtf8 start, constUtf8 end) -{ - /* If end is NULL then the length of the value is unknown and - the value is 0-terminated. */ - - utf8 last = (utf8) start; - - while (end != NULL ? start < end : *start) - { - int c = genxNextUnicodeChar(&start); - - if (c == -1) - return w->status = GENX_BAD_UTF8; - - if (!isXMLChar(w, c)) - return w->status = GENX_NON_XML_CHARACTER; - - switch(c) - { - case 9: - collectPiece(w, value, " ", 5); - break; - case 0xa: - collectPiece(w, value, " ", 5); - break; - case 0xd: - collectPiece(w, value, " ", 5); - break; - case '"': - collectPiece(w, value, """, 6); - break; - case '<': - collectPiece(w, value, "<", 4); - break; - case '&': - collectPiece(w, value, "&", 5); - break; - /* - case '>': - collectPiece(w, value, ">", 4); - break; - */ - default: - collectPiece(w, value, (const char *) last, start - last); - break; - } - last = (utf8) start; - } - - return GENX_SUCCESS; -} - -static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr) -{ - genxWriter w = a->writer; - - /* if valuestr not provided, this is an xmlns with a pre-cooked value */ - if (valuestr) - { - startCollect(&a->value); - - if (collectAttributeValue (w, &a->value, valuestr, NULL) != GENX_SUCCESS) - return w->status; - - endCollect(&a->value); - } - - /* now add the namespace attribute; might fail if it's been hand-declared */ - if (a->ns) - addNamespace(a->ns, NULL); - - if (valuestr && a->provided) - return w->status = GENX_DUPLICATE_ATTRIBUTE; - - a->provided = True; - - /* Add the attribute to the ordered list if not canonical. */ - if (!w->canonical) - { - if (w->lastAttribute != NULL) - w->lastAttribute = w->lastAttribute->next = a; - else - w->lastAttribute = w->firstAttribute = a; - } - - return GENX_SUCCESS; -} - -/* - * public attribute adder. - * The only difference is that it doesn't allow a NULL value - */ -genxStatus genxAddAttribute(genxAttribute a, constUtf8 valuestr) -{ - if (a->writer->sequence != SEQUENCE_START_TAG && - a->writer->sequence != SEQUENCE_ATTRIBUTES) - return a->writer->status = GENX_SEQUENCE_ERROR; - a->writer->sequence = SEQUENCE_ATTRIBUTES; - - if (valuestr == NULL) - return a->writer->status = GENX_MISSING_VALUE; - - return addAttribute(a, valuestr); -} - -genxStatus genxStartAttribute(genxAttribute a) -{ - genxWriter w = a->writer; - - if (w->sequence != SEQUENCE_START_TAG && - w->sequence != SEQUENCE_ATTRIBUTES) - return w->status = GENX_SEQUENCE_ERROR; - - w->sequence = SEQUENCE_START_ATTR; - w->nowStartingAttr = a; - - startCollect(&a->value); - - return GENX_SUCCESS; -} - -genxStatus genxEndAttribute(genxWriter w) -{ - genxAttribute a; - - if (w->sequence != SEQUENCE_START_ATTR) - return w->status = GENX_SEQUENCE_ERROR; - - a = w->nowStartingAttr; - w->sequence = SEQUENCE_ATTRIBUTES; - - endCollect(&a->value); - - /* now add the namespace attribute; might fail if it's been hand-declared */ - if (a->ns) - addNamespace(a->ns, NULL); - - if (a->provided) - return w->status = GENX_DUPLICATE_ATTRIBUTE; - - a->provided = True; - - /* Add the attribute to the ordered list if not canonical. */ - if (!w->canonical) - { - if (w->lastAttribute != NULL) - w->lastAttribute = w->lastAttribute->next = a; - else - w->lastAttribute = w->firstAttribute = a; - } - - return GENX_SUCCESS; -} - -genxStatus genxEndElement(genxWriter w) -{ - int i; - Boolean close = True; - - switch (w->sequence) - { - case SEQUENCE_NO_DOC: - case SEQUENCE_PRE_DOC: - case SEQUENCE_POST_DOC: - case SEQUENCE_START_ATTR: - return w->status = GENX_SEQUENCE_ERROR; - case SEQUENCE_START_TAG: - case SEQUENCE_ATTRIBUTES: - if ((w->status = writeStartTag(w, !w->canonical)) != GENX_SUCCESS) - return w->status; - close = w->canonical; - break; - case SEQUENCE_CONTENT: - break; - } - - /* - * Output the closing tag. - */ - if (close) - { - genxElement e; - - /* - * first peek into the stack to find the right namespace declaration - * (if any) so we can properly prefix the end-tag. Have to do this - * before unwinding the stack because that might reset some xmlns - * prefixes to the context in the parent element - */ - for (i = w->stack.count - 1; w->stack.pointers[i] != NULL; i -= 2) - ; - e = (genxElement) w->stack.pointers[--i]; - - if (w->ppIndent) - { - w->ppDepth--; - - if (!w->ppSimple) - if (writeIndentation (w) != GENX_SUCCESS) - return w->status; - } - - SendCheck(w, "ns && e->ns->declaration != w->xmlnsEquals) - { - SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); - SendCheck(w, ":"); - } - SendCheck(w, e->type); - SendCheck(w, ">"); - } - - if (w->ppIndent) - w->ppSimple = False; - - /* - * pop zero or more namespace declarations, then a null, then the - * start-element declaration off the stack - */ - w->stack.count--; - while (w->stack.pointers[w->stack.count] != NULL) - { - genxNamespace ns = (genxNamespace) w->stack.pointers[--w->stack.count]; - w->stack.count--; /* don't need decl */ - - /* if not a fake unset-default namespace */ - if (ns) - { - /* - * if they've stupidly jammed in their own namespace-prefix - * declarations, we have to go looking to see if there's another - * one in effect - */ - if (ns->baroque) - { - i = w->stack.count; - while (i > 0) - { - while (w->stack.pointers[i] != NULL) - { - genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--]; - genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--]; - - if (otherNs == ns) - { - ns->declaration = otherDecl; - i = 0; - break; - } - } - - /* skip NULL & element */ - i -= 2; - } - } - ns->declCount--; - if (ns->declCount == 0) - ns->baroque = False; - } - } - - /* pop the NULL */ - --w->stack.count; - if (w->stack.count < 0) - return w->status = GENX_NO_START_TAG; - - if (w->stack.count == 0) - w->sequence = SEQUENCE_POST_DOC; - else - w->sequence = SEQUENCE_CONTENT; - - return GENX_SUCCESS; -} - -/* - * Internal character-adder. It tries to keep the number of sendx() - * calls down by looking at each character but only doing the output - * when it has to escape something; ordinary text gets saved up in - * chunks the start of which is indicated by *breaker. - * c is the character, next points to the UTF8 representing the next - * lastsP indirectly points to the UTF8 representing the - * character, breakerP* indirectly points to the last place genx - * changed the UTF8, e.g. by escaping a '<' - */ -static genxStatus addChar(genxWriter w, int c, constUtf8 next, - constUtf8 * lastsP, constUtf8 * breakerP) -{ - if (c == -1) - return GENX_BAD_UTF8; - - if (!isXMLChar(w, c)) - return GENX_NON_XML_CHARACTER; - - switch(c) - { - case 0xd: - if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) - return w->status; - *breakerP = next; - sendx(w, (utf8) " "); - break; - case '<': - if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) - return w->status; - *breakerP = next; - sendx(w, (utf8) "<"); - break; - case '&': - if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) - return w->status; - *breakerP = next; - sendx(w, (utf8) "&"); - break; - case '>': - if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) - return w->status; - *breakerP = next; - sendx(w, (utf8) ">"); - break; - default: - break; - } - *lastsP = next; - return GENX_SUCCESS; -} - -genxStatus genxAddText(genxWriter w, constUtf8 start) -{ - constUtf8 lasts = start; - constUtf8 breaker = start; - - if (w->sequence == SEQUENCE_START_TAG || - w->sequence == SEQUENCE_ATTRIBUTES) - { - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - w->sequence = SEQUENCE_CONTENT; - } - - if (w->sequence == SEQUENCE_CONTENT) - { - while (*start) - { - int c = genxNextUnicodeChar(&start); - - w->status = addChar(w, c, start, &lasts, &breaker); - if (w->status != GENX_SUCCESS) - return w->status; - } - return sendxBounded(w, breaker, (utf8) start); - } - else if (w->sequence == SEQUENCE_START_ATTR) - { - return collectAttributeValue (w, &w->nowStartingAttr->value, start, NULL); - } - else - return w->status = GENX_SEQUENCE_ERROR; -} - -genxStatus genxAddBoundedText(genxWriter w, constUtf8 start, constUtf8 end) -{ - constUtf8 lasts = start; - constUtf8 breaker = start; - - if (w->sequence == SEQUENCE_START_TAG || - w->sequence == SEQUENCE_ATTRIBUTES) - { - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - w->sequence = SEQUENCE_CONTENT; - } - - if (w->sequence == SEQUENCE_CONTENT) - { - while (start < end) - { - int c = genxNextUnicodeChar(&start); - - w->status = addChar(w, c, (utf8) start, &lasts, &breaker); - if (w->status != GENX_SUCCESS) - return w->status; - } - return sendxBounded(w, breaker, (utf8) start); - } - else if (w->sequence == SEQUENCE_START_ATTR) - { - return collectAttributeValue (w, &w->nowStartingAttr->value, start, end); - } - else - return w->status = GENX_SEQUENCE_ERROR; -} - -genxStatus genxAddCountedText(genxWriter w, constUtf8 start, int byteCount) -{ - utf8 end = (utf8) (start + byteCount); - - return genxAddBoundedText(w, start, end); -} - -genxStatus genxAddCharacter(genxWriter w, int c) -{ - unsigned char cUTF8[10]; - utf8 lasts, breaker, next; - - if (w->sequence == SEQUENCE_START_TAG || - w->sequence == SEQUENCE_ATTRIBUTES) - { - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - w->sequence = SEQUENCE_CONTENT; - } - - if (!isXMLChar(w, c)) - return w->status = GENX_NON_XML_CHARACTER; - - if (w->sequence == SEQUENCE_START_ATTR) - { - int done = 1; - collector* value = &w->nowStartingAttr->value; - - switch(c) - { - case 9: - collectPiece(w, value, " ", 5); - break; - case 0xa: - collectPiece(w, value, " ", 5); - break; - case 0xd: - collectPiece(w, value, " ", 5); - break; - case '"': - collectPiece(w, value, """, 6); - break; - case '<': - collectPiece(w, value, "<", 4); - break; - case '&': - collectPiece(w, value, "&", 5); - break; - /* - case '>': - collectPiece(w, value, ">", 4); - break; - */ - default: - done = 0; - break; - } - - if (done) - return GENX_SUCCESS; - } - - /* make UTF8 representation of character */ - lasts = breaker = next = cUTF8; - - if (c < 0x80) - *next++ = c; - else if (c < 0x800) - { - *next++ = 0xc0 | (c >> 6); - *next++ = 0x80 | (c & 0x3f); - } - else if (c < 0x10000) - { - *next++ = 0xe0 | (c >> 12); - *next++ = 0x80 | ((c & 0xfc0) >> 6); - *next++ = 0x80 | (c & 0x3f); - } - else - { - *next++ = 0xf0 | (c >> 18); - *next++ = 0x80 | ((c & 0x3f000) >> 12); - *next++ = 0x80 | ((c & 0xfc0) >> 6); - *next++ = 0x80 | (c & 0x3f); - } - *next = 0; - - if (w->sequence == SEQUENCE_CONTENT) - { - w->status = - addChar(w, c, next, (constUtf8 *) &lasts, (constUtf8 *) &breaker); - - if (w->status != GENX_SUCCESS) - return w->status; - - return sendxBounded(w, breaker, next); - } - else if (w->sequence == SEQUENCE_START_ATTR) - { - collectPiece(w, &w->nowStartingAttr->value, - (const char *) cUTF8, next - cUTF8); - return GENX_SUCCESS; - } - else - return w->status = GENX_SEQUENCE_ERROR; -} - -genxStatus genxEndDocument(genxWriter w) -{ - if (w->sequence != SEQUENCE_POST_DOC) - return w->status = GENX_SEQUENCE_ERROR; - - /* Write a newline after the closing tag. */ - SendCheck (w, "\n"); - - if ((w->status = (*w->sender->flush)(w->userData)) != GENX_SUCCESS) - return w->status; - - w->sequence = SEQUENCE_NO_DOC; - return GENX_SUCCESS; -} - -genxStatus genxXmlDeclaration(genxWriter w, - constUtf8 ver, - constUtf8 enc, - constUtf8 stl) -{ - if (w->sequence != SEQUENCE_PRE_DOC) - return w->status = GENX_SEQUENCE_ERROR; - - if ((w->status = genxCheckText(w, ver)) != GENX_SUCCESS) - return w->status; - - if (enc != NULL && (w->status = genxCheckText(w, enc)) != GENX_SUCCESS) - return w->status; - - if (stl != NULL && (w->status = genxCheckText(w, stl)) != GENX_SUCCESS) - return w->status; - - SendCheck (w, "\n"); - - return GENX_SUCCESS; -} - -genxStatus genxComment(genxWriter w, constUtf8 text) -{ - int i; - - if (w->sequence == SEQUENCE_NO_DOC || - w->sequence == SEQUENCE_START_ATTR) - return w->status = GENX_SEQUENCE_ERROR; - - if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS) - return w->status; - - /* no leading '-', no trailing '-', no '--' */ - if (text[0] == '-') - return w->status = GENX_MALFORMED_COMMENT; - for (i = 0; text[i]; i++) - if (text[i] == '-' && (text[i + 1] == '-' || text[i + 1] == 0)) - return w->status = GENX_MALFORMED_COMMENT; - - if (w->sequence == SEQUENCE_START_TAG || - w->sequence == SEQUENCE_ATTRIBUTES) - { - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - w->sequence = SEQUENCE_CONTENT; - } - - else if (w->sequence == SEQUENCE_POST_DOC) - if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) - return w->status; - - if ((w->status = sendx(w, (utf8) "")) != GENX_SUCCESS) - return w->status; - - if (w->sequence == SEQUENCE_PRE_DOC) - if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) - return w->status; - - return GENX_SUCCESS; -} - -genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text) -{ - int i; - - if (w->sequence == SEQUENCE_NO_DOC || - w->sequence == SEQUENCE_START_ATTR) - return w->status = GENX_SEQUENCE_ERROR; - - if ((w->status = genxCheckText(w, target)) != GENX_SUCCESS) - return w->status; - if ((w->status = checkNCName(w, target)) != GENX_SUCCESS) - return w->status; - if ((strlen((const char *) target) >= 3) && - (target[0] == 'x' || target[0] == 'X') && - (target[1] == 'm' || target[1] == 'M') && - (target[2] == 'l' || target[2] == 'L') && - (target[3] == 0)) - return w->status = GENX_XML_PI_TARGET; - - if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS) - return w->status; - - /* no ?> within */ - for (i = 1; text[i]; i++) - if (text[i] == '>' && text[i - 1] == '?') - return w->status = GENX_MALFORMED_PI; - - if (w->sequence == SEQUENCE_START_TAG || - w->sequence == SEQUENCE_ATTRIBUTES) - { - if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS) - return w->status; - w->sequence = SEQUENCE_CONTENT; - } - - else if (w->sequence == SEQUENCE_POST_DOC) - if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) - return w->status; - - if ((w->status = sendx(w, (utf8) "status; - if ((w->status = sendx(w, target)) != GENX_SUCCESS) - return w->status; - if (text[0]) - { - if ((w->status = sendx(w, (utf8) " ")) != GENX_SUCCESS) - return w->status; - if ((w->status = sendx(w, text)) != GENX_SUCCESS) - return w->status; - } - if ((w->status = sendx(w, (utf8) "?>")) != GENX_SUCCESS) - return w->status; - - if (w->sequence == SEQUENCE_PRE_DOC) - if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) - return w->status; - - return GENX_SUCCESS; -} - -/******************************* - * Literal versions of the writing routines - */ -genxStatus genxStartElementLiteral(genxWriter w, - constUtf8 xmlns, constUtf8 type) -{ - genxNamespace ns = NULL; - genxElement e; - - if (xmlns) - { - ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); - if (ns == NULL || w->status != GENX_SUCCESS) - return w->status; - } - e = genxDeclareElement(w, ns, type, &w->status); - if (e == NULL || w->status != GENX_SUCCESS) - return w->status; - - return genxStartElement(e); -} - -genxStatus genxAddAttributeLiteral(genxWriter w, constUtf8 xmlns, - constUtf8 name, constUtf8 value) -{ - genxNamespace ns = NULL; - genxAttribute a; - - if (xmlns) - { - ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); - if (ns == NULL && w->status != GENX_SUCCESS) - return w->status; - } - - a = genxDeclareAttribute(w, ns, name, &w->status); - if (a == NULL || w->status != GENX_SUCCESS) - return w->status; - - return genxAddAttribute(a, value); -} - -genxStatus genxStartAttributeLiteral(genxWriter w, - constUtf8 xmlns, constUtf8 name) -{ - genxNamespace ns = NULL; - genxAttribute a; - - if (xmlns) - { - ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); - if (ns == NULL && w->status != GENX_SUCCESS) - return w->status; - } - - a = genxDeclareAttribute(w, ns, name, &w->status); - if (a == NULL || w->status != GENX_SUCCESS) - return w->status; - - return genxStartAttribute(a); -} - -genxStatus genxAddNamespaceLiteral(genxWriter w, - constUtf8 uri, constUtf8 prefix) -{ - genxNamespace ns = genxDeclareNamespace(w, uri, prefix, &w->status); - if (ns == NULL && w->status != GENX_SUCCESS) - return w->status; - - return genxAddNamespace(ns, NULL); -} - -/* - * return version - */ -char * genxGetVersion() -{ - return GENX_VERSION; -} -- cgit v1.1