2bba3d20f5
the use of modified default calling conventions in client code. To deal with this issue and generally clean up the mass of macros being used to support bits of the machinery, two new macros are being added: - XMLCALL, which expands to whatever is needed to nail down the calling convention for all calls across the library boundary. This must match the convention used for the system's malloc() implementation. - XMLIMPORT, defined to be whatever magic is needed to mark an entry point as imported from a dynamically loaded module (.dll, .so, .sl, whatever). These macros are used to define the XMLPARSEAPI macro already being used to define the API entry points. In addition, XMLCALL is used to define the types of callback functions, and all example code uses this explicitly in both the distributed applications and the documentation.
843 lines
20 KiB
C
Executable File
843 lines
20 KiB
C
Executable File
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
|
See the file COPYING for copying permission.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#include "expat.h"
|
|
#include "codepage.h"
|
|
#include "xmlfile.h"
|
|
#include "xmltchar.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#include <crtdbg.h>
|
|
#endif
|
|
|
|
/* This ensures proper sorting. */
|
|
|
|
#define NSSEP T('\001')
|
|
|
|
static void XMLCALL
|
|
characterData(void *userData, const XML_Char *s, int len)
|
|
{
|
|
FILE *fp = userData;
|
|
for (; len > 0; --len, ++s) {
|
|
switch (*s) {
|
|
case T('&'):
|
|
fputts(T("&"), fp);
|
|
break;
|
|
case T('<'):
|
|
fputts(T("<"), fp);
|
|
break;
|
|
case T('>'):
|
|
fputts(T(">"), fp);
|
|
break;
|
|
#ifdef W3C14N
|
|
case 13:
|
|
fputts(T("
"), fp);
|
|
break;
|
|
#else
|
|
case T('"'):
|
|
fputts(T("""), fp);
|
|
break;
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
ftprintf(fp, T("&#%d;"), *s);
|
|
break;
|
|
#endif
|
|
default:
|
|
puttc(*s, fp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
attributeValue(FILE *fp, const XML_Char *s)
|
|
{
|
|
puttc(T('='), fp);
|
|
puttc(T('"'), fp);
|
|
for (;;) {
|
|
switch (*s) {
|
|
case 0:
|
|
case NSSEP:
|
|
puttc(T('"'), fp);
|
|
return;
|
|
case T('&'):
|
|
fputts(T("&"), fp);
|
|
break;
|
|
case T('<'):
|
|
fputts(T("<"), fp);
|
|
break;
|
|
case T('"'):
|
|
fputts(T("""), fp);
|
|
break;
|
|
#ifdef W3C14N
|
|
case 9:
|
|
fputts(T("	"), fp);
|
|
break;
|
|
case 10:
|
|
fputts(T("
"), fp);
|
|
break;
|
|
case 13:
|
|
fputts(T("
"), fp);
|
|
break;
|
|
#else
|
|
case T('>'):
|
|
fputts(T(">"), fp);
|
|
break;
|
|
case 9:
|
|
case 10:
|
|
case 13:
|
|
ftprintf(fp, T("&#%d;"), *s);
|
|
break;
|
|
#endif
|
|
default:
|
|
puttc(*s, fp);
|
|
break;
|
|
}
|
|
s++;
|
|
}
|
|
}
|
|
|
|
/* Lexicographically comparing UTF-8 encoded attribute values,
|
|
is equivalent to lexicographically comparing based on the character number. */
|
|
|
|
static int
|
|
attcmp(const void *att1, const void *att2)
|
|
{
|
|
return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
|
|
}
|
|
|
|
static void XMLCALL
|
|
startElement(void *userData, const XML_Char *name, const XML_Char **atts)
|
|
{
|
|
int nAtts;
|
|
const XML_Char **p;
|
|
FILE *fp = userData;
|
|
puttc(T('<'), fp);
|
|
fputts(name, fp);
|
|
|
|
p = atts;
|
|
while (*p)
|
|
++p;
|
|
nAtts = (p - atts) >> 1;
|
|
if (nAtts > 1)
|
|
qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
|
|
while (*atts) {
|
|
puttc(T(' '), fp);
|
|
fputts(*atts++, fp);
|
|
attributeValue(fp, *atts);
|
|
atts++;
|
|
}
|
|
puttc(T('>'), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
endElement(void *userData, const XML_Char *name)
|
|
{
|
|
FILE *fp = userData;
|
|
puttc(T('<'), fp);
|
|
puttc(T('/'), fp);
|
|
fputts(name, fp);
|
|
puttc(T('>'), fp);
|
|
}
|
|
|
|
static int
|
|
nsattcmp(const void *p1, const void *p2)
|
|
{
|
|
const XML_Char *att1 = *(const XML_Char **)p1;
|
|
const XML_Char *att2 = *(const XML_Char **)p2;
|
|
int sep1 = (tcsrchr(att1, NSSEP) != 0);
|
|
int sep2 = (tcsrchr(att1, NSSEP) != 0);
|
|
if (sep1 != sep2)
|
|
return sep1 - sep2;
|
|
return tcscmp(att1, att2);
|
|
}
|
|
|
|
static void XMLCALL
|
|
startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
|
|
{
|
|
int nAtts;
|
|
int nsi;
|
|
const XML_Char **p;
|
|
FILE *fp = userData;
|
|
const XML_Char *sep;
|
|
puttc(T('<'), fp);
|
|
|
|
sep = tcsrchr(name, NSSEP);
|
|
if (sep) {
|
|
fputts(T("n1:"), fp);
|
|
fputts(sep + 1, fp);
|
|
fputts(T(" xmlns:n1"), fp);
|
|
attributeValue(fp, name);
|
|
nsi = 2;
|
|
}
|
|
else {
|
|
fputts(name, fp);
|
|
nsi = 1;
|
|
}
|
|
|
|
p = atts;
|
|
while (*p)
|
|
++p;
|
|
nAtts = (p - atts) >> 1;
|
|
if (nAtts > 1)
|
|
qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
|
|
while (*atts) {
|
|
name = *atts++;
|
|
sep = tcsrchr(name, NSSEP);
|
|
puttc(T(' '), fp);
|
|
if (sep) {
|
|
ftprintf(fp, T("n%d:"), nsi);
|
|
fputts(sep + 1, fp);
|
|
}
|
|
else
|
|
fputts(name, fp);
|
|
attributeValue(fp, *atts);
|
|
if (sep) {
|
|
ftprintf(fp, T(" xmlns:n%d"), nsi++);
|
|
attributeValue(fp, name);
|
|
}
|
|
atts++;
|
|
}
|
|
puttc(T('>'), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
endElementNS(void *userData, const XML_Char *name)
|
|
{
|
|
FILE *fp = userData;
|
|
const XML_Char *sep;
|
|
puttc(T('<'), fp);
|
|
puttc(T('/'), fp);
|
|
sep = tcsrchr(name, NSSEP);
|
|
if (sep) {
|
|
fputts(T("n1:"), fp);
|
|
fputts(sep + 1, fp);
|
|
}
|
|
else
|
|
fputts(name, fp);
|
|
puttc(T('>'), fp);
|
|
}
|
|
|
|
#ifndef W3C14N
|
|
|
|
static void XMLCALL
|
|
processingInstruction(void *userData, const XML_Char *target,
|
|
const XML_Char *data)
|
|
{
|
|
FILE *fp = userData;
|
|
puttc(T('<'), fp);
|
|
puttc(T('?'), fp);
|
|
fputts(target, fp);
|
|
puttc(T(' '), fp);
|
|
fputts(data, fp);
|
|
puttc(T('?'), fp);
|
|
puttc(T('>'), fp);
|
|
}
|
|
|
|
#endif /* not W3C14N */
|
|
|
|
static void XMLCALL
|
|
defaultCharacterData(void *userData, const XML_Char *s, int len)
|
|
{
|
|
XML_DefaultCurrent((XML_Parser) userData);
|
|
}
|
|
|
|
static void XMLCALL
|
|
defaultStartElement(void *userData, const XML_Char *name,
|
|
const XML_Char **atts)
|
|
{
|
|
XML_DefaultCurrent((XML_Parser) userData);
|
|
}
|
|
|
|
static void XMLCALL
|
|
defaultEndElement(void *userData, const XML_Char *name)
|
|
{
|
|
XML_DefaultCurrent((XML_Parser) userData);
|
|
}
|
|
|
|
static void XMLCALL
|
|
defaultProcessingInstruction(void *userData, const XML_Char *target,
|
|
const XML_Char *data)
|
|
{
|
|
XML_DefaultCurrent((XML_Parser) userData);
|
|
}
|
|
|
|
static void XMLCALL
|
|
nopCharacterData(void *userData, const XML_Char *s, int len)
|
|
{
|
|
}
|
|
|
|
static void XMLCALL
|
|
nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts)
|
|
{
|
|
}
|
|
|
|
static void XMLCALL
|
|
nopEndElement(void *userData, const XML_Char *name)
|
|
{
|
|
}
|
|
|
|
static void XMLCALL
|
|
nopProcessingInstruction(void *userData, const XML_Char *target,
|
|
const XML_Char *data)
|
|
{
|
|
}
|
|
|
|
static void XMLCALL
|
|
markup(void *userData, const XML_Char *s, int len)
|
|
{
|
|
FILE *fp = XML_GetUserData((XML_Parser) userData);
|
|
for (; len > 0; --len, ++s)
|
|
puttc(*s, fp);
|
|
}
|
|
|
|
static void
|
|
metaLocation(XML_Parser parser)
|
|
{
|
|
const XML_Char *uri = XML_GetBase(parser);
|
|
if (uri)
|
|
ftprintf(XML_GetUserData(parser), T(" uri=\"%s\""), uri);
|
|
ftprintf(XML_GetUserData(parser),
|
|
T(" byte=\"%ld\" nbytes=\"%d\" line=\"%d\" col=\"%d\""),
|
|
XML_GetCurrentByteIndex(parser),
|
|
XML_GetCurrentByteCount(parser),
|
|
XML_GetCurrentLineNumber(parser),
|
|
XML_GetCurrentColumnNumber(parser));
|
|
}
|
|
|
|
static void
|
|
metaStartDocument(void *userData)
|
|
{
|
|
fputts(T("<document>\n"), XML_GetUserData((XML_Parser) userData));
|
|
}
|
|
|
|
static void
|
|
metaEndDocument(void *userData)
|
|
{
|
|
fputts(T("</document>\n"), XML_GetUserData((XML_Parser) userData));
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaStartElement(void *userData, const XML_Char *name,
|
|
const XML_Char **atts)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
const XML_Char **specifiedAttsEnd
|
|
= atts + XML_GetSpecifiedAttributeCount(parser);
|
|
const XML_Char **idAttPtr;
|
|
int idAttIndex = XML_GetIdAttributeIndex(parser);
|
|
if (idAttIndex < 0)
|
|
idAttPtr = 0;
|
|
else
|
|
idAttPtr = atts + idAttIndex;
|
|
|
|
ftprintf(fp, T("<starttag name=\"%s\""), name);
|
|
metaLocation(parser);
|
|
if (*atts) {
|
|
fputts(T(">\n"), fp);
|
|
do {
|
|
ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
|
|
characterData(fp, atts[1], tcslen(atts[1]));
|
|
if (atts >= specifiedAttsEnd)
|
|
fputts(T("\" defaulted=\"yes\"/>\n"), fp);
|
|
else if (atts == idAttPtr)
|
|
fputts(T("\" id=\"yes\"/>\n"), fp);
|
|
else
|
|
fputts(T("\"/>\n"), fp);
|
|
} while (*(atts += 2));
|
|
fputts(T("</starttag>\n"), fp);
|
|
}
|
|
else
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaEndElement(void *userData, const XML_Char *name)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
ftprintf(fp, T("<endtag name=\"%s\""), name);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaProcessingInstruction(void *userData, const XML_Char *target,
|
|
const XML_Char *data)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
|
|
characterData(fp, data, tcslen(data));
|
|
puttc(T('"'), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaComment(void *userData, const XML_Char *data)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<comment data=\""), fp);
|
|
characterData(fp, data, tcslen(data));
|
|
puttc(T('"'), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaStartCdataSection(void *userData)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<startcdata"), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaEndCdataSection(void *userData)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<endcdata"), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaCharacterData(void *userData, const XML_Char *s, int len)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<chars str=\""), fp);
|
|
characterData(fp, s, len);
|
|
puttc(T('"'), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaStartDoctypeDecl(void *userData,
|
|
const XML_Char *doctypeName,
|
|
const XML_Char *sysid,
|
|
const XML_Char *pubid,
|
|
int has_internal_subset)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaEndDoctypeDecl(void *userData)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<enddoctype"), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaNotationDecl(void *userData,
|
|
const XML_Char *notationName,
|
|
const XML_Char *base,
|
|
const XML_Char *systemId,
|
|
const XML_Char *publicId)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
ftprintf(fp, T("<notation name=\"%s\""), notationName);
|
|
if (publicId)
|
|
ftprintf(fp, T(" public=\"%s\""), publicId);
|
|
if (systemId) {
|
|
fputts(T(" system=\""), fp);
|
|
characterData(fp, systemId, tcslen(systemId));
|
|
puttc(T('"'), fp);
|
|
}
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
|
|
static void XMLCALL
|
|
metaEntityDecl(void *userData,
|
|
const XML_Char *entityName,
|
|
int is_param,
|
|
const XML_Char *value,
|
|
int value_length,
|
|
const XML_Char *base,
|
|
const XML_Char *systemId,
|
|
const XML_Char *publicId,
|
|
const XML_Char *notationName)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
|
|
if (value) {
|
|
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
|
metaLocation(parser);
|
|
puttc(T('>'), fp);
|
|
characterData(fp, value, value_length);
|
|
fputts(T("</entity/>\n"), fp);
|
|
}
|
|
else if (notationName) {
|
|
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
|
if (publicId)
|
|
ftprintf(fp, T(" public=\"%s\""), publicId);
|
|
fputts(T(" system=\""), fp);
|
|
characterData(fp, systemId, tcslen(systemId));
|
|
puttc(T('"'), fp);
|
|
ftprintf(fp, T(" notation=\"%s\""), notationName);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
else {
|
|
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
|
if (publicId)
|
|
ftprintf(fp, T(" public=\"%s\""), publicId);
|
|
fputts(T(" system=\""), fp);
|
|
characterData(fp, systemId, tcslen(systemId));
|
|
puttc(T('"'), fp);
|
|
metaLocation(parser);
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaStartNamespaceDecl(void *userData,
|
|
const XML_Char *prefix,
|
|
const XML_Char *uri)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
fputts(T("<startns"), fp);
|
|
if (prefix)
|
|
ftprintf(fp, T(" prefix=\"%s\""), prefix);
|
|
if (uri) {
|
|
fputts(T(" ns=\""), fp);
|
|
characterData(fp, uri, tcslen(uri));
|
|
fputts(T("\"/>\n"), fp);
|
|
}
|
|
else
|
|
fputts(T("/>\n"), fp);
|
|
}
|
|
|
|
static void XMLCALL
|
|
metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
|
|
{
|
|
XML_Parser parser = (XML_Parser) userData;
|
|
FILE *fp = XML_GetUserData(parser);
|
|
if (!prefix)
|
|
fputts(T("<endns/>\n"), fp);
|
|
else
|
|
ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
|
|
}
|
|
|
|
static int XMLCALL
|
|
unknownEncodingConvert(void *data, const char *p)
|
|
{
|
|
return codepageConvert(*(int *)data, p);
|
|
}
|
|
|
|
static int XMLCALL
|
|
unknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info)
|
|
{
|
|
int cp;
|
|
static const XML_Char prefixL[] = T("windows-");
|
|
static const XML_Char prefixU[] = T("WINDOWS-");
|
|
int i;
|
|
|
|
for (i = 0; prefixU[i]; i++)
|
|
if (name[i] != prefixU[i] && name[i] != prefixL[i])
|
|
return 0;
|
|
|
|
cp = 0;
|
|
for (; name[i]; i++) {
|
|
static const XML_Char digits[] = T("0123456789");
|
|
const XML_Char *s = tcschr(digits, name[i]);
|
|
if (!s)
|
|
return 0;
|
|
cp *= 10;
|
|
cp += s - digits;
|
|
if (cp >= 0x10000)
|
|
return 0;
|
|
}
|
|
if (!codepageMap(cp, info->map))
|
|
return 0;
|
|
info->convert = unknownEncodingConvert;
|
|
/* We could just cast the code page integer to a void *,
|
|
and avoid the use of release. */
|
|
info->release = free;
|
|
info->data = malloc(sizeof(int));
|
|
if (!info->data)
|
|
return 0;
|
|
*(int *)info->data = cp;
|
|
return 1;
|
|
}
|
|
|
|
static int XMLCALL
|
|
notStandalone(void *userData)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
showVersion(XML_Char *prog)
|
|
{
|
|
XML_Char *s = prog;
|
|
XML_Char ch;
|
|
const XML_Feature *features = XML_GetFeatureList();
|
|
while ((ch = *s) != 0) {
|
|
if (ch == '/'
|
|
#ifdef WIN32
|
|
|| ch == '\\'
|
|
#endif
|
|
)
|
|
prog = s + 1;
|
|
++s;
|
|
}
|
|
ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
|
|
if (features != NULL && features[0].feature != XML_FEATURE_END) {
|
|
int i = 1;
|
|
ftprintf(stdout, T("%s"), features[0].name);
|
|
if (features[0].value)
|
|
ftprintf(stdout, T("=%ld"), features[0].value);
|
|
while (features[i].feature != XML_FEATURE_END) {
|
|
ftprintf(stdout, T(", %s"), features[i].name);
|
|
if (features[i].value)
|
|
ftprintf(stdout, T("=%ld"), features[i].value);
|
|
++i;
|
|
}
|
|
ftprintf(stdout, T("\n"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
usage(const XML_Char *prog, int rc)
|
|
{
|
|
ftprintf(stderr,
|
|
T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] "
|
|
"[-e encoding] file ...\n"), prog);
|
|
exit(rc);
|
|
}
|
|
|
|
int
|
|
tmain(int argc, XML_Char **argv)
|
|
{
|
|
int i, j;
|
|
const XML_Char *outputDir = NULL;
|
|
const XML_Char *encoding = NULL;
|
|
unsigned processFlags = XML_MAP_FILE;
|
|
int windowsCodePages = 0;
|
|
int outputType = 0;
|
|
int useNamespaces = 0;
|
|
int requireStandalone = 0;
|
|
int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
|
|
int useStdin = 0;
|
|
|
|
#ifdef _MSC_VER
|
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
|
|
#endif
|
|
|
|
i = 1;
|
|
j = 0;
|
|
while (i < argc) {
|
|
if (j == 0) {
|
|
if (argv[i][0] != T('-'))
|
|
break;
|
|
if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
|
|
i++;
|
|
break;
|
|
}
|
|
j++;
|
|
}
|
|
switch (argv[i][j]) {
|
|
case T('r'):
|
|
processFlags &= ~XML_MAP_FILE;
|
|
j++;
|
|
break;
|
|
case T('s'):
|
|
requireStandalone = 1;
|
|
j++;
|
|
break;
|
|
case T('n'):
|
|
useNamespaces = 1;
|
|
j++;
|
|
break;
|
|
case T('p'):
|
|
paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
|
|
/* fall through */
|
|
case T('x'):
|
|
processFlags |= XML_EXTERNAL_ENTITIES;
|
|
j++;
|
|
break;
|
|
case T('w'):
|
|
windowsCodePages = 1;
|
|
j++;
|
|
break;
|
|
case T('m'):
|
|
outputType = 'm';
|
|
j++;
|
|
break;
|
|
case T('c'):
|
|
outputType = 'c';
|
|
useNamespaces = 0;
|
|
j++;
|
|
break;
|
|
case T('t'):
|
|
outputType = 't';
|
|
j++;
|
|
break;
|
|
case T('d'):
|
|
if (argv[i][j + 1] == T('\0')) {
|
|
if (++i == argc)
|
|
usage(argv[0], 2);
|
|
outputDir = argv[i];
|
|
}
|
|
else
|
|
outputDir = argv[i] + j + 1;
|
|
i++;
|
|
j = 0;
|
|
break;
|
|
case T('e'):
|
|
if (argv[i][j + 1] == T('\0')) {
|
|
if (++i == argc)
|
|
usage(argv[0], 2);
|
|
encoding = argv[i];
|
|
}
|
|
else
|
|
encoding = argv[i] + j + 1;
|
|
i++;
|
|
j = 0;
|
|
break;
|
|
case T('h'):
|
|
usage(argv[0], 0);
|
|
return 0;
|
|
case T('v'):
|
|
showVersion(argv[0]);
|
|
return 0;
|
|
case T('\0'):
|
|
if (j > 1) {
|
|
i++;
|
|
j = 0;
|
|
break;
|
|
}
|
|
/* fall through */
|
|
default:
|
|
usage(argv[0], 2);
|
|
}
|
|
}
|
|
if (i == argc) {
|
|
useStdin = 1;
|
|
processFlags &= ~XML_MAP_FILE;
|
|
i--;
|
|
}
|
|
for (; i < argc; i++) {
|
|
FILE *fp = 0;
|
|
XML_Char *outName = 0;
|
|
int result;
|
|
XML_Parser parser;
|
|
if (useNamespaces)
|
|
parser = XML_ParserCreateNS(encoding, NSSEP);
|
|
else
|
|
parser = XML_ParserCreate(encoding);
|
|
if (requireStandalone)
|
|
XML_SetNotStandaloneHandler(parser, notStandalone);
|
|
XML_SetParamEntityParsing(parser, paramEntityParsing);
|
|
if (outputType == 't') {
|
|
/* This is for doing timings; this gives a more realistic estimate of
|
|
the parsing time. */
|
|
outputDir = 0;
|
|
XML_SetElementHandler(parser, nopStartElement, nopEndElement);
|
|
XML_SetCharacterDataHandler(parser, nopCharacterData);
|
|
XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
|
|
}
|
|
else if (outputDir) {
|
|
const XML_Char *file = useStdin ? T("STDIN") : argv[i];
|
|
if (tcsrchr(file, T('/')))
|
|
file = tcsrchr(file, T('/')) + 1;
|
|
#ifdef WIN32
|
|
if (tcsrchr(file, T('\\')))
|
|
file = tcsrchr(file, T('\\')) + 1;
|
|
#endif
|
|
outName = malloc((tcslen(outputDir) + tcslen(file) + 2)
|
|
* sizeof(XML_Char));
|
|
tcscpy(outName, outputDir);
|
|
tcscat(outName, T("/"));
|
|
tcscat(outName, file);
|
|
fp = tfopen(outName, T("wb"));
|
|
if (!fp) {
|
|
tperror(outName);
|
|
exit(1);
|
|
}
|
|
setvbuf(fp, NULL, _IOFBF, 16384);
|
|
#ifdef XML_UNICODE
|
|
puttc(0xFEFF, fp);
|
|
#endif
|
|
XML_SetUserData(parser, fp);
|
|
switch (outputType) {
|
|
case 'm':
|
|
XML_UseParserAsHandlerArg(parser);
|
|
XML_SetElementHandler(parser, metaStartElement, metaEndElement);
|
|
XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
|
|
XML_SetCommentHandler(parser, metaComment);
|
|
XML_SetCdataSectionHandler(parser, metaStartCdataSection,
|
|
metaEndCdataSection);
|
|
XML_SetCharacterDataHandler(parser, metaCharacterData);
|
|
XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
|
|
metaEndDoctypeDecl);
|
|
XML_SetEntityDeclHandler(parser, metaEntityDecl);
|
|
XML_SetNotationDeclHandler(parser, metaNotationDecl);
|
|
XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
|
|
metaEndNamespaceDecl);
|
|
metaStartDocument(parser);
|
|
break;
|
|
case 'c':
|
|
XML_UseParserAsHandlerArg(parser);
|
|
XML_SetDefaultHandler(parser, markup);
|
|
XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
|
|
XML_SetCharacterDataHandler(parser, defaultCharacterData);
|
|
XML_SetProcessingInstructionHandler(parser,
|
|
defaultProcessingInstruction);
|
|
break;
|
|
default:
|
|
if (useNamespaces)
|
|
XML_SetElementHandler(parser, startElementNS, endElementNS);
|
|
else
|
|
XML_SetElementHandler(parser, startElement, endElement);
|
|
XML_SetCharacterDataHandler(parser, characterData);
|
|
#ifndef W3C14N
|
|
XML_SetProcessingInstructionHandler(parser, processingInstruction);
|
|
#endif /* not W3C14N */
|
|
break;
|
|
}
|
|
}
|
|
if (windowsCodePages)
|
|
XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
|
|
result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
|
|
if (outputDir) {
|
|
if (outputType == 'm')
|
|
metaEndDocument(parser);
|
|
fclose(fp);
|
|
if (!result)
|
|
tremove(outName);
|
|
free(outName);
|
|
}
|
|
XML_ParserFree(parser);
|
|
}
|
|
return 0;
|
|
}
|