diff options
author | Daniel Veillard <veillard@src.gnome.org> | 2001-05-10 14:17:55 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 2001-05-10 14:17:55 +0000 |
commit | a737459bc41f3f4558d814889f0981e2aee4b97f (patch) | |
tree | 88a8a03fcb6e462535e7d1f8f8228c7848f3d275 /catalog.c | |
parent | c17337c062d428462b57b8eb25c6867c3ee1d31b (diff) | |
download | android_external_libxml2-a737459bc41f3f4558d814889f0981e2aee4b97f.tar.gz android_external_libxml2-a737459bc41f3f4558d814889f0981e2aee4b97f.tar.bz2 android_external_libxml2-a737459bc41f3f4558d814889f0981e2aee4b97f.zip |
- Makefile.am xmlversion.h.in configure.in include/Makefile.am:
integrating catalogs
- catalog.[ch] testCatalog.c: adding a small catalo API
(only SGML catalog support).
- parser.c: restaured xmlKeepBlanksDefault(0) API
Daniel
Diffstat (limited to 'catalog.c')
-rw-r--r-- | catalog.c | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/catalog.c b/catalog.c new file mode 100644 index 00000000..437474a9 --- /dev/null +++ b/catalog.c @@ -0,0 +1,531 @@ +/** + * catalog.c: set of generic Catalog related routines + * + * Reference: SGML Open Technical Resolution TR9401:1997. + * http://www.jclark.com/sp/catalog.htm + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#include "libxml.h" + +#ifdef LIBXML_CATALOG_ENABLED +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <string.h> +#include <libxml/xmlmemory.h> +#include <libxml/hash.h> +#include <libxml/uri.h> +#include <libxml/parserInternals.h> +#include <libxml/catalog.h> +#include <libxml/xmlerror.h> + +/************************************************************************ + * * + * Types, all private * + * * + ************************************************************************/ + +typedef enum { + XML_CATA_NONE = 0, + XML_CATA_SYSTEM, + XML_CATA_PUBLIC, + XML_CATA_ENTITY, + XML_CATA_PENTITY, + XML_CATA_DOCTYPE, + XML_CATA_LINKTYPE, + XML_CATA_NOTATION, + XML_CATA_DELEGATE, + XML_CATA_BASE, + XML_CATA_CATALOG, + XML_CATA_DOCUMENT, + XML_CATA_SGMLDECL +} xmlCatalogEntryType; + +typedef struct _xmlCatalogEntry xmlCatalogEntry; +typedef xmlCatalogEntry *xmlCatalogEntryPtr; +struct _xmlCatalogEntry { + xmlCatalogEntryType type; + xmlChar *name; + xmlChar *value; +}; + +static xmlHashTablePtr xmlDefaultCatalog; + +/************************************************************************ + * * + * alloc or dealloc * + * * + ************************************************************************/ + +static xmlCatalogEntryPtr +xmlNewCatalogEntry(int type, xmlChar *name, xmlChar *value) { + xmlCatalogEntryPtr ret; + + ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "malloc of %d byte failed\n", sizeof(xmlCatalogEntry)); + return(NULL); + } + ret->type = type; + ret->name = name; + ret->value = value; + return(ret); +} + +static void +xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) { + if (ret == NULL) + return; + if (ret->name != NULL) + xmlFree(ret->name); + if (ret->value != NULL) + xmlFree(ret->value); + xmlFree(ret); +} + +/************************************************************************ + * * + * The parser * + * * + ************************************************************************/ + + +#define RAW *cur +#define NEXT cur++; +#define SKIP(x) cur += x; + +#define SKIP_BLANKS while (IS_BLANK(*cur)) NEXT; + +static const xmlChar * +xmlParseCatalogComment(const xmlChar *cur) { + if ((cur[0] != '-') || (cur[1] != '-')) + return(cur); + SKIP(2); + while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-')))) + NEXT; + if (cur[0] == 0) { + return(NULL); + } + return(cur); +} + +static const xmlChar * +xmlParseCatalogPubid(const xmlChar *cur, xmlChar **id) { + xmlChar *buf = NULL; + int len = 0; + int size = 50; + xmlChar stop; + int count = 0; + + *id = NULL; + + if (RAW == '"') { + NEXT; + stop = '"'; + } else if (RAW == '\'') { + NEXT; + stop = '\''; + } else { + stop = ' '; + } + buf = (xmlChar *) xmlMalloc(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlGenericError(xmlGenericErrorContext, + "malloc of %d byte failed\n", size); + return(NULL); + } + while (xmlIsPubidChar(*cur)) { + if ((*cur == stop) && (stop != ' ')) + break; + if ((stop == ' ') && (IS_BLANK(*cur))) + break; + if (len + 1 >= size) { + size *= 2; + buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (buf == NULL) { + xmlGenericError(xmlGenericErrorContext, + "realloc of %d byte failed\n", size); + return(NULL); + } + } + buf[len++] = *cur; + count++; + NEXT; + } + buf[len] = 0; + if (stop == ' ') { + if (!IS_BLANK(*cur)) { + xmlFree(buf); + return(NULL); + } + } else { + if (*cur != stop) { + xmlFree(buf); + return(NULL); + } + NEXT; + } + *id = buf; + return(cur); +} + +static const xmlChar * +xmlParseCatalogName(const xmlChar *cur, xmlChar **name) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + int len = 0; + int c; + + *name = NULL; + + /* + * Handler for more complex cases + */ + c = *cur; + if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) { + return(NULL); + } + + while (((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || (c == ':'))) { + buf[len++] = c; + cur++; + c = *cur; + if (len >= XML_MAX_NAMELEN) + return(NULL); + } + *name = xmlStrndup(buf, len); + return(cur); +} + +static int +xmlParseCatalog(const xmlChar *value, const char *file) { + const xmlChar *cur = value; + xmlChar *base = NULL; + + if ((cur == NULL) || (file == NULL)) + return(-1); + base = xmlStrdup((const xmlChar *) file); + + while ((cur != NULL) && (cur[0] != '0')) { + SKIP_BLANKS; + if ((cur[0] == '-') && (cur[1] == '-')) { + cur = xmlParseCatalogComment(cur); + if (cur == NULL) { + /* error */ + break; + } + } else { + xmlChar *sysid = NULL; + xmlChar *name = NULL; + xmlCatalogEntryType type = XML_CATA_NONE; + + cur = xmlParseCatalogName(cur, &name); + if (name == NULL) { + /* error */ + break; + } + if (!IS_BLANK(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) + type = XML_CATA_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) + type = XML_CATA_PUBLIC; + else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) + type = XML_CATA_DELEGATE; + else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) + type = XML_CATA_ENTITY; + else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) + type = XML_CATA_DOCTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) + type = XML_CATA_LINKTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) + type = XML_CATA_NOTATION; + else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) + type = XML_CATA_SGMLDECL; + else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) + type = XML_CATA_DOCUMENT; + else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) + type = XML_CATA_CATALOG; + else if (xmlStrEqual(name, (const xmlChar *) "BASE")) + type = XML_CATA_BASE; + else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) + type = XML_CATA_DELEGATE; + else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) { + xmlFree(name); + cur = xmlParseCatalogName(cur, &name); + if (name == NULL) { + /* error */ + break; + } + continue; + } + xmlFree(name); + + switch(type) { + case XML_CATA_ENTITY: + if (*cur == '%') + type = XML_CATA_PENTITY; + case XML_CATA_PENTITY: + case XML_CATA_DOCTYPE: + case XML_CATA_LINKTYPE: + case XML_CATA_NOTATION: + cur = xmlParseCatalogName(cur, &name); + if (cur == NULL) { + /* error */ + break; + } + if (!IS_BLANK(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + cur = xmlParseCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + case XML_CATA_PUBLIC: + case XML_CATA_SYSTEM: + case XML_CATA_DELEGATE: + cur = xmlParseCatalogPubid(cur, &name); + if (cur == NULL) { + /* error */ + break; + } + if (!IS_BLANK(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + cur = xmlParseCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + case XML_CATA_BASE: + case XML_CATA_CATALOG: + case XML_CATA_DOCUMENT: + case XML_CATA_SGMLDECL: + cur = xmlParseCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + default: + break; + } + if (cur == NULL) { + if (name != NULL) + xmlFree(name); + if (sysid != NULL) + xmlFree(sysid); + break; + } else if (type == XML_CATA_BASE) { + if (base != NULL) + xmlFree(base); + base = sysid; + } else if ((type == XML_CATA_PUBLIC) || + (type == XML_CATA_SYSTEM)) { + xmlChar *filename; + + filename = xmlBuildURI(sysid, base); + if (filename != NULL) { + + xmlHashAddEntry(xmlDefaultCatalog, name, + xmlNewCatalogEntry(type, name, filename)); + } + if (sysid != NULL) + xmlFree(sysid); + } else { + /* + * drop anything else we won't handle it + */ + if (name != NULL) + xmlFree(name); + if (sysid != NULL) + xmlFree(sysid); + } + } + } + if (base != NULL) + xmlFree(base); + if (cur == NULL) + return(-1); + return(0); +} + +/************************************************************************ + * * + * Public interfaces * + * * + ************************************************************************/ + +/* + * xmlLoadCatalog: + * @filename: a file path + * + * Load the catalog and makes its definition effective for the default + * external entity loader. + * + * Returns 0 in case of success -1 in case of error + */ +int +xmlLoadCatalog(const char *filename) { + int fd, len, ret; + struct stat info; + xmlChar *content; + + if (filename == NULL) + return(-1); + if (xmlDefaultCatalog == NULL) + xmlDefaultCatalog = xmlHashCreate(20); + if (xmlDefaultCatalog == NULL) + return(-1); + + if (stat(filename, &info) < 0) + return(-1); + + if ((fd = open(filename, O_RDONLY)) < 0) + return(-1); + + content = xmlMalloc(info.st_size + 10); + if (content == NULL) { + xmlGenericError(xmlGenericErrorContext, + "realloc of %d byte failed\n", info.st_size + 10); + } + len = read(fd, content, info.st_size); + if (len < 0) { + xmlFree(content); + return(-1); + } + content[len] = 0; + close(fd); + + ret = xmlParseCatalog(content, filename); + xmlFree(content); + return(ret); +} + +/** + * xmlCatalogCleanup: + * + * Free up all the memory associated with catalogs + */ +void +xmlCatalogCleanup(void) { + if (xmlDefaultCatalog != NULL) + xmlHashFree(xmlDefaultCatalog, + (xmlHashDeallocator) xmlFreeCatalogEntry); + xmlDefaultCatalog = NULL; +} + +/** + * xmlCatalogDumpEntry: + * @entry: the + * @out: the file. + * + * Free up all the memory associated with catalogs + */ +static void +xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) { + if ((entry == NULL) || (out == NULL)) + return; + switch (entry->type) { + case XML_CATA_ENTITY: + fprintf(out, "ENTITY "); break; + case XML_CATA_PENTITY: + fprintf(out, "ENTITY %%"); break; + case XML_CATA_DOCTYPE: + fprintf(out, "DOCTYPE "); break; + case XML_CATA_LINKTYPE: + fprintf(out, "LINKTYPE "); break; + case XML_CATA_NOTATION: + fprintf(out, "NOTATION "); break; + case XML_CATA_PUBLIC: + fprintf(out, "PUBLIC "); break; + case XML_CATA_SYSTEM: + fprintf(out, "SYSTEM "); break; + case XML_CATA_DELEGATE: + fprintf(out, "DELEGATE "); break; + case XML_CATA_BASE: + fprintf(out, "BASE "); break; + case XML_CATA_CATALOG: + fprintf(out, "CATALOG "); break; + case XML_CATA_DOCUMENT: + fprintf(out, "DOCUMENT "); break; + case XML_CATA_SGMLDECL: + fprintf(out, "SGMLDECL "); break; + default: + return; + } + switch (entry->type) { + case XML_CATA_ENTITY: + case XML_CATA_PENTITY: + case XML_CATA_DOCTYPE: + case XML_CATA_LINKTYPE: + case XML_CATA_NOTATION: + fprintf(out, "%s", entry->name); break; + case XML_CATA_PUBLIC: + case XML_CATA_SYSTEM: + case XML_CATA_SGMLDECL: + case XML_CATA_DOCUMENT: + case XML_CATA_CATALOG: + case XML_CATA_BASE: + case XML_CATA_DELEGATE: + fprintf(out, "\"%s\"", entry->name); break; + default: + break; + } + switch (entry->type) { + case XML_CATA_ENTITY: + case XML_CATA_PENTITY: + case XML_CATA_DOCTYPE: + case XML_CATA_LINKTYPE: + case XML_CATA_NOTATION: + case XML_CATA_PUBLIC: + case XML_CATA_SYSTEM: + case XML_CATA_DELEGATE: + fprintf(out, " \"%s\"", entry->value); break; + default: + break; + } + fprintf(out, "\n"); +} + +/** + * xmlCatalogDump: + * @out: the file. + * + * Free up all the memory associated with catalogs + */ +void +xmlCatalogDump(FILE *out) { + if (out == NULL) + return; + if (xmlDefaultCatalog != NULL) { + xmlHashScan(xmlDefaultCatalog, + (xmlHashScanner) xmlCatalogDumpEntry, out); + } +} +#endif /* LIBXML_CATALOG_ENABLED */ |