diff options
Diffstat (limited to 'libxsde/xsde/c/genx/genx.c')
-rw-r--r-- | libxsde/xsde/c/genx/genx.c | 292 |
1 files changed, 251 insertions, 41 deletions
diff --git a/libxsde/xsde/c/genx/genx.c b/libxsde/xsde/c/genx/genx.c index c7aac99..8fbecd8 100644 --- a/libxsde/xsde/c/genx/genx.c +++ b/libxsde/xsde/c/genx/genx.c @@ -1,27 +1,43 @@ /* * Copyright (c) 2004 by Tim Bray and Sun Microsystems. - * Copyright (c) Code Synthesis Tools CC; see the accompanying LICENSE - * file for details. + * Copyright (c) Code Synthesis Tools CC (see the LICENSE file). * - * For copying permission, see the accompanying COPYING file. + * For copying permission, see the accompanying LICENSE file. */ #include <xsde/c/pre.h> +#include <xsde/config.h> + +#ifdef XSDE_SNPRINTF +# define GENX_SNPRINTF 1 +#else +# define GENX_SNPRINTF 0 +#endif + +#ifdef XSDE_CUSTOM_ALLOCATOR +# include <xsde/allocator.h> +# define GENX_CUSTOM_ALLOC xsde_alloc +# define GENX_CUSTOM_FREE xsde_free +#endif + #define GENX_VERSION "cs-1" +/* Use snprintf() unless instructed otherwise. */ +#ifndef GENX_SNPRINTF +# define GENX_SNPRINTF 1 +#endif + +#if defined(GENX_CUSTOM_ALLOC) != defined(GENX_CUSTOM_FREE) +# error both GENX_CUSTOM_ALLOC and GENX_CUSTOM_FREE must be defined +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <xsde/config.h> - #include <xsde/c/genx/genx.h> -#ifdef XSDE_CUSTOM_ALLOCATOR -# include <xsde/allocator.h> -#endif - #define Boolean int #define True 1 #define False 0 @@ -89,7 +105,7 @@ struct genxNamespace_rec struct genxElement_rec { genxWriter writer; - utf8 type; + utf8 name; genxNamespace ns; }; @@ -140,6 +156,7 @@ struct genxWriter_rec /* Pretty-printing state */ int ppIndent; int ppDepth; + int ppSuspendDepth; /* Non-0 means we are suspended. */ Boolean ppSimple; /* Canonicalization. */ @@ -173,8 +190,8 @@ static void * allocate(genxWriter w, size_t bytes) if (w->alloc) return (void *) (*w->alloc)(w->userData, bytes); else -#ifdef XSDE_CUSTOM_ALLOCATOR - return (void *) xsde_alloc(bytes); +#ifdef GENX_CUSTOM_ALLOC + return (void *) GENX_CUSTOM_ALLOC(bytes); #else return (void *) malloc(bytes); #endif @@ -185,20 +202,24 @@ static void deallocate(genxWriter w, void * data) if (w->dealloc) (*w->dealloc)(w->userData, data); else if (w->alloc == NULL) -#ifdef XSDE_CUSTOM_ALLOCATOR - xsde_free(data); +#ifdef GENX_CUSTOM_FREE + GENX_CUSTOM_FREE(data); #else free(data); #endif + } static utf8 copy(genxWriter w, constUtf8 from) { utf8 temp; + size_t sl = strlen((const char *) from); - if ((temp = (utf8) allocate(w, strlen((const char *) from) + 1)) == NULL) + if ((temp = (utf8) allocate(w, sl + 1)) == NULL) return NULL; - strcpy((char *) temp, (const char *) from); + + memcpy(temp, from, sl); + temp[sl] = 0; return temp; } @@ -219,7 +240,7 @@ static genxStatus growCollector(genxWriter w, collector * c, size_t size) if ((newSpace = (utf8) allocate(w, c->space)) == NULL) return GENX_ALLOC_FAILED; - strncpy((char *) newSpace, (const char *) c->buf, c->used); + memcpy(newSpace, c->buf, c->used); newSpace[c->used] = 0; deallocate(w, c->buf); c->buf = newSpace; @@ -243,11 +264,13 @@ static genxStatus collectString(genxWriter w, collector * c, constUtf8 string) if ((w->status = growCollector(w, c, sl)) != GENX_SUCCESS) return GENX_ALLOC_FAILED; - strcpy((char *) c->buf, (const char *) string); + memcpy(c->buf, string, sl); + c->buf[sl] = 0; 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;} +/* Note: does not add the trailing '\0' (done by endCollect() call). */ +#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;}memcpy((char *)(c)->buf+(c)->used,d,size);(c)->used+=size;} /******************************* * private list utilities @@ -333,7 +356,7 @@ static genxNamespace findNamespace(plist * pl, constUtf8 uri) return NULL; } -static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 type) +static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 name) { size_t i; genxElement * ee = (genxElement *) pl->pointers; @@ -342,15 +365,15 @@ static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 type) { if (xmlns == NULL) { - if (ee[i]->ns == NULL && strcmp((const char *) type, - (const char *) ee[i]->type) == 0) + if (ee[i]->ns == NULL && strcmp((const char *) name, + (const char *) ee[i]->name) == 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) + strcmp((const char *) name, (const char *) ee[i]->name) == 0) return ee[i]; } } @@ -373,7 +396,18 @@ static utf8 storePrefix(genxWriter w, constUtf8 prefix, Boolean force) prefix = (utf8) "xmlns"; else { - sprintf((char *) buf, "xmlns:%s", prefix); + size_t pl = strlen((const char *) prefix); + + if (pl > sizeof(buf) - (6 + 1)) + { + w->status = GENX_BAD_NAMESPACE_NAME; + return NULL; + } + + memcpy (buf, "xmlns:", 6); + memcpy (buf + 6, prefix, pl); + buf[pl + 6] = 0; + prefix = buf; } @@ -563,8 +597,8 @@ genxWriter genxNew(genxAlloc alloc, genxDealloc dealloc, void * userData) if (alloc) w = (genxWriter) (*alloc)(userData, sizeof(struct genxWriter_rec)); else -#ifdef XSDE_CUSTOM_ALLOCATOR - w = (genxWriter) xsde_alloc(sizeof(struct genxWriter_rec)); +#ifdef GENX_CUSTOM_ALLOC + w = (genxWriter) GENX_CUSTOM_ALLOC(sizeof(struct genxWriter_rec)); #else w = (genxWriter) malloc(sizeof(struct genxWriter_rec)); #endif @@ -714,6 +748,62 @@ int genxGetPrettyPrint(genxWriter w) } /* + * Suspend/resume pretty-printing. + */ +genxStatus genxSuspendPrettyPrint(genxWriter w) +{ + int d = w->ppDepth; + + if (w->ppIndent == 0) + return w->status = GENX_SEQUENCE_ERROR; + + switch (w->sequence) + { + case SEQUENCE_START_TAG: + case SEQUENCE_ATTRIBUTES: + d++; /* No start tag written, still outer depth. */ + case SEQUENCE_CONTENT: + break; + default: + return w->status = GENX_SEQUENCE_ERROR; + } + + if (w->ppSuspendDepth == 0) /* Ignore nested suspend/resume calls. */ + w->ppSuspendDepth = d; + + return w->status; +} + +genxStatus genxResumePrettyPrint(genxWriter w) +{ + int d = w->ppDepth; + + if (w->ppIndent == 0 || w->ppSuspendDepth == 0) + return w->status = GENX_SEQUENCE_ERROR; + + switch (w->sequence) + { + case SEQUENCE_START_TAG: + case SEQUENCE_ATTRIBUTES: + d++; /* No start tag written, still outer depth. */ + case SEQUENCE_CONTENT: + break; + default: + return w->status = GENX_SEQUENCE_ERROR; + } + + if (w->ppSuspendDepth == d) /* Ignore nested suspend/resume calls. */ + w->ppSuspendDepth = 0; + + return w->status; +} + +int genxPrettyPrintSuspended(genxWriter w) +{ + return w->ppSuspendDepth; +} + +/* * get/set canonicalization. */ genxStatus genxSetCanonical(genxWriter w, int flag) @@ -773,7 +863,7 @@ void genxDispose(genxWriter w) for (i = 0; i < w->elements.count; i++) { - deallocate(w, ee[i]->type); + deallocate(w, ee[i]->name); deallocate(w, ee[i]); } @@ -947,11 +1037,14 @@ genxNamespace genxDeclareNamespace(genxWriter w, constUtf8 uri, /* wasn't already declared */ else { - /* make a default prefix if none provided */ if (defaultPref == NULL) { +#if GENX_SNPRINTF + snprintf((char *) newPrefix, sizeof(newPrefix), "g%d", w->nextPrefix++); +#else sprintf((char *) newPrefix, "g%d", w->nextPrefix++); +#endif defaultPref = newPrefix; } @@ -1030,20 +1123,20 @@ utf8 genxGetNamespacePrefix(genxNamespace ns) * DeclareElement - see genx.h for details */ genxElement genxDeclareElement(genxWriter w, - genxNamespace ns, constUtf8 type, + genxNamespace ns, constUtf8 name, genxStatus * statusP) { genxElement old; genxElement el; - if ((w->status = checkNCName(w, type)) != GENX_SUCCESS) + if ((w->status = checkNCName(w, name)) != GENX_SUCCESS) { *statusP = w->status; return NULL; } /* already declared? */ - old = findElement(&w->elements, (ns == NULL) ? NULL : ns->name, type); + old = findElement(&w->elements, (ns == NULL) ? NULL : ns->name, name); if (old) return old; @@ -1055,7 +1148,7 @@ genxElement genxDeclareElement(genxWriter w, el->writer = w; el->ns = ns; - if ((el->type = copy(w, type)) == NULL) + if ((el->name = copy(w, name)) == NULL) { w->status = *statusP = GENX_ALLOC_FAILED; return NULL; @@ -1238,8 +1331,9 @@ genxStatus genxStartDocSender(genxWriter w, genxSender * sender) if (w->ppIndent) { - w->ppSimple = True; w->ppDepth = 0; + w->ppSuspendDepth = 0; + w->ppSimple = True; } return GENX_SUCCESS; @@ -1313,7 +1407,9 @@ static genxStatus writeStartTag(genxWriter w, Boolean close) if (w->ppIndent) { - if (w->ppDepth) + if (w->ppDepth && + /* Suspend depth could be at this element's depth (after ++ below). */ + (w->ppSuspendDepth == 0 || w->ppSuspendDepth > w->ppDepth)) if (writeIndentation (w) != GENX_SUCCESS) return w->status; @@ -1322,6 +1418,15 @@ static genxStatus writeStartTag(genxWriter w, Boolean close) w->ppDepth++; w->ppSimple = True; } + else + { + /* + * Conceptually we incremented/decremented the depth, so check if we + * need to resume pretty-printing. + */ + if (w->ppSuspendDepth > w->ppDepth) + w->ppSuspendDepth = 0; + } } SendCheck(w, "<"); @@ -1330,7 +1435,7 @@ static genxStatus writeStartTag(genxWriter w, Boolean close) SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); SendCheck(w, ":"); } - SendCheck(w, e->type); + SendCheck(w, e->name); /* If we are canonicalizing, then write sorted attributes. Otherwise write them in the order specified. */ @@ -1732,6 +1837,22 @@ genxStatus genxStartAttribute(genxAttribute a) return GENX_SUCCESS; } +genxStatus genxGetCurrentAttribute (genxWriter w, + constUtf8* xmlns, constUtf8* name) +{ + genxAttribute a; + + if (w->sequence != SEQUENCE_START_ATTR) + return w->status = GENX_SEQUENCE_ERROR; + + a = w->nowStartingAttr; + + *xmlns = a->ns ? a->ns->name : NULL; + *name = a->name; + + return GENX_SUCCESS; +} + genxStatus genxEndAttribute(genxWriter w) { genxAttribute a; @@ -1765,6 +1886,36 @@ genxStatus genxEndAttribute(genxWriter w) return GENX_SUCCESS; } +genxStatus genxGetCurrentElement (genxWriter w, + constUtf8* xmlns, constUtf8* name) +{ + int i; + genxElement e; + + switch (w->sequence) + { + case SEQUENCE_START_TAG: + case SEQUENCE_ATTRIBUTES: + e = w->nowStarting; + break; + case SEQUENCE_CONTENT: + /* Find the element. The same code as in EndElement() below. */ + for (i = (int) (w->stack.count) - 1; + w->stack.pointers[i] != NULL; + i -= 2) + ; + e = (genxElement) w->stack.pointers[--i]; + break; + default: + return w->status = GENX_SEQUENCE_ERROR; + } + + *xmlns = e->ns ? e->ns->name : NULL; + *name = e->name; + + return GENX_SUCCESS; +} + genxStatus genxEndElement(genxWriter w) { int i; @@ -1810,9 +1961,12 @@ genxStatus genxEndElement(genxWriter w) { w->ppDepth--; - if (!w->ppSimple) + if (!w->ppSimple && w->ppSuspendDepth == 0) if (writeIndentation (w) != GENX_SUCCESS) return w->status; + + if (w->ppSuspendDepth > w->ppDepth) + w->ppSuspendDepth = 0; /* Resume pretty-printing. */ } SendCheck(w, "</"); @@ -1821,11 +1975,15 @@ genxStatus genxEndElement(genxWriter w) SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); SendCheck(w, ":"); } - SendCheck(w, e->type); + SendCheck(w, e->name); SendCheck(w, ">"); } - if (w->ppIndent) + /* If this element is written while pretty-printing is suspended, + treat it as simple. As an example, think of an XHTML <b> element + for which we suspend pretty-printing before writing the opening + tag and resume it after the closing one. */ + if (w->ppIndent && w->ppSuspendDepth == 0) w->ppSimple = False; /* @@ -2118,7 +2276,7 @@ genxStatus genxEndDocument(genxWriter w) return w->status = GENX_SEQUENCE_ERROR; /* Write a newline after the closing tag. */ - /* Disabled for xsde SendCheck (w, "\n");*/ + /* Disabled for xsde: SendCheck (w, "\n"); */ if ((w->status = (*w->sender->flush)(w->userData)) != GENX_SUCCESS) return w->status; @@ -2164,6 +2322,58 @@ genxStatus genxXmlDeclaration(genxWriter w, return GENX_SUCCESS; } +genxStatus genxDoctypeDeclaration(genxWriter w, + constUtf8 re, + constUtf8 pi, + constUtf8 si, + constUtf8 is) +{ + if (w->sequence != SEQUENCE_PRE_DOC) + return w->status = GENX_SEQUENCE_ERROR; + + if ((w->status = genxCheckText(w, re)) != GENX_SUCCESS) + return w->status; + + if (pi != NULL && (w->status = genxCheckText(w, pi)) != GENX_SUCCESS) + return w->status; + + if (si != NULL && (w->status = genxCheckText(w, si)) != GENX_SUCCESS) + return w->status; + + if (is != NULL && (w->status = genxCheckText(w, is)) != GENX_SUCCESS) + return w->status; + + SendCheck (w, "<!DOCTYPE "); + SendCheck (w, re); + + if (pi != NULL) + { + SendCheck (w, " PUBLIC\n \""); + SendCheck (w, pi); + SendCheck (w, "\""); + } + + if (si != NULL) + { + if (pi == NULL) + SendCheck (w, " SYSTEM"); + + SendCheck (w, "\n \""); + SendCheck (w, si); + SendCheck (w, "\""); + } + + if (is != NULL) + { + SendCheck (w, " [\n"); + SendCheck (w, is); + SendCheck (w, "\n]"); + } + + SendCheck (w, ">\n"); + return GENX_SUCCESS; +} + genxStatus genxComment(genxWriter w, constUtf8 text) { size_t i; @@ -2272,7 +2482,7 @@ genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text) * Literal versions of the writing routines */ genxStatus genxStartElementLiteral(genxWriter w, - constUtf8 xmlns, constUtf8 type) + constUtf8 xmlns, constUtf8 name) { genxNamespace ns = NULL; genxElement e; @@ -2283,7 +2493,7 @@ genxStatus genxStartElementLiteral(genxWriter w, if (ns == NULL || w->status != GENX_SUCCESS) return w->status; } - e = genxDeclareElement(w, ns, type, &w->status); + e = genxDeclareElement(w, ns, name, &w->status); if (e == NULL || w->status != GENX_SUCCESS) return w->status; |