Annotation of embedaddon/libxml2/runtest.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * runtest.c: C program to run libxml2 regression tests without
        !             3:  *            requiring make or Python, and reducing platform dependancies
        !             4:  *            to a strict minimum.
        !             5:  *
        !             6:  * To compile on Unixes:
        !             7:  * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
        !             8:  *
        !             9:  * See Copyright for the status of this software.
        !            10:  *
        !            11:  * daniel@veillard.com
        !            12:  */
        !            13: 
        !            14: #ifdef HAVE_CONFIG_H
        !            15: #include "libxml.h"
        !            16: #else
        !            17: #include <stdio.h>
        !            18: #endif
        !            19: 
        !            20: #if !defined(_WIN32) || defined(__CYGWIN__)
        !            21: #include <unistd.h>
        !            22: #endif
        !            23: #include <string.h>
        !            24: #include <sys/types.h>
        !            25: #include <sys/stat.h>
        !            26: #include <fcntl.h>
        !            27: 
        !            28: #include <libxml/parser.h>
        !            29: #include <libxml/tree.h>
        !            30: #include <libxml/uri.h>
        !            31: 
        !            32: #ifdef LIBXML_OUTPUT_ENABLED
        !            33: #ifdef LIBXML_READER_ENABLED
        !            34: #include <libxml/xmlreader.h>
        !            35: #endif
        !            36: 
        !            37: #ifdef LIBXML_XINCLUDE_ENABLED
        !            38: #include <libxml/xinclude.h>
        !            39: #endif
        !            40: 
        !            41: #ifdef LIBXML_XPATH_ENABLED
        !            42: #include <libxml/xpath.h>
        !            43: #include <libxml/xpathInternals.h>
        !            44: #ifdef LIBXML_XPTR_ENABLED
        !            45: #include <libxml/xpointer.h>
        !            46: #endif
        !            47: #endif
        !            48: 
        !            49: #ifdef LIBXML_SCHEMAS_ENABLED
        !            50: #include <libxml/relaxng.h>
        !            51: #include <libxml/xmlschemas.h>
        !            52: #include <libxml/xmlschemastypes.h>
        !            53: #endif
        !            54: 
        !            55: #ifdef LIBXML_PATTERN_ENABLED
        !            56: #include <libxml/pattern.h>
        !            57: #endif
        !            58: 
        !            59: #ifdef LIBXML_C14N_ENABLED
        !            60: #include <libxml/c14n.h>
        !            61: #endif
        !            62: 
        !            63: #ifdef LIBXML_HTML_ENABLED
        !            64: #include <libxml/HTMLparser.h>
        !            65: #include <libxml/HTMLtree.h>
        !            66: 
        !            67: /*
        !            68:  * pseudo flag for the unification of HTML and XML tests
        !            69:  */
        !            70: #define XML_PARSE_HTML 1 << 24
        !            71: #endif
        !            72: 
        !            73: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
        !            74: #include <libxml/globals.h>
        !            75: #include <libxml/threads.h>
        !            76: #include <libxml/parser.h>
        !            77: #include <libxml/catalog.h>
        !            78: #include <string.h>
        !            79: #endif
        !            80: 
        !            81: /*
        !            82:  * O_BINARY is just for Windows compatibility - if it isn't defined
        !            83:  * on this system, avoid any compilation error
        !            84:  */
        !            85: #ifdef O_BINARY
        !            86: #define RD_FLAGS       O_RDONLY | O_BINARY
        !            87: #else
        !            88: #define        RD_FLAGS        O_RDONLY
        !            89: #endif
        !            90: 
        !            91: typedef int (*functest) (const char *filename, const char *result,
        !            92:                          const char *error, int options);
        !            93: 
        !            94: typedef struct testDesc testDesc;
        !            95: typedef testDesc *testDescPtr;
        !            96: struct testDesc {
        !            97:     const char *desc; /* descripton of the test */
        !            98:     functest    func; /* function implementing the test */
        !            99:     const char *in;   /* glob to path for input files */
        !           100:     const char *out;  /* output directory */
        !           101:     const char *suffix;/* suffix for output files */
        !           102:     const char *err;  /* suffix for error output files */
        !           103:     int     options;  /* parser options for the test */
        !           104: };
        !           105: 
        !           106: static int checkTestFile(const char *filename);
        !           107: 
        !           108: #if defined(_WIN32) && !defined(__CYGWIN__)
        !           109: 
        !           110: #include <windows.h>
        !           111: #include <io.h>
        !           112: 
        !           113: typedef struct
        !           114: {
        !           115:       size_t gl_pathc;    /* Count of paths matched so far  */
        !           116:       char **gl_pathv;    /* List of matched pathnames.  */
        !           117:       size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
        !           118: } glob_t;
        !           119: 
        !           120: #define GLOB_DOOFFS 0
        !           121: static int glob(const char *pattern, int flags,
        !           122:                 int errfunc(const char *epath, int eerrno),
        !           123:                 glob_t *pglob) {
        !           124:     glob_t *ret;
        !           125:     WIN32_FIND_DATA FindFileData;
        !           126:     HANDLE hFind;
        !           127:     unsigned int nb_paths = 0;
        !           128:     char directory[500];
        !           129:     int len;
        !           130: 
        !           131:     if ((pattern == NULL) || (pglob == NULL)) return(-1);
        !           132: 
        !           133:     strncpy(directory, pattern, 499);
        !           134:     for (len = strlen(directory);len >= 0;len--) {
        !           135:         if (directory[len] == '/') {
        !           136:            len++;
        !           137:            directory[len] = 0;
        !           138:            break;
        !           139:        }
        !           140:     }
        !           141:     if (len <= 0)
        !           142:         len = 0;
        !           143: 
        !           144: 
        !           145:     ret = pglob;
        !           146:     memset(ret, 0, sizeof(glob_t));
        !           147: 
        !           148:     hFind = FindFirstFileA(pattern, &FindFileData);
        !           149:     if (hFind == INVALID_HANDLE_VALUE)
        !           150:         return(0);
        !           151:     nb_paths = 20;
        !           152:     ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
        !           153:     if (ret->gl_pathv == NULL) {
        !           154:        FindClose(hFind);
        !           155:         return(-1);
        !           156:     }
        !           157:     strncpy(directory + len, FindFileData.cFileName, 499 - len);
        !           158:     ret->gl_pathv[ret->gl_pathc] = strdup(directory);
        !           159:     if (ret->gl_pathv[ret->gl_pathc] == NULL)
        !           160:         goto done;
        !           161:     ret->gl_pathc++;
        !           162:     while(FindNextFileA(hFind, &FindFileData)) {
        !           163:         if (FindFileData.cFileName[0] == '.')
        !           164:            continue;
        !           165:         if (ret->gl_pathc + 2 > nb_paths) {
        !           166:             char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
        !           167:             if (tmp == NULL)
        !           168:                 break;
        !           169:             ret->gl_pathv = tmp;
        !           170:             nb_paths *= 2;
        !           171:        }
        !           172:        strncpy(directory + len, FindFileData.cFileName, 499 - len);
        !           173:        ret->gl_pathv[ret->gl_pathc] = strdup(directory);
        !           174:         if (ret->gl_pathv[ret->gl_pathc] == NULL)
        !           175:             break;
        !           176:         ret->gl_pathc++;
        !           177:     }
        !           178:     ret->gl_pathv[ret->gl_pathc] = NULL;
        !           179: 
        !           180: done:
        !           181:     FindClose(hFind);
        !           182:     return(0);
        !           183: }
        !           184: 
        !           185: 
        !           186: 
        !           187: static void globfree(glob_t *pglob) {
        !           188:     unsigned int i;
        !           189:     if (pglob == NULL)
        !           190:         return;
        !           191: 
        !           192:     for (i = 0;i < pglob->gl_pathc;i++) {
        !           193:          if (pglob->gl_pathv[i] != NULL)
        !           194:              free(pglob->gl_pathv[i]);
        !           195:     }
        !           196: }
        !           197: #define vsnprintf _vsnprintf
        !           198: #define snprintf _snprintf
        !           199: #else
        !           200: #include <glob.h>
        !           201: #endif
        !           202: 
        !           203: /************************************************************************
        !           204:  *                                                                     *
        !           205:  *             Libxml2 specific routines                               *
        !           206:  *                                                                     *
        !           207:  ************************************************************************/
        !           208: 
        !           209: static int nb_tests = 0;
        !           210: static int nb_errors = 0;
        !           211: static int nb_leaks = 0;
        !           212: static int extraMemoryFromResolver = 0;
        !           213: 
        !           214: static int
        !           215: fatalError(void) {
        !           216:     fprintf(stderr, "Exitting tests on fatal error\n");
        !           217:     exit(1);
        !           218: }
        !           219: 
        !           220: /*
        !           221:  * We need to trap calls to the resolver to not account memory for the catalog
        !           222:  * which is shared to the current running test. We also don't want to have
        !           223:  * network downloads modifying tests.
        !           224:  */
        !           225: static xmlParserInputPtr
        !           226: testExternalEntityLoader(const char *URL, const char *ID,
        !           227:                         xmlParserCtxtPtr ctxt) {
        !           228:     xmlParserInputPtr ret;
        !           229: 
        !           230:     if (checkTestFile(URL)) {
        !           231:        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
        !           232:     } else {
        !           233:        int memused = xmlMemUsed();
        !           234:        ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
        !           235:        extraMemoryFromResolver += xmlMemUsed() - memused;
        !           236:     }
        !           237: 
        !           238:     return(ret);
        !           239: }
        !           240: 
        !           241: /*
        !           242:  * Trapping the error messages at the generic level to grab the equivalent of
        !           243:  * stderr messages on CLI tools.
        !           244:  */
        !           245: static char testErrors[32769];
        !           246: static int testErrorsSize = 0;
        !           247: 
        !           248: static void XMLCDECL
        !           249: testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
        !           250:     va_list args;
        !           251:     int res;
        !           252: 
        !           253:     if (testErrorsSize >= 32768)
        !           254:         return;
        !           255:     va_start(args, msg);
        !           256:     res = vsnprintf(&testErrors[testErrorsSize],
        !           257:                     32768 - testErrorsSize,
        !           258:                    msg, args);
        !           259:     va_end(args);
        !           260:     if (testErrorsSize + res >= 32768) {
        !           261:         /* buffer is full */
        !           262:        testErrorsSize = 32768;
        !           263:        testErrors[testErrorsSize] = 0;
        !           264:     } else {
        !           265:         testErrorsSize += res;
        !           266:     }
        !           267:     testErrors[testErrorsSize] = 0;
        !           268: }
        !           269: 
        !           270: static void XMLCDECL
        !           271: channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
        !           272:     va_list args;
        !           273:     int res;
        !           274: 
        !           275:     if (testErrorsSize >= 32768)
        !           276:         return;
        !           277:     va_start(args, msg);
        !           278:     res = vsnprintf(&testErrors[testErrorsSize],
        !           279:                     32768 - testErrorsSize,
        !           280:                    msg, args);
        !           281:     va_end(args);
        !           282:     if (testErrorsSize + res >= 32768) {
        !           283:         /* buffer is full */
        !           284:        testErrorsSize = 32768;
        !           285:        testErrors[testErrorsSize] = 0;
        !           286:     } else {
        !           287:         testErrorsSize += res;
        !           288:     }
        !           289:     testErrors[testErrorsSize] = 0;
        !           290: }
        !           291: 
        !           292: /**
        !           293:  * xmlParserPrintFileContext:
        !           294:  * @input:  an xmlParserInputPtr input
        !           295:  *
        !           296:  * Displays current context within the input content for error tracking
        !           297:  */
        !           298: 
        !           299: static void
        !           300: xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
        !           301:                xmlGenericErrorFunc chanl, void *data ) {
        !           302:     const xmlChar *cur, *base;
        !           303:     unsigned int n, col;       /* GCC warns if signed, because compared with sizeof() */
        !           304:     xmlChar  content[81]; /* space for 80 chars + line terminator */
        !           305:     xmlChar *ctnt;
        !           306: 
        !           307:     if (input == NULL) return;
        !           308:     cur = input->cur;
        !           309:     base = input->base;
        !           310:     /* skip backwards over any end-of-lines */
        !           311:     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
        !           312:        cur--;
        !           313:     }
        !           314:     n = 0;
        !           315:     /* search backwards for beginning-of-line (to max buff size) */
        !           316:     while ((n++ < (sizeof(content)-1)) && (cur > base) &&
        !           317:    (*(cur) != '\n') && (*(cur) != '\r'))
        !           318:         cur--;
        !           319:     if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
        !           320:     /* calculate the error position in terms of the current position */
        !           321:     col = input->cur - cur;
        !           322:     /* search forward for end-of-line (to max buff size) */
        !           323:     n = 0;
        !           324:     ctnt = content;
        !           325:     /* copy selected text to our buffer */
        !           326:     while ((*cur != 0) && (*(cur) != '\n') &&
        !           327:    (*(cur) != '\r') && (n < sizeof(content)-1)) {
        !           328:                *ctnt++ = *cur++;
        !           329:        n++;
        !           330:     }
        !           331:     *ctnt = 0;
        !           332:     /* print out the selected text */
        !           333:     chanl(data ,"%s\n", content);
        !           334:     /* create blank line with problem pointer */
        !           335:     n = 0;
        !           336:     ctnt = content;
        !           337:     /* (leave buffer space for pointer + line terminator) */
        !           338:     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
        !           339:        if (*(ctnt) != '\t')
        !           340:            *(ctnt) = ' ';
        !           341:        ctnt++;
        !           342:     }
        !           343:     *ctnt++ = '^';
        !           344:     *ctnt = 0;
        !           345:     chanl(data ,"%s\n", content);
        !           346: }
        !           347: 
        !           348: static void
        !           349: testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
        !           350:     char *file = NULL;
        !           351:     int line = 0;
        !           352:     int code = -1;
        !           353:     int domain;
        !           354:     void *data = NULL;
        !           355:     const char *str;
        !           356:     const xmlChar *name = NULL;
        !           357:     xmlNodePtr node;
        !           358:     xmlErrorLevel level;
        !           359:     xmlParserInputPtr input = NULL;
        !           360:     xmlParserInputPtr cur = NULL;
        !           361:     xmlParserCtxtPtr ctxt = NULL;
        !           362: 
        !           363:     if (err == NULL)
        !           364:         return;
        !           365: 
        !           366:     file = err->file;
        !           367:     line = err->line;
        !           368:     code = err->code;
        !           369:     domain = err->domain;
        !           370:     level = err->level;
        !           371:     node = err->node;
        !           372:     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
        !           373:         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
        !           374:        (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
        !           375:        ctxt = err->ctxt;
        !           376:     }
        !           377:     str = err->message;
        !           378: 
        !           379:     if (code == XML_ERR_OK)
        !           380:         return;
        !           381: 
        !           382:     if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
        !           383:         name = node->name;
        !           384: 
        !           385:     /*
        !           386:      * Maintain the compatibility with the legacy error handling
        !           387:      */
        !           388:     if (ctxt != NULL) {
        !           389:         input = ctxt->input;
        !           390:         if ((input != NULL) && (input->filename == NULL) &&
        !           391:             (ctxt->inputNr > 1)) {
        !           392:             cur = input;
        !           393:             input = ctxt->inputTab[ctxt->inputNr - 2];
        !           394:         }
        !           395:         if (input != NULL) {
        !           396:             if (input->filename)
        !           397:                 channel(data, "%s:%d: ", input->filename, input->line);
        !           398:             else if ((line != 0) && (domain == XML_FROM_PARSER))
        !           399:                 channel(data, "Entity: line %d: ", input->line);
        !           400:         }
        !           401:     } else {
        !           402:         if (file != NULL)
        !           403:             channel(data, "%s:%d: ", file, line);
        !           404:         else if ((line != 0) && (domain == XML_FROM_PARSER))
        !           405:             channel(data, "Entity: line %d: ", line);
        !           406:     }
        !           407:     if (name != NULL) {
        !           408:         channel(data, "element %s: ", name);
        !           409:     }
        !           410:     if (code == XML_ERR_OK)
        !           411:         return;
        !           412:     switch (domain) {
        !           413:         case XML_FROM_PARSER:
        !           414:             channel(data, "parser ");
        !           415:             break;
        !           416:         case XML_FROM_NAMESPACE:
        !           417:             channel(data, "namespace ");
        !           418:             break;
        !           419:         case XML_FROM_DTD:
        !           420:         case XML_FROM_VALID:
        !           421:             channel(data, "validity ");
        !           422:             break;
        !           423:         case XML_FROM_HTML:
        !           424:             channel(data, "HTML parser ");
        !           425:             break;
        !           426:         case XML_FROM_MEMORY:
        !           427:             channel(data, "memory ");
        !           428:             break;
        !           429:         case XML_FROM_OUTPUT:
        !           430:             channel(data, "output ");
        !           431:             break;
        !           432:         case XML_FROM_IO:
        !           433:             channel(data, "I/O ");
        !           434:             break;
        !           435:         case XML_FROM_XINCLUDE:
        !           436:             channel(data, "XInclude ");
        !           437:             break;
        !           438:         case XML_FROM_XPATH:
        !           439:             channel(data, "XPath ");
        !           440:             break;
        !           441:         case XML_FROM_XPOINTER:
        !           442:             channel(data, "parser ");
        !           443:             break;
        !           444:         case XML_FROM_REGEXP:
        !           445:             channel(data, "regexp ");
        !           446:             break;
        !           447:         case XML_FROM_MODULE:
        !           448:             channel(data, "module ");
        !           449:             break;
        !           450:         case XML_FROM_SCHEMASV:
        !           451:             channel(data, "Schemas validity ");
        !           452:             break;
        !           453:         case XML_FROM_SCHEMASP:
        !           454:             channel(data, "Schemas parser ");
        !           455:             break;
        !           456:         case XML_FROM_RELAXNGP:
        !           457:             channel(data, "Relax-NG parser ");
        !           458:             break;
        !           459:         case XML_FROM_RELAXNGV:
        !           460:             channel(data, "Relax-NG validity ");
        !           461:             break;
        !           462:         case XML_FROM_CATALOG:
        !           463:             channel(data, "Catalog ");
        !           464:             break;
        !           465:         case XML_FROM_C14N:
        !           466:             channel(data, "C14N ");
        !           467:             break;
        !           468:         case XML_FROM_XSLT:
        !           469:             channel(data, "XSLT ");
        !           470:             break;
        !           471:         default:
        !           472:             break;
        !           473:     }
        !           474:     if (code == XML_ERR_OK)
        !           475:         return;
        !           476:     switch (level) {
        !           477:         case XML_ERR_NONE:
        !           478:             channel(data, ": ");
        !           479:             break;
        !           480:         case XML_ERR_WARNING:
        !           481:             channel(data, "warning : ");
        !           482:             break;
        !           483:         case XML_ERR_ERROR:
        !           484:             channel(data, "error : ");
        !           485:             break;
        !           486:         case XML_ERR_FATAL:
        !           487:             channel(data, "error : ");
        !           488:             break;
        !           489:     }
        !           490:     if (code == XML_ERR_OK)
        !           491:         return;
        !           492:     if (str != NULL) {
        !           493:         int len;
        !           494:        len = xmlStrlen((const xmlChar *)str);
        !           495:        if ((len > 0) && (str[len - 1] != '\n'))
        !           496:            channel(data, "%s\n", str);
        !           497:        else
        !           498:            channel(data, "%s", str);
        !           499:     } else {
        !           500:         channel(data, "%s\n", "out of memory error");
        !           501:     }
        !           502:     if (code == XML_ERR_OK)
        !           503:         return;
        !           504: 
        !           505:     if (ctxt != NULL) {
        !           506:         xmlParserPrintFileContextInternal(input, channel, data);
        !           507:         if (cur != NULL) {
        !           508:             if (cur->filename)
        !           509:                 channel(data, "%s:%d: \n", cur->filename, cur->line);
        !           510:             else if ((line != 0) && (domain == XML_FROM_PARSER))
        !           511:                 channel(data, "Entity: line %d: \n", cur->line);
        !           512:             xmlParserPrintFileContextInternal(cur, channel, data);
        !           513:         }
        !           514:     }
        !           515:     if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
        !           516:         (err->int1 < 100) &&
        !           517:        (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
        !           518:        xmlChar buf[150];
        !           519:        int i;
        !           520: 
        !           521:        channel(data, "%s\n", err->str1);
        !           522:        for (i=0;i < err->int1;i++)
        !           523:             buf[i] = ' ';
        !           524:        buf[i++] = '^';
        !           525:        buf[i] = 0;
        !           526:        channel(data, "%s\n", buf);
        !           527:     }
        !           528: }
        !           529: 
        !           530: static void
        !           531: initializeLibxml2(void) {
        !           532:     xmlGetWarningsDefaultValue = 0;
        !           533:     xmlPedanticParserDefault(0);
        !           534: 
        !           535:     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
        !           536:     xmlInitParser();
        !           537:     xmlSetExternalEntityLoader(testExternalEntityLoader);
        !           538:     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
        !           539: #ifdef LIBXML_SCHEMAS_ENABLED
        !           540:     xmlSchemaInitTypes();
        !           541:     xmlRelaxNGInitTypes();
        !           542: #endif
        !           543: }
        !           544: 
        !           545: 
        !           546: /************************************************************************
        !           547:  *                                                                     *
        !           548:  *             File name and path utilities                            *
        !           549:  *                                                                     *
        !           550:  ************************************************************************/
        !           551: 
        !           552: static const char *baseFilename(const char *filename) {
        !           553:     const char *cur;
        !           554:     if (filename == NULL)
        !           555:         return(NULL);
        !           556:     cur = &filename[strlen(filename)];
        !           557:     while ((cur > filename) && (*cur != '/'))
        !           558:         cur--;
        !           559:     if (*cur == '/')
        !           560:         return(cur + 1);
        !           561:     return(cur);
        !           562: }
        !           563: 
        !           564: static char *resultFilename(const char *filename, const char *out,
        !           565:                             const char *suffix) {
        !           566:     const char *base;
        !           567:     char res[500];
        !           568:     char suffixbuff[500];
        !           569: 
        !           570: /*************
        !           571:     if ((filename[0] == 't') && (filename[1] == 'e') &&
        !           572:         (filename[2] == 's') && (filename[3] == 't') &&
        !           573:        (filename[4] == '/'))
        !           574:        filename = &filename[5];
        !           575:  *************/
        !           576: 
        !           577:     base = baseFilename(filename);
        !           578:     if (suffix == NULL)
        !           579:         suffix = ".tmp";
        !           580:     if (out == NULL)
        !           581:         out = "";
        !           582: 
        !           583:     strncpy(suffixbuff,suffix,499);
        !           584: #ifdef VMS
        !           585:     if(strstr(base,".") && suffixbuff[0]=='.')
        !           586:       suffixbuff[0]='_';
        !           587: #endif
        !           588: 
        !           589:     snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
        !           590:     res[499] = 0;
        !           591:     return(strdup(res));
        !           592: }
        !           593: 
        !           594: static int checkTestFile(const char *filename) {
        !           595:     struct stat buf;
        !           596: 
        !           597:     if (stat(filename, &buf) == -1)
        !           598:         return(0);
        !           599: 
        !           600: #if defined(_WIN32) && !defined(__CYGWIN__)
        !           601:     if (!(buf.st_mode & _S_IFREG))
        !           602:         return(0);
        !           603: #else
        !           604:     if (!S_ISREG(buf.st_mode))
        !           605:         return(0);
        !           606: #endif
        !           607: 
        !           608:     return(1);
        !           609: }
        !           610: 
        !           611: static int compareFiles(const char *r1, const char *r2) {
        !           612:     int res1, res2;
        !           613:     int fd1, fd2;
        !           614:     char bytes1[4096];
        !           615:     char bytes2[4096];
        !           616: 
        !           617:     fd1 = open(r1, RD_FLAGS);
        !           618:     if (fd1 < 0)
        !           619:         return(-1);
        !           620:     fd2 = open(r2, RD_FLAGS);
        !           621:     if (fd2 < 0) {
        !           622:         close(fd1);
        !           623:         return(-1);
        !           624:     }
        !           625:     while (1) {
        !           626:         res1 = read(fd1, bytes1, 4096);
        !           627:         res2 = read(fd2, bytes2, 4096);
        !           628:        if ((res1 != res2) || (res1 < 0)) {
        !           629:            close(fd1);
        !           630:            close(fd2);
        !           631:            return(1);
        !           632:        }
        !           633:        if (res1 == 0)
        !           634:            break;
        !           635:        if (memcmp(bytes1, bytes2, res1) != 0) {
        !           636:            close(fd1);
        !           637:            close(fd2);
        !           638:            return(1);
        !           639:        }
        !           640:     }
        !           641:     close(fd1);
        !           642:     close(fd2);
        !           643:     return(0);
        !           644: }
        !           645: 
        !           646: static int compareFileMem(const char *filename, const char *mem, int size) {
        !           647:     int res;
        !           648:     int fd;
        !           649:     char bytes[4096];
        !           650:     int idx = 0;
        !           651:     struct stat info;
        !           652: 
        !           653:     if (stat(filename, &info) < 0)
        !           654:        return(-1);
        !           655:     if (info.st_size != size)
        !           656:         return(-1);
        !           657:     fd = open(filename, RD_FLAGS);
        !           658:     if (fd < 0)
        !           659:         return(-1);
        !           660:     while (idx < size) {
        !           661:         res = read(fd, bytes, 4096);
        !           662:        if (res <= 0)
        !           663:            break;
        !           664:        if (res + idx > size)
        !           665:            break;
        !           666:        if (memcmp(bytes, &mem[idx], res) != 0) {
        !           667:            int ix;
        !           668:            for (ix=0; ix<res; ix++)
        !           669:                if (bytes[ix] != mem[idx+ix])
        !           670:                        break;
        !           671:            fprintf(stderr,"Compare error at position %d\n", idx+ix);
        !           672:            close(fd);
        !           673:            return(1);
        !           674:        }
        !           675:        idx += res;
        !           676:     }
        !           677:     close(fd);
        !           678:     return(idx != size);
        !           679: }
        !           680: 
        !           681: static int loadMem(const char *filename, const char **mem, int *size) {
        !           682:     int fd, res;
        !           683:     struct stat info;
        !           684:     char *base;
        !           685:     int siz = 0;
        !           686:     if (stat(filename, &info) < 0)
        !           687:        return(-1);
        !           688:     base = malloc(info.st_size + 1);
        !           689:     if (base == NULL)
        !           690:        return(-1);
        !           691:     if ((fd = open(filename, RD_FLAGS)) < 0) {
        !           692:         free(base);
        !           693:        return(-1);
        !           694:     }
        !           695:     while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
        !           696:         siz += res;
        !           697:     }
        !           698:     close(fd);
        !           699: #if !defined(_WIN32)
        !           700:     if (siz != info.st_size) {
        !           701:         free(base);
        !           702:        return(-1);
        !           703:     }
        !           704: #endif
        !           705:     base[siz] = 0;
        !           706:     *mem = base;
        !           707:     *size = siz;
        !           708:     return(0);
        !           709: }
        !           710: 
        !           711: static int unloadMem(const char *mem) {
        !           712:     free((char *)mem);
        !           713:     return(0);
        !           714: }
        !           715: 
        !           716: /************************************************************************
        !           717:  *                                                                     *
        !           718:  *             Tests implementations                                   *
        !           719:  *                                                                     *
        !           720:  ************************************************************************/
        !           721: 
        !           722: /************************************************************************
        !           723:  *                                                                     *
        !           724:  *             Parse to SAX based tests                                *
        !           725:  *                                                                     *
        !           726:  ************************************************************************/
        !           727: 
        !           728: static FILE *SAXdebug = NULL;
        !           729: 
        !           730: /*
        !           731:  * empty SAX block
        !           732:  */
        !           733: static xmlSAXHandler emptySAXHandlerStruct = {
        !           734:     NULL, /* internalSubset */
        !           735:     NULL, /* isStandalone */
        !           736:     NULL, /* hasInternalSubset */
        !           737:     NULL, /* hasExternalSubset */
        !           738:     NULL, /* resolveEntity */
        !           739:     NULL, /* getEntity */
        !           740:     NULL, /* entityDecl */
        !           741:     NULL, /* notationDecl */
        !           742:     NULL, /* attributeDecl */
        !           743:     NULL, /* elementDecl */
        !           744:     NULL, /* unparsedEntityDecl */
        !           745:     NULL, /* setDocumentLocator */
        !           746:     NULL, /* startDocument */
        !           747:     NULL, /* endDocument */
        !           748:     NULL, /* startElement */
        !           749:     NULL, /* endElement */
        !           750:     NULL, /* reference */
        !           751:     NULL, /* characters */
        !           752:     NULL, /* ignorableWhitespace */
        !           753:     NULL, /* processingInstruction */
        !           754:     NULL, /* comment */
        !           755:     NULL, /* xmlParserWarning */
        !           756:     NULL, /* xmlParserError */
        !           757:     NULL, /* xmlParserError */
        !           758:     NULL, /* getParameterEntity */
        !           759:     NULL, /* cdataBlock; */
        !           760:     NULL, /* externalSubset; */
        !           761:     1,
        !           762:     NULL,
        !           763:     NULL, /* startElementNs */
        !           764:     NULL, /* endElementNs */
        !           765:     NULL  /* xmlStructuredErrorFunc */
        !           766: };
        !           767: 
        !           768: static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
        !           769: static int callbacks = 0;
        !           770: static int quiet = 0;
        !           771: 
        !           772: /**
        !           773:  * isStandaloneDebug:
        !           774:  * @ctxt:  An XML parser context
        !           775:  *
        !           776:  * Is this document tagged standalone ?
        !           777:  *
        !           778:  * Returns 1 if true
        !           779:  */
        !           780: static int
        !           781: isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
        !           782: {
        !           783:     callbacks++;
        !           784:     if (quiet)
        !           785:        return(0);
        !           786:     fprintf(SAXdebug, "SAX.isStandalone()\n");
        !           787:     return(0);
        !           788: }
        !           789: 
        !           790: /**
        !           791:  * hasInternalSubsetDebug:
        !           792:  * @ctxt:  An XML parser context
        !           793:  *
        !           794:  * Does this document has an internal subset
        !           795:  *
        !           796:  * Returns 1 if true
        !           797:  */
        !           798: static int
        !           799: hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
        !           800: {
        !           801:     callbacks++;
        !           802:     if (quiet)
        !           803:        return(0);
        !           804:     fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
        !           805:     return(0);
        !           806: }
        !           807: 
        !           808: /**
        !           809:  * hasExternalSubsetDebug:
        !           810:  * @ctxt:  An XML parser context
        !           811:  *
        !           812:  * Does this document has an external subset
        !           813:  *
        !           814:  * Returns 1 if true
        !           815:  */
        !           816: static int
        !           817: hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
        !           818: {
        !           819:     callbacks++;
        !           820:     if (quiet)
        !           821:        return(0);
        !           822:     fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
        !           823:     return(0);
        !           824: }
        !           825: 
        !           826: /**
        !           827:  * internalSubsetDebug:
        !           828:  * @ctxt:  An XML parser context
        !           829:  *
        !           830:  * Does this document has an internal subset
        !           831:  */
        !           832: static void
        !           833: internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
        !           834:               const xmlChar *ExternalID, const xmlChar *SystemID)
        !           835: {
        !           836:     callbacks++;
        !           837:     if (quiet)
        !           838:        return;
        !           839:     fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
        !           840:     if (ExternalID == NULL)
        !           841:        fprintf(SAXdebug, " ,");
        !           842:     else
        !           843:        fprintf(SAXdebug, " %s,", ExternalID);
        !           844:     if (SystemID == NULL)
        !           845:        fprintf(SAXdebug, " )\n");
        !           846:     else
        !           847:        fprintf(SAXdebug, " %s)\n", SystemID);
        !           848: }
        !           849: 
        !           850: /**
        !           851:  * externalSubsetDebug:
        !           852:  * @ctxt:  An XML parser context
        !           853:  *
        !           854:  * Does this document has an external subset
        !           855:  */
        !           856: static void
        !           857: externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
        !           858:               const xmlChar *ExternalID, const xmlChar *SystemID)
        !           859: {
        !           860:     callbacks++;
        !           861:     if (quiet)
        !           862:        return;
        !           863:     fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
        !           864:     if (ExternalID == NULL)
        !           865:        fprintf(SAXdebug, " ,");
        !           866:     else
        !           867:        fprintf(SAXdebug, " %s,", ExternalID);
        !           868:     if (SystemID == NULL)
        !           869:        fprintf(SAXdebug, " )\n");
        !           870:     else
        !           871:        fprintf(SAXdebug, " %s)\n", SystemID);
        !           872: }
        !           873: 
        !           874: /**
        !           875:  * resolveEntityDebug:
        !           876:  * @ctxt:  An XML parser context
        !           877:  * @publicId: The public ID of the entity
        !           878:  * @systemId: The system ID of the entity
        !           879:  *
        !           880:  * Special entity resolver, better left to the parser, it has
        !           881:  * more context than the application layer.
        !           882:  * The default behaviour is to NOT resolve the entities, in that case
        !           883:  * the ENTITY_REF nodes are built in the structure (and the parameter
        !           884:  * values).
        !           885:  *
        !           886:  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
        !           887:  */
        !           888: static xmlParserInputPtr
        !           889: resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
        !           890: {
        !           891:     callbacks++;
        !           892:     if (quiet)
        !           893:        return(NULL);
        !           894:     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
        !           895: 
        !           896: 
        !           897:     fprintf(SAXdebug, "SAX.resolveEntity(");
        !           898:     if (publicId != NULL)
        !           899:        fprintf(SAXdebug, "%s", (char *)publicId);
        !           900:     else
        !           901:        fprintf(SAXdebug, " ");
        !           902:     if (systemId != NULL)
        !           903:        fprintf(SAXdebug, ", %s)\n", (char *)systemId);
        !           904:     else
        !           905:        fprintf(SAXdebug, ", )\n");
        !           906: /*********
        !           907:     if (systemId != NULL) {
        !           908:         return(xmlNewInputFromFile(ctxt, (char *) systemId));
        !           909:     }
        !           910:  *********/
        !           911:     return(NULL);
        !           912: }
        !           913: 
        !           914: /**
        !           915:  * getEntityDebug:
        !           916:  * @ctxt:  An XML parser context
        !           917:  * @name: The entity name
        !           918:  *
        !           919:  * Get an entity by name
        !           920:  *
        !           921:  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
        !           922:  */
        !           923: static xmlEntityPtr
        !           924: getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
        !           925: {
        !           926:     callbacks++;
        !           927:     if (quiet)
        !           928:        return(NULL);
        !           929:     fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
        !           930:     return(NULL);
        !           931: }
        !           932: 
        !           933: /**
        !           934:  * getParameterEntityDebug:
        !           935:  * @ctxt:  An XML parser context
        !           936:  * @name: The entity name
        !           937:  *
        !           938:  * Get a parameter entity by name
        !           939:  *
        !           940:  * Returns the xmlParserInputPtr
        !           941:  */
        !           942: static xmlEntityPtr
        !           943: getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
        !           944: {
        !           945:     callbacks++;
        !           946:     if (quiet)
        !           947:        return(NULL);
        !           948:     fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
        !           949:     return(NULL);
        !           950: }
        !           951: 
        !           952: 
        !           953: /**
        !           954:  * entityDeclDebug:
        !           955:  * @ctxt:  An XML parser context
        !           956:  * @name:  the entity name
        !           957:  * @type:  the entity type
        !           958:  * @publicId: The public ID of the entity
        !           959:  * @systemId: The system ID of the entity
        !           960:  * @content: the entity value (without processing).
        !           961:  *
        !           962:  * An entity definition has been parsed
        !           963:  */
        !           964: static void
        !           965: entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
        !           966:           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
        !           967: {
        !           968: const xmlChar *nullstr = BAD_CAST "(null)";
        !           969:     /* not all libraries handle printing null pointers nicely */
        !           970:     if (publicId == NULL)
        !           971:         publicId = nullstr;
        !           972:     if (systemId == NULL)
        !           973:         systemId = nullstr;
        !           974:     if (content == NULL)
        !           975:         content = (xmlChar *)nullstr;
        !           976:     callbacks++;
        !           977:     if (quiet)
        !           978:        return;
        !           979:     fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
        !           980:             name, type, publicId, systemId, content);
        !           981: }
        !           982: 
        !           983: /**
        !           984:  * attributeDeclDebug:
        !           985:  * @ctxt:  An XML parser context
        !           986:  * @name:  the attribute name
        !           987:  * @type:  the attribute type
        !           988:  *
        !           989:  * An attribute definition has been parsed
        !           990:  */
        !           991: static void
        !           992: attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
        !           993:                    const xmlChar * name, int type, int def,
        !           994:                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
        !           995: {
        !           996:     callbacks++;
        !           997:     if (quiet)
        !           998:         return;
        !           999:     if (defaultValue == NULL)
        !          1000:         fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
        !          1001:                 elem, name, type, def);
        !          1002:     else
        !          1003:         fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
        !          1004:                 elem, name, type, def, defaultValue);
        !          1005:     xmlFreeEnumeration(tree);
        !          1006: }
        !          1007: 
        !          1008: /**
        !          1009:  * elementDeclDebug:
        !          1010:  * @ctxt:  An XML parser context
        !          1011:  * @name:  the element name
        !          1012:  * @type:  the element type
        !          1013:  * @content: the element value (without processing).
        !          1014:  *
        !          1015:  * An element definition has been parsed
        !          1016:  */
        !          1017: static void
        !          1018: elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
        !          1019:            xmlElementContentPtr content ATTRIBUTE_UNUSED)
        !          1020: {
        !          1021:     callbacks++;
        !          1022:     if (quiet)
        !          1023:        return;
        !          1024:     fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
        !          1025:             name, type);
        !          1026: }
        !          1027: 
        !          1028: /**
        !          1029:  * notationDeclDebug:
        !          1030:  * @ctxt:  An XML parser context
        !          1031:  * @name: The name of the notation
        !          1032:  * @publicId: The public ID of the entity
        !          1033:  * @systemId: The system ID of the entity
        !          1034:  *
        !          1035:  * What to do when a notation declaration has been parsed.
        !          1036:  */
        !          1037: static void
        !          1038: notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
        !          1039:             const xmlChar *publicId, const xmlChar *systemId)
        !          1040: {
        !          1041:     callbacks++;
        !          1042:     if (quiet)
        !          1043:        return;
        !          1044:     fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
        !          1045:             (char *) name, (char *) publicId, (char *) systemId);
        !          1046: }
        !          1047: 
        !          1048: /**
        !          1049:  * unparsedEntityDeclDebug:
        !          1050:  * @ctxt:  An XML parser context
        !          1051:  * @name: The name of the entity
        !          1052:  * @publicId: The public ID of the entity
        !          1053:  * @systemId: The system ID of the entity
        !          1054:  * @notationName: the name of the notation
        !          1055:  *
        !          1056:  * What to do when an unparsed entity declaration is parsed
        !          1057:  */
        !          1058: static void
        !          1059: unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
        !          1060:                   const xmlChar *publicId, const xmlChar *systemId,
        !          1061:                   const xmlChar *notationName)
        !          1062: {
        !          1063: const xmlChar *nullstr = BAD_CAST "(null)";
        !          1064: 
        !          1065:     if (publicId == NULL)
        !          1066:         publicId = nullstr;
        !          1067:     if (systemId == NULL)
        !          1068:         systemId = nullstr;
        !          1069:     if (notationName == NULL)
        !          1070:         notationName = nullstr;
        !          1071:     callbacks++;
        !          1072:     if (quiet)
        !          1073:        return;
        !          1074:     fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
        !          1075:             (char *) name, (char *) publicId, (char *) systemId,
        !          1076:            (char *) notationName);
        !          1077: }
        !          1078: 
        !          1079: /**
        !          1080:  * setDocumentLocatorDebug:
        !          1081:  * @ctxt:  An XML parser context
        !          1082:  * @loc: A SAX Locator
        !          1083:  *
        !          1084:  * Receive the document locator at startup, actually xmlDefaultSAXLocator
        !          1085:  * Everything is available on the context, so this is useless in our case.
        !          1086:  */
        !          1087: static void
        !          1088: setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
        !          1089: {
        !          1090:     callbacks++;
        !          1091:     if (quiet)
        !          1092:        return;
        !          1093:     fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
        !          1094: }
        !          1095: 
        !          1096: /**
        !          1097:  * startDocumentDebug:
        !          1098:  * @ctxt:  An XML parser context
        !          1099:  *
        !          1100:  * called when the document start being processed.
        !          1101:  */
        !          1102: static void
        !          1103: startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
        !          1104: {
        !          1105:     callbacks++;
        !          1106:     if (quiet)
        !          1107:        return;
        !          1108:     fprintf(SAXdebug, "SAX.startDocument()\n");
        !          1109: }
        !          1110: 
        !          1111: /**
        !          1112:  * endDocumentDebug:
        !          1113:  * @ctxt:  An XML parser context
        !          1114:  *
        !          1115:  * called when the document end has been detected.
        !          1116:  */
        !          1117: static void
        !          1118: endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
        !          1119: {
        !          1120:     callbacks++;
        !          1121:     if (quiet)
        !          1122:        return;
        !          1123:     fprintf(SAXdebug, "SAX.endDocument()\n");
        !          1124: }
        !          1125: 
        !          1126: /**
        !          1127:  * startElementDebug:
        !          1128:  * @ctxt:  An XML parser context
        !          1129:  * @name:  The element name
        !          1130:  *
        !          1131:  * called when an opening tag has been processed.
        !          1132:  */
        !          1133: static void
        !          1134: startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
        !          1135: {
        !          1136:     int i;
        !          1137: 
        !          1138:     callbacks++;
        !          1139:     if (quiet)
        !          1140:        return;
        !          1141:     fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
        !          1142:     if (atts != NULL) {
        !          1143:         for (i = 0;(atts[i] != NULL);i++) {
        !          1144:            fprintf(SAXdebug, ", %s='", atts[i++]);
        !          1145:            if (atts[i] != NULL)
        !          1146:                fprintf(SAXdebug, "%s'", atts[i]);
        !          1147:        }
        !          1148:     }
        !          1149:     fprintf(SAXdebug, ")\n");
        !          1150: }
        !          1151: 
        !          1152: /**
        !          1153:  * endElementDebug:
        !          1154:  * @ctxt:  An XML parser context
        !          1155:  * @name:  The element name
        !          1156:  *
        !          1157:  * called when the end of an element has been detected.
        !          1158:  */
        !          1159: static void
        !          1160: endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
        !          1161: {
        !          1162:     callbacks++;
        !          1163:     if (quiet)
        !          1164:        return;
        !          1165:     fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
        !          1166: }
        !          1167: 
        !          1168: /**
        !          1169:  * charactersDebug:
        !          1170:  * @ctxt:  An XML parser context
        !          1171:  * @ch:  a xmlChar string
        !          1172:  * @len: the number of xmlChar
        !          1173:  *
        !          1174:  * receiving some chars from the parser.
        !          1175:  * Question: how much at a time ???
        !          1176:  */
        !          1177: static void
        !          1178: charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
        !          1179: {
        !          1180:     char output[40];
        !          1181:     int i;
        !          1182: 
        !          1183:     callbacks++;
        !          1184:     if (quiet)
        !          1185:        return;
        !          1186:     for (i = 0;(i<len) && (i < 30);i++)
        !          1187:        output[i] = ch[i];
        !          1188:     output[i] = 0;
        !          1189: 
        !          1190:     fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
        !          1191: }
        !          1192: 
        !          1193: /**
        !          1194:  * referenceDebug:
        !          1195:  * @ctxt:  An XML parser context
        !          1196:  * @name:  The entity name
        !          1197:  *
        !          1198:  * called when an entity reference is detected.
        !          1199:  */
        !          1200: static void
        !          1201: referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
        !          1202: {
        !          1203:     callbacks++;
        !          1204:     if (quiet)
        !          1205:        return;
        !          1206:     fprintf(SAXdebug, "SAX.reference(%s)\n", name);
        !          1207: }
        !          1208: 
        !          1209: /**
        !          1210:  * ignorableWhitespaceDebug:
        !          1211:  * @ctxt:  An XML parser context
        !          1212:  * @ch:  a xmlChar string
        !          1213:  * @start: the first char in the string
        !          1214:  * @len: the number of xmlChar
        !          1215:  *
        !          1216:  * receiving some ignorable whitespaces from the parser.
        !          1217:  * Question: how much at a time ???
        !          1218:  */
        !          1219: static void
        !          1220: ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
        !          1221: {
        !          1222:     char output[40];
        !          1223:     int i;
        !          1224: 
        !          1225:     callbacks++;
        !          1226:     if (quiet)
        !          1227:        return;
        !          1228:     for (i = 0;(i<len) && (i < 30);i++)
        !          1229:        output[i] = ch[i];
        !          1230:     output[i] = 0;
        !          1231:     fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
        !          1232: }
        !          1233: 
        !          1234: /**
        !          1235:  * processingInstructionDebug:
        !          1236:  * @ctxt:  An XML parser context
        !          1237:  * @target:  the target name
        !          1238:  * @data: the PI data's
        !          1239:  * @len: the number of xmlChar
        !          1240:  *
        !          1241:  * A processing instruction has been parsed.
        !          1242:  */
        !          1243: static void
        !          1244: processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
        !          1245:                       const xmlChar *data)
        !          1246: {
        !          1247:     callbacks++;
        !          1248:     if (quiet)
        !          1249:        return;
        !          1250:     if (data != NULL)
        !          1251:        fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
        !          1252:                (char *) target, (char *) data);
        !          1253:     else
        !          1254:        fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
        !          1255:                (char *) target);
        !          1256: }
        !          1257: 
        !          1258: /**
        !          1259:  * cdataBlockDebug:
        !          1260:  * @ctx: the user data (XML parser context)
        !          1261:  * @value:  The pcdata content
        !          1262:  * @len:  the block length
        !          1263:  *
        !          1264:  * called when a pcdata block has been parsed
        !          1265:  */
        !          1266: static void
        !          1267: cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
        !          1268: {
        !          1269:     callbacks++;
        !          1270:     if (quiet)
        !          1271:        return;
        !          1272:     fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
        !          1273:            (char *) value, len);
        !          1274: }
        !          1275: 
        !          1276: /**
        !          1277:  * commentDebug:
        !          1278:  * @ctxt:  An XML parser context
        !          1279:  * @value:  the comment content
        !          1280:  *
        !          1281:  * A comment has been parsed.
        !          1282:  */
        !          1283: static void
        !          1284: commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
        !          1285: {
        !          1286:     callbacks++;
        !          1287:     if (quiet)
        !          1288:        return;
        !          1289:     fprintf(SAXdebug, "SAX.comment(%s)\n", value);
        !          1290: }
        !          1291: 
        !          1292: /**
        !          1293:  * warningDebug:
        !          1294:  * @ctxt:  An XML parser context
        !          1295:  * @msg:  the message to display/transmit
        !          1296:  * @...:  extra parameters for the message display
        !          1297:  *
        !          1298:  * Display and format a warning messages, gives file, line, position and
        !          1299:  * extra parameters.
        !          1300:  */
        !          1301: static void XMLCDECL
        !          1302: warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
        !          1303: {
        !          1304:     va_list args;
        !          1305: 
        !          1306:     callbacks++;
        !          1307:     if (quiet)
        !          1308:        return;
        !          1309:     va_start(args, msg);
        !          1310:     fprintf(SAXdebug, "SAX.warning: ");
        !          1311:     vfprintf(SAXdebug, msg, args);
        !          1312:     va_end(args);
        !          1313: }
        !          1314: 
        !          1315: /**
        !          1316:  * errorDebug:
        !          1317:  * @ctxt:  An XML parser context
        !          1318:  * @msg:  the message to display/transmit
        !          1319:  * @...:  extra parameters for the message display
        !          1320:  *
        !          1321:  * Display and format a error messages, gives file, line, position and
        !          1322:  * extra parameters.
        !          1323:  */
        !          1324: static void XMLCDECL
        !          1325: errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
        !          1326: {
        !          1327:     va_list args;
        !          1328: 
        !          1329:     callbacks++;
        !          1330:     if (quiet)
        !          1331:        return;
        !          1332:     va_start(args, msg);
        !          1333:     fprintf(SAXdebug, "SAX.error: ");
        !          1334:     vfprintf(SAXdebug, msg, args);
        !          1335:     va_end(args);
        !          1336: }
        !          1337: 
        !          1338: /**
        !          1339:  * fatalErrorDebug:
        !          1340:  * @ctxt:  An XML parser context
        !          1341:  * @msg:  the message to display/transmit
        !          1342:  * @...:  extra parameters for the message display
        !          1343:  *
        !          1344:  * Display and format a fatalError messages, gives file, line, position and
        !          1345:  * extra parameters.
        !          1346:  */
        !          1347: static void XMLCDECL
        !          1348: fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
        !          1349: {
        !          1350:     va_list args;
        !          1351: 
        !          1352:     callbacks++;
        !          1353:     if (quiet)
        !          1354:        return;
        !          1355:     va_start(args, msg);
        !          1356:     fprintf(SAXdebug, "SAX.fatalError: ");
        !          1357:     vfprintf(SAXdebug, msg, args);
        !          1358:     va_end(args);
        !          1359: }
        !          1360: 
        !          1361: static xmlSAXHandler debugSAXHandlerStruct = {
        !          1362:     internalSubsetDebug,
        !          1363:     isStandaloneDebug,
        !          1364:     hasInternalSubsetDebug,
        !          1365:     hasExternalSubsetDebug,
        !          1366:     resolveEntityDebug,
        !          1367:     getEntityDebug,
        !          1368:     entityDeclDebug,
        !          1369:     notationDeclDebug,
        !          1370:     attributeDeclDebug,
        !          1371:     elementDeclDebug,
        !          1372:     unparsedEntityDeclDebug,
        !          1373:     setDocumentLocatorDebug,
        !          1374:     startDocumentDebug,
        !          1375:     endDocumentDebug,
        !          1376:     startElementDebug,
        !          1377:     endElementDebug,
        !          1378:     referenceDebug,
        !          1379:     charactersDebug,
        !          1380:     ignorableWhitespaceDebug,
        !          1381:     processingInstructionDebug,
        !          1382:     commentDebug,
        !          1383:     warningDebug,
        !          1384:     errorDebug,
        !          1385:     fatalErrorDebug,
        !          1386:     getParameterEntityDebug,
        !          1387:     cdataBlockDebug,
        !          1388:     externalSubsetDebug,
        !          1389:     1,
        !          1390:     NULL,
        !          1391:     NULL,
        !          1392:     NULL,
        !          1393:     NULL
        !          1394: };
        !          1395: 
        !          1396: static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
        !          1397: 
        !          1398: /*
        !          1399:  * SAX2 specific callbacks
        !          1400:  */
        !          1401: /**
        !          1402:  * startElementNsDebug:
        !          1403:  * @ctxt:  An XML parser context
        !          1404:  * @name:  The element name
        !          1405:  *
        !          1406:  * called when an opening tag has been processed.
        !          1407:  */
        !          1408: static void
        !          1409: startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
        !          1410:                     const xmlChar *localname,
        !          1411:                     const xmlChar *prefix,
        !          1412:                     const xmlChar *URI,
        !          1413:                    int nb_namespaces,
        !          1414:                    const xmlChar **namespaces,
        !          1415:                    int nb_attributes,
        !          1416:                    int nb_defaulted,
        !          1417:                    const xmlChar **attributes)
        !          1418: {
        !          1419:     int i;
        !          1420: 
        !          1421:     callbacks++;
        !          1422:     if (quiet)
        !          1423:        return;
        !          1424:     fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
        !          1425:     if (prefix == NULL)
        !          1426:        fprintf(SAXdebug, ", NULL");
        !          1427:     else
        !          1428:        fprintf(SAXdebug, ", %s", (char *) prefix);
        !          1429:     if (URI == NULL)
        !          1430:        fprintf(SAXdebug, ", NULL");
        !          1431:     else
        !          1432:        fprintf(SAXdebug, ", '%s'", (char *) URI);
        !          1433:     fprintf(SAXdebug, ", %d", nb_namespaces);
        !          1434: 
        !          1435:     if (namespaces != NULL) {
        !          1436:         for (i = 0;i < nb_namespaces * 2;i++) {
        !          1437:            fprintf(SAXdebug, ", xmlns");
        !          1438:            if (namespaces[i] != NULL)
        !          1439:                fprintf(SAXdebug, ":%s", namespaces[i]);
        !          1440:            i++;
        !          1441:            fprintf(SAXdebug, "='%s'", namespaces[i]);
        !          1442:        }
        !          1443:     }
        !          1444:     fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
        !          1445:     if (attributes != NULL) {
        !          1446:         for (i = 0;i < nb_attributes * 5;i += 5) {
        !          1447:            if (attributes[i + 1] != NULL)
        !          1448:                fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
        !          1449:            else
        !          1450:                fprintf(SAXdebug, ", %s='", attributes[i]);
        !          1451:            fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
        !          1452:                    (int)(attributes[i + 4] - attributes[i + 3]));
        !          1453:        }
        !          1454:     }
        !          1455:     fprintf(SAXdebug, ")\n");
        !          1456: }
        !          1457: 
        !          1458: /**
        !          1459:  * endElementDebug:
        !          1460:  * @ctxt:  An XML parser context
        !          1461:  * @name:  The element name
        !          1462:  *
        !          1463:  * called when the end of an element has been detected.
        !          1464:  */
        !          1465: static void
        !          1466: endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
        !          1467:                   const xmlChar *localname,
        !          1468:                   const xmlChar *prefix,
        !          1469:                   const xmlChar *URI)
        !          1470: {
        !          1471:     callbacks++;
        !          1472:     if (quiet)
        !          1473:        return;
        !          1474:     fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
        !          1475:     if (prefix == NULL)
        !          1476:        fprintf(SAXdebug, ", NULL");
        !          1477:     else
        !          1478:        fprintf(SAXdebug, ", %s", (char *) prefix);
        !          1479:     if (URI == NULL)
        !          1480:        fprintf(SAXdebug, ", NULL)\n");
        !          1481:     else
        !          1482:        fprintf(SAXdebug, ", '%s')\n", (char *) URI);
        !          1483: }
        !          1484: 
        !          1485: static xmlSAXHandler debugSAX2HandlerStruct = {
        !          1486:     internalSubsetDebug,
        !          1487:     isStandaloneDebug,
        !          1488:     hasInternalSubsetDebug,
        !          1489:     hasExternalSubsetDebug,
        !          1490:     resolveEntityDebug,
        !          1491:     getEntityDebug,
        !          1492:     entityDeclDebug,
        !          1493:     notationDeclDebug,
        !          1494:     attributeDeclDebug,
        !          1495:     elementDeclDebug,
        !          1496:     unparsedEntityDeclDebug,
        !          1497:     setDocumentLocatorDebug,
        !          1498:     startDocumentDebug,
        !          1499:     endDocumentDebug,
        !          1500:     NULL,
        !          1501:     NULL,
        !          1502:     referenceDebug,
        !          1503:     charactersDebug,
        !          1504:     ignorableWhitespaceDebug,
        !          1505:     processingInstructionDebug,
        !          1506:     commentDebug,
        !          1507:     warningDebug,
        !          1508:     errorDebug,
        !          1509:     fatalErrorDebug,
        !          1510:     getParameterEntityDebug,
        !          1511:     cdataBlockDebug,
        !          1512:     externalSubsetDebug,
        !          1513:     XML_SAX2_MAGIC,
        !          1514:     NULL,
        !          1515:     startElementNsDebug,
        !          1516:     endElementNsDebug,
        !          1517:     NULL
        !          1518: };
        !          1519: 
        !          1520: static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
        !          1521: 
        !          1522: #ifdef LIBXML_HTML_ENABLED
        !          1523: /**
        !          1524:  * htmlstartElementDebug:
        !          1525:  * @ctxt:  An XML parser context
        !          1526:  * @name:  The element name
        !          1527:  *
        !          1528:  * called when an opening tag has been processed.
        !          1529:  */
        !          1530: static void
        !          1531: htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
        !          1532: {
        !          1533:     int i;
        !          1534: 
        !          1535:     fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
        !          1536:     if (atts != NULL) {
        !          1537:         for (i = 0;(atts[i] != NULL);i++) {
        !          1538:            fprintf(SAXdebug, ", %s", atts[i++]);
        !          1539:            if (atts[i] != NULL) {
        !          1540:                unsigned char output[40];
        !          1541:                const unsigned char *att = atts[i];
        !          1542:                int outlen, attlen;
        !          1543:                fprintf(SAXdebug, "='");
        !          1544:                while ((attlen = strlen((char*)att)) > 0) {
        !          1545:                    outlen = sizeof output - 1;
        !          1546:                    htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
        !          1547:                    output[outlen] = 0;
        !          1548:                    fprintf(SAXdebug, "%s", (char *) output);
        !          1549:                    att += attlen;
        !          1550:                }
        !          1551:                fprintf(SAXdebug, "'");
        !          1552:            }
        !          1553:        }
        !          1554:     }
        !          1555:     fprintf(SAXdebug, ")\n");
        !          1556: }
        !          1557: 
        !          1558: /**
        !          1559:  * htmlcharactersDebug:
        !          1560:  * @ctxt:  An XML parser context
        !          1561:  * @ch:  a xmlChar string
        !          1562:  * @len: the number of xmlChar
        !          1563:  *
        !          1564:  * receiving some chars from the parser.
        !          1565:  * Question: how much at a time ???
        !          1566:  */
        !          1567: static void
        !          1568: htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
        !          1569: {
        !          1570:     unsigned char output[40];
        !          1571:     int inlen = len, outlen = 30;
        !          1572: 
        !          1573:     htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
        !          1574:     output[outlen] = 0;
        !          1575: 
        !          1576:     fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
        !          1577: }
        !          1578: 
        !          1579: /**
        !          1580:  * htmlcdataDebug:
        !          1581:  * @ctxt:  An XML parser context
        !          1582:  * @ch:  a xmlChar string
        !          1583:  * @len: the number of xmlChar
        !          1584:  *
        !          1585:  * receiving some cdata chars from the parser.
        !          1586:  * Question: how much at a time ???
        !          1587:  */
        !          1588: static void
        !          1589: htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
        !          1590: {
        !          1591:     unsigned char output[40];
        !          1592:     int inlen = len, outlen = 30;
        !          1593: 
        !          1594:     htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
        !          1595:     output[outlen] = 0;
        !          1596: 
        !          1597:     fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
        !          1598: }
        !          1599: 
        !          1600: static xmlSAXHandler debugHTMLSAXHandlerStruct = {
        !          1601:     internalSubsetDebug,
        !          1602:     isStandaloneDebug,
        !          1603:     hasInternalSubsetDebug,
        !          1604:     hasExternalSubsetDebug,
        !          1605:     resolveEntityDebug,
        !          1606:     getEntityDebug,
        !          1607:     entityDeclDebug,
        !          1608:     notationDeclDebug,
        !          1609:     attributeDeclDebug,
        !          1610:     elementDeclDebug,
        !          1611:     unparsedEntityDeclDebug,
        !          1612:     setDocumentLocatorDebug,
        !          1613:     startDocumentDebug,
        !          1614:     endDocumentDebug,
        !          1615:     htmlstartElementDebug,
        !          1616:     endElementDebug,
        !          1617:     referenceDebug,
        !          1618:     htmlcharactersDebug,
        !          1619:     ignorableWhitespaceDebug,
        !          1620:     processingInstructionDebug,
        !          1621:     commentDebug,
        !          1622:     warningDebug,
        !          1623:     errorDebug,
        !          1624:     fatalErrorDebug,
        !          1625:     getParameterEntityDebug,
        !          1626:     htmlcdataDebug,
        !          1627:     externalSubsetDebug,
        !          1628:     1,
        !          1629:     NULL,
        !          1630:     NULL,
        !          1631:     NULL,
        !          1632:     NULL
        !          1633: };
        !          1634: 
        !          1635: static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
        !          1636: #endif /* LIBXML_HTML_ENABLED */
        !          1637: 
        !          1638: #ifdef LIBXML_SAX1_ENABLED
        !          1639: /**
        !          1640:  * saxParseTest:
        !          1641:  * @filename: the file to parse
        !          1642:  * @result: the file with expected result
        !          1643:  * @err: the file with error messages
        !          1644:  *
        !          1645:  * Parse a file using the SAX API and check for errors.
        !          1646:  *
        !          1647:  * Returns 0 in case of success, an error code otherwise
        !          1648:  */
        !          1649: static int
        !          1650: saxParseTest(const char *filename, const char *result,
        !          1651:              const char *err ATTRIBUTE_UNUSED,
        !          1652:              int options) {
        !          1653:     int ret;
        !          1654:     char *temp;
        !          1655: 
        !          1656:     nb_tests++;
        !          1657:     temp = resultFilename(filename, "", ".res");
        !          1658:     if (temp == NULL) {
        !          1659:         fprintf(stderr, "out of memory\n");
        !          1660:         fatalError();
        !          1661:     }
        !          1662:     SAXdebug = fopen(temp, "wb");
        !          1663:     if (SAXdebug == NULL) {
        !          1664:         fprintf(stderr, "Failed to write to %s\n", temp);
        !          1665:        free(temp);
        !          1666:        return(-1);
        !          1667:     }
        !          1668: 
        !          1669:     /* for SAX we really want the callbacks though the context handlers */
        !          1670:     xmlSetStructuredErrorFunc(NULL, NULL);
        !          1671:     xmlSetGenericErrorFunc(NULL, testErrorHandler);
        !          1672: 
        !          1673: #ifdef LIBXML_HTML_ENABLED
        !          1674:     if (options & XML_PARSE_HTML) {
        !          1675:        htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
        !          1676:        ret = 0;
        !          1677:     } else
        !          1678: #endif
        !          1679:     ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
        !          1680:     if (ret == XML_WAR_UNDECLARED_ENTITY) {
        !          1681:         fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
        !          1682:         ret = 0;
        !          1683:     }
        !          1684:     if (ret != 0) {
        !          1685:         fprintf(stderr, "Failed to parse %s\n", filename);
        !          1686:        return(1);
        !          1687:     }
        !          1688: #ifdef LIBXML_HTML_ENABLED
        !          1689:     if (options & XML_PARSE_HTML) {
        !          1690:        htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
        !          1691:        ret = 0;
        !          1692:     } else
        !          1693: #endif
        !          1694:     if (options & XML_PARSE_SAX1) {
        !          1695:        ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
        !          1696:     } else {
        !          1697:        ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
        !          1698:     }
        !          1699:     if (ret == XML_WAR_UNDECLARED_ENTITY) {
        !          1700:         fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
        !          1701:         ret = 0;
        !          1702:     }
        !          1703:     fclose(SAXdebug);
        !          1704:     if (compareFiles(temp, result)) {
        !          1705:         fprintf(stderr, "Got a difference for %s\n", filename);
        !          1706:         ret = 1;
        !          1707:     }
        !          1708:     if (temp != NULL) {
        !          1709:         unlink(temp);
        !          1710:         free(temp);
        !          1711:     }
        !          1712: 
        !          1713:     /* switch back to structured error handling */
        !          1714:     xmlSetGenericErrorFunc(NULL, NULL);
        !          1715:     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
        !          1716: 
        !          1717:     return(ret);
        !          1718: }
        !          1719: #endif
        !          1720: 
        !          1721: /************************************************************************
        !          1722:  *                                                                     *
        !          1723:  *             Parse to tree based tests                               *
        !          1724:  *                                                                     *
        !          1725:  ************************************************************************/
        !          1726: /**
        !          1727:  * oldParseTest:
        !          1728:  * @filename: the file to parse
        !          1729:  * @result: the file with expected result
        !          1730:  * @err: the file with error messages: unused
        !          1731:  *
        !          1732:  * Parse a file using the old xmlParseFile API, then serialize back
        !          1733:  * reparse the result and serialize again, then check for deviation
        !          1734:  * in serialization.
        !          1735:  *
        !          1736:  * Returns 0 in case of success, an error code otherwise
        !          1737:  */
        !          1738: static int
        !          1739: oldParseTest(const char *filename, const char *result,
        !          1740:              const char *err ATTRIBUTE_UNUSED,
        !          1741:             int options ATTRIBUTE_UNUSED) {
        !          1742:     xmlDocPtr doc;
        !          1743:     char *temp;
        !          1744:     int res = 0;
        !          1745: 
        !          1746:     nb_tests++;
        !          1747:     /*
        !          1748:      * base of the test, parse with the old API
        !          1749:      */
        !          1750: #ifdef LIBXML_SAX1_ENABLED
        !          1751:     doc = xmlParseFile(filename);
        !          1752: #else
        !          1753:     doc = xmlReadFile(filename, NULL, 0);
        !          1754: #endif
        !          1755:     if (doc == NULL)
        !          1756:         return(1);
        !          1757:     temp = resultFilename(filename, "", ".res");
        !          1758:     if (temp == NULL) {
        !          1759:         fprintf(stderr, "out of memory\n");
        !          1760:         fatalError();
        !          1761:     }
        !          1762:     xmlSaveFile(temp, doc);
        !          1763:     if (compareFiles(temp, result)) {
        !          1764:         res = 1;
        !          1765:     }
        !          1766:     xmlFreeDoc(doc);
        !          1767: 
        !          1768:     /*
        !          1769:      * Parse the saved result to make sure the round trip is okay
        !          1770:      */
        !          1771: #ifdef LIBXML_SAX1_ENABLED
        !          1772:     doc = xmlParseFile(temp);
        !          1773: #else
        !          1774:     doc = xmlReadFile(temp, NULL, 0);
        !          1775: #endif
        !          1776:     if (doc == NULL)
        !          1777:         return(1);
        !          1778:     xmlSaveFile(temp, doc);
        !          1779:     if (compareFiles(temp, result)) {
        !          1780:         res = 1;
        !          1781:     }
        !          1782:     xmlFreeDoc(doc);
        !          1783: 
        !          1784:     if (temp != NULL) {
        !          1785:         unlink(temp);
        !          1786:         free(temp);
        !          1787:     }
        !          1788:     return(res);
        !          1789: }
        !          1790: 
        !          1791: #ifdef LIBXML_PUSH_ENABLED
        !          1792: /**
        !          1793:  * pushParseTest:
        !          1794:  * @filename: the file to parse
        !          1795:  * @result: the file with expected result
        !          1796:  * @err: the file with error messages: unused
        !          1797:  *
        !          1798:  * Parse a file using the Push API, then serialize back
        !          1799:  * to check for content.
        !          1800:  *
        !          1801:  * Returns 0 in case of success, an error code otherwise
        !          1802:  */
        !          1803: static int
        !          1804: pushParseTest(const char *filename, const char *result,
        !          1805:              const char *err ATTRIBUTE_UNUSED,
        !          1806:             int options) {
        !          1807:     xmlParserCtxtPtr ctxt;
        !          1808:     xmlDocPtr doc;
        !          1809:     const char *base;
        !          1810:     int size, res;
        !          1811:     int cur = 0;
        !          1812: 
        !          1813:     nb_tests++;
        !          1814:     /*
        !          1815:      * load the document in memory and work from there.
        !          1816:      */
        !          1817:     if (loadMem(filename, &base, &size) != 0) {
        !          1818:         fprintf(stderr, "Failed to load %s\n", filename);
        !          1819:        return(-1);
        !          1820:     }
        !          1821: 
        !          1822: #ifdef LIBXML_HTML_ENABLED
        !          1823:     if (options & XML_PARSE_HTML)
        !          1824:        ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
        !          1825:                                        XML_CHAR_ENCODING_NONE);
        !          1826:     else
        !          1827: #endif
        !          1828:     ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
        !          1829:     xmlCtxtUseOptions(ctxt, options);
        !          1830:     cur += 4;
        !          1831:     while (cur < size) {
        !          1832:         if (cur + 1024 >= size) {
        !          1833: #ifdef LIBXML_HTML_ENABLED
        !          1834:            if (options & XML_PARSE_HTML)
        !          1835:                htmlParseChunk(ctxt, base + cur, size - cur, 1);
        !          1836:            else
        !          1837: #endif
        !          1838:            xmlParseChunk(ctxt, base + cur, size - cur, 1);
        !          1839:            break;
        !          1840:        } else {
        !          1841: #ifdef LIBXML_HTML_ENABLED
        !          1842:            if (options & XML_PARSE_HTML)
        !          1843:                htmlParseChunk(ctxt, base + cur, 1024, 0);
        !          1844:            else
        !          1845: #endif
        !          1846:            xmlParseChunk(ctxt, base + cur, 1024, 0);
        !          1847:            cur += 1024;
        !          1848:        }
        !          1849:     }
        !          1850:     doc = ctxt->myDoc;
        !          1851: #ifdef LIBXML_HTML_ENABLED
        !          1852:     if (options & XML_PARSE_HTML)
        !          1853:         res = 1;
        !          1854:     else
        !          1855: #endif
        !          1856:     res = ctxt->wellFormed;
        !          1857:     xmlFreeParserCtxt(ctxt);
        !          1858:     free((char *)base);
        !          1859:     if (!res) {
        !          1860:        xmlFreeDoc(doc);
        !          1861:        fprintf(stderr, "Failed to parse %s\n", filename);
        !          1862:        return(-1);
        !          1863:     }
        !          1864: #ifdef LIBXML_HTML_ENABLED
        !          1865:     if (options & XML_PARSE_HTML)
        !          1866:        htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
        !          1867:     else
        !          1868: #endif
        !          1869:     xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
        !          1870:     xmlFreeDoc(doc);
        !          1871:     res = compareFileMem(result, base, size);
        !          1872:     if ((base == NULL) || (res != 0)) {
        !          1873:        if (base != NULL)
        !          1874:            xmlFree((char *)base);
        !          1875:         fprintf(stderr, "Result for %s failed\n", filename);
        !          1876:        return(-1);
        !          1877:     }
        !          1878:     xmlFree((char *)base);
        !          1879:     if (err != NULL) {
        !          1880:        res = compareFileMem(err, testErrors, testErrorsSize);
        !          1881:        if (res != 0) {
        !          1882:            fprintf(stderr, "Error for %s failed\n", filename);
        !          1883:            return(-1);
        !          1884:        }
        !          1885:     }
        !          1886:     return(0);
        !          1887: }
        !          1888: #endif
        !          1889: 
        !          1890: /**
        !          1891:  * memParseTest:
        !          1892:  * @filename: the file to parse
        !          1893:  * @result: the file with expected result
        !          1894:  * @err: the file with error messages: unused
        !          1895:  *
        !          1896:  * Parse a file using the old xmlReadMemory API, then serialize back
        !          1897:  * reparse the result and serialize again, then check for deviation
        !          1898:  * in serialization.
        !          1899:  *
        !          1900:  * Returns 0 in case of success, an error code otherwise
        !          1901:  */
        !          1902: static int
        !          1903: memParseTest(const char *filename, const char *result,
        !          1904:              const char *err ATTRIBUTE_UNUSED,
        !          1905:             int options ATTRIBUTE_UNUSED) {
        !          1906:     xmlDocPtr doc;
        !          1907:     const char *base;
        !          1908:     int size, res;
        !          1909: 
        !          1910:     nb_tests++;
        !          1911:     /*
        !          1912:      * load and parse the memory
        !          1913:      */
        !          1914:     if (loadMem(filename, &base, &size) != 0) {
        !          1915:         fprintf(stderr, "Failed to load %s\n", filename);
        !          1916:        return(-1);
        !          1917:     }
        !          1918: 
        !          1919:     doc = xmlReadMemory(base, size, filename, NULL, 0);
        !          1920:     unloadMem(base);
        !          1921:     if (doc == NULL) {
        !          1922:         return(1);
        !          1923:     }
        !          1924:     xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
        !          1925:     xmlFreeDoc(doc);
        !          1926:     res = compareFileMem(result, base, size);
        !          1927:     if ((base == NULL) || (res != 0)) {
        !          1928:        if (base != NULL)
        !          1929:            xmlFree((char *)base);
        !          1930:         fprintf(stderr, "Result for %s failed\n", filename);
        !          1931:        return(-1);
        !          1932:     }
        !          1933:     xmlFree((char *)base);
        !          1934:     return(0);
        !          1935: }
        !          1936: 
        !          1937: /**
        !          1938:  * noentParseTest:
        !          1939:  * @filename: the file to parse
        !          1940:  * @result: the file with expected result
        !          1941:  * @err: the file with error messages: unused
        !          1942:  *
        !          1943:  * Parse a file with entity resolution, then serialize back
        !          1944:  * reparse the result and serialize again, then check for deviation
        !          1945:  * in serialization.
        !          1946:  *
        !          1947:  * Returns 0 in case of success, an error code otherwise
        !          1948:  */
        !          1949: static int
        !          1950: noentParseTest(const char *filename, const char *result,
        !          1951:                const char *err  ATTRIBUTE_UNUSED,
        !          1952:               int options) {
        !          1953:     xmlDocPtr doc;
        !          1954:     char *temp;
        !          1955:     int res = 0;
        !          1956: 
        !          1957:     nb_tests++;
        !          1958:     /*
        !          1959:      * base of the test, parse with the old API
        !          1960:      */
        !          1961:     doc = xmlReadFile(filename, NULL, options);
        !          1962:     if (doc == NULL)
        !          1963:         return(1);
        !          1964:     temp = resultFilename(filename, "", ".res");
        !          1965:     if (temp == NULL) {
        !          1966:         fprintf(stderr, "Out of memory\n");
        !          1967:         fatalError();
        !          1968:     }
        !          1969:     xmlSaveFile(temp, doc);
        !          1970:     if (compareFiles(temp, result)) {
        !          1971:         res = 1;
        !          1972:     }
        !          1973:     xmlFreeDoc(doc);
        !          1974: 
        !          1975:     /*
        !          1976:      * Parse the saved result to make sure the round trip is okay
        !          1977:      */
        !          1978:     doc = xmlReadFile(filename, NULL, options);
        !          1979:     if (doc == NULL)
        !          1980:         return(1);
        !          1981:     xmlSaveFile(temp, doc);
        !          1982:     if (compareFiles(temp, result)) {
        !          1983:         res = 1;
        !          1984:     }
        !          1985:     xmlFreeDoc(doc);
        !          1986: 
        !          1987:     if (temp != NULL) {
        !          1988:         unlink(temp);
        !          1989:         free(temp);
        !          1990:     }
        !          1991:     return(res);
        !          1992: }
        !          1993: 
        !          1994: /**
        !          1995:  * errParseTest:
        !          1996:  * @filename: the file to parse
        !          1997:  * @result: the file with expected result
        !          1998:  * @err: the file with error messages
        !          1999:  *
        !          2000:  * Parse a file using the xmlReadFile API and check for errors.
        !          2001:  *
        !          2002:  * Returns 0 in case of success, an error code otherwise
        !          2003:  */
        !          2004: static int
        !          2005: errParseTest(const char *filename, const char *result, const char *err,
        !          2006:              int options) {
        !          2007:     xmlDocPtr doc;
        !          2008:     const char *base = NULL;
        !          2009:     int size, res = 0;
        !          2010: 
        !          2011:     nb_tests++;
        !          2012: #ifdef LIBXML_HTML_ENABLED
        !          2013:     if (options & XML_PARSE_HTML) {
        !          2014:         doc = htmlReadFile(filename, NULL, options);
        !          2015:     } else
        !          2016: #endif
        !          2017: #ifdef LIBXML_XINCLUDE_ENABLED
        !          2018:     if (options & XML_PARSE_XINCLUDE) {
        !          2019:        doc = xmlReadFile(filename, NULL, options);
        !          2020:        xmlXIncludeProcessFlags(doc, options);
        !          2021:     } else
        !          2022: #endif
        !          2023:     {
        !          2024:        xmlGetWarningsDefaultValue = 1;
        !          2025:        doc = xmlReadFile(filename, NULL, options);
        !          2026:     }
        !          2027:     xmlGetWarningsDefaultValue = 0;
        !          2028:     if (result) {
        !          2029:        if (doc == NULL) {
        !          2030:            base = "";
        !          2031:            size = 0;
        !          2032:        } else {
        !          2033: #ifdef LIBXML_HTML_ENABLED
        !          2034:            if (options & XML_PARSE_HTML) {
        !          2035:                htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
        !          2036:            } else
        !          2037: #endif
        !          2038:            xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
        !          2039:        }
        !          2040:        res = compareFileMem(result, base, size);
        !          2041:     }
        !          2042:     if (doc != NULL) {
        !          2043:        if (base != NULL)
        !          2044:            xmlFree((char *)base);
        !          2045:        xmlFreeDoc(doc);
        !          2046:     }
        !          2047:     if (res != 0) {
        !          2048:         fprintf(stderr, "Result for %s failed\n", filename);
        !          2049:        return(-1);
        !          2050:     }
        !          2051:     if (err != NULL) {
        !          2052:        res = compareFileMem(err, testErrors, testErrorsSize);
        !          2053:        if (res != 0) {
        !          2054:            fprintf(stderr, "Error for %s failed\n", filename);
        !          2055:            return(-1);
        !          2056:        }
        !          2057:     } else if (options & XML_PARSE_DTDVALID) {
        !          2058:         if (testErrorsSize != 0)
        !          2059:            fprintf(stderr, "Validation for %s failed\n", filename);
        !          2060:     }
        !          2061: 
        !          2062:     return(0);
        !          2063: }
        !          2064: 
        !          2065: #ifdef LIBXML_READER_ENABLED
        !          2066: /************************************************************************
        !          2067:  *                                                                     *
        !          2068:  *             Reader based tests                                      *
        !          2069:  *                                                                     *
        !          2070:  ************************************************************************/
        !          2071: 
        !          2072: static void processNode(FILE *out, xmlTextReaderPtr reader) {
        !          2073:     const xmlChar *name, *value;
        !          2074:     int type, empty;
        !          2075: 
        !          2076:     type = xmlTextReaderNodeType(reader);
        !          2077:     empty = xmlTextReaderIsEmptyElement(reader);
        !          2078: 
        !          2079:     name = xmlTextReaderConstName(reader);
        !          2080:     if (name == NULL)
        !          2081:        name = BAD_CAST "--";
        !          2082: 
        !          2083:     value = xmlTextReaderConstValue(reader);
        !          2084: 
        !          2085: 
        !          2086:     fprintf(out, "%d %d %s %d %d",
        !          2087:            xmlTextReaderDepth(reader),
        !          2088:            type,
        !          2089:            name,
        !          2090:            empty,
        !          2091:            xmlTextReaderHasValue(reader));
        !          2092:     if (value == NULL)
        !          2093:        fprintf(out, "\n");
        !          2094:     else {
        !          2095:        fprintf(out, " %s\n", value);
        !          2096:     }
        !          2097: }
        !          2098: static int
        !          2099: streamProcessTest(const char *filename, const char *result, const char *err,
        !          2100:                   xmlTextReaderPtr reader, const char *rng) {
        !          2101:     int ret;
        !          2102:     char *temp = NULL;
        !          2103:     FILE *t = NULL;
        !          2104: 
        !          2105:     if (reader == NULL)
        !          2106:         return(-1);
        !          2107: 
        !          2108:     nb_tests++;
        !          2109:     if (result != NULL) {
        !          2110:        temp = resultFilename(filename, "", ".res");
        !          2111:        if (temp == NULL) {
        !          2112:            fprintf(stderr, "Out of memory\n");
        !          2113:            fatalError();
        !          2114:        }
        !          2115:        t = fopen(temp, "wb");
        !          2116:        if (t == NULL) {
        !          2117:            fprintf(stderr, "Can't open temp file %s\n", temp);
        !          2118:            free(temp);
        !          2119:            return(-1);
        !          2120:        }
        !          2121:     }
        !          2122: #ifdef LIBXML_SCHEMAS_ENABLED
        !          2123:     if (rng != NULL) {
        !          2124:        ret = xmlTextReaderRelaxNGValidate(reader, rng);
        !          2125:        if (ret < 0) {
        !          2126:            testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
        !          2127:                             rng);
        !          2128:            fclose(t);
        !          2129:             if (temp != NULL) {
        !          2130:                 unlink(temp);
        !          2131:                 free(temp);
        !          2132:             }
        !          2133:            return(0);
        !          2134:        }
        !          2135:     }
        !          2136: #endif
        !          2137:     xmlGetWarningsDefaultValue = 1;
        !          2138:     ret = xmlTextReaderRead(reader);
        !          2139:     while (ret == 1) {
        !          2140:        if ((t != NULL) && (rng == NULL))
        !          2141:            processNode(t, reader);
        !          2142:         ret = xmlTextReaderRead(reader);
        !          2143:     }
        !          2144:     if (ret != 0) {
        !          2145:         testErrorHandler(NULL, "%s : failed to parse\n", filename);
        !          2146:     }
        !          2147:     if (rng != NULL) {
        !          2148:         if (xmlTextReaderIsValid(reader) != 1) {
        !          2149:            testErrorHandler(NULL, "%s fails to validate\n", filename);
        !          2150:        } else {
        !          2151:            testErrorHandler(NULL, "%s validates\n", filename);
        !          2152:        }
        !          2153:     }
        !          2154:     xmlGetWarningsDefaultValue = 0;
        !          2155:     if (t != NULL) {
        !          2156:         fclose(t);
        !          2157:        ret = compareFiles(temp, result);
        !          2158:         if (temp != NULL) {
        !          2159:             unlink(temp);
        !          2160:             free(temp);
        !          2161:         }
        !          2162:        if (ret) {
        !          2163:            fprintf(stderr, "Result for %s failed\n", filename);
        !          2164:            return(-1);
        !          2165:        }
        !          2166:     }
        !          2167:     if (err != NULL) {
        !          2168:        ret = compareFileMem(err, testErrors, testErrorsSize);
        !          2169:        if (ret != 0) {
        !          2170:            fprintf(stderr, "Error for %s failed\n", filename);
        !          2171:            printf("%s", testErrors);
        !          2172:            return(-1);
        !          2173:        }
        !          2174:     }
        !          2175: 
        !          2176:     return(0);
        !          2177: }
        !          2178: 
        !          2179: /**
        !          2180:  * streamParseTest:
        !          2181:  * @filename: the file to parse
        !          2182:  * @result: the file with expected result
        !          2183:  * @err: the file with error messages
        !          2184:  *
        !          2185:  * Parse a file using the reader API and check for errors.
        !          2186:  *
        !          2187:  * Returns 0 in case of success, an error code otherwise
        !          2188:  */
        !          2189: static int
        !          2190: streamParseTest(const char *filename, const char *result, const char *err,
        !          2191:                 int options) {
        !          2192:     xmlTextReaderPtr reader;
        !          2193:     int ret;
        !          2194: 
        !          2195:     reader = xmlReaderForFile(filename, NULL, options);
        !          2196:     ret = streamProcessTest(filename, result, err, reader, NULL);
        !          2197:     xmlFreeTextReader(reader);
        !          2198:     return(ret);
        !          2199: }
        !          2200: 
        !          2201: /**
        !          2202:  * walkerParseTest:
        !          2203:  * @filename: the file to parse
        !          2204:  * @result: the file with expected result
        !          2205:  * @err: the file with error messages
        !          2206:  *
        !          2207:  * Parse a file using the walker, i.e. a reader built from a atree.
        !          2208:  *
        !          2209:  * Returns 0 in case of success, an error code otherwise
        !          2210:  */
        !          2211: static int
        !          2212: walkerParseTest(const char *filename, const char *result, const char *err,
        !          2213:                 int options) {
        !          2214:     xmlDocPtr doc;
        !          2215:     xmlTextReaderPtr reader;
        !          2216:     int ret;
        !          2217: 
        !          2218:     doc = xmlReadFile(filename, NULL, options);
        !          2219:     if (doc == NULL) {
        !          2220:         fprintf(stderr, "Failed to parse %s\n", filename);
        !          2221:        return(-1);
        !          2222:     }
        !          2223:     reader = xmlReaderWalker(doc);
        !          2224:     ret = streamProcessTest(filename, result, err, reader, NULL);
        !          2225:     xmlFreeTextReader(reader);
        !          2226:     xmlFreeDoc(doc);
        !          2227:     return(ret);
        !          2228: }
        !          2229: 
        !          2230: /**
        !          2231:  * streamMemParseTest:
        !          2232:  * @filename: the file to parse
        !          2233:  * @result: the file with expected result
        !          2234:  * @err: the file with error messages
        !          2235:  *
        !          2236:  * Parse a file using the reader API from memory and check for errors.
        !          2237:  *
        !          2238:  * Returns 0 in case of success, an error code otherwise
        !          2239:  */
        !          2240: static int
        !          2241: streamMemParseTest(const char *filename, const char *result, const char *err,
        !          2242:                    int options) {
        !          2243:     xmlTextReaderPtr reader;
        !          2244:     int ret;
        !          2245:     const char *base;
        !          2246:     int size;
        !          2247: 
        !          2248:     /*
        !          2249:      * load and parse the memory
        !          2250:      */
        !          2251:     if (loadMem(filename, &base, &size) != 0) {
        !          2252:         fprintf(stderr, "Failed to load %s\n", filename);
        !          2253:        return(-1);
        !          2254:     }
        !          2255:     reader = xmlReaderForMemory(base, size, filename, NULL, options);
        !          2256:     ret = streamProcessTest(filename, result, err, reader, NULL);
        !          2257:     free((char *)base);
        !          2258:     xmlFreeTextReader(reader);
        !          2259:     return(ret);
        !          2260: }
        !          2261: #endif
        !          2262: 
        !          2263: #ifdef LIBXML_XPATH_ENABLED
        !          2264: #ifdef LIBXML_DEBUG_ENABLED
        !          2265: /************************************************************************
        !          2266:  *                                                                     *
        !          2267:  *             XPath and XPointer based tests                          *
        !          2268:  *                                                                     *
        !          2269:  ************************************************************************/
        !          2270: 
        !          2271: static FILE *xpathOutput;
        !          2272: static xmlDocPtr xpathDocument;
        !          2273: 
        !          2274: static void
        !          2275: testXPath(const char *str, int xptr, int expr) {
        !          2276:     xmlXPathObjectPtr res;
        !          2277:     xmlXPathContextPtr ctxt;
        !          2278: 
        !          2279:     nb_tests++;
        !          2280: #if defined(LIBXML_XPTR_ENABLED)
        !          2281:     if (xptr) {
        !          2282:        ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
        !          2283:        res = xmlXPtrEval(BAD_CAST str, ctxt);
        !          2284:     } else {
        !          2285: #endif
        !          2286:        ctxt = xmlXPathNewContext(xpathDocument);
        !          2287:        ctxt->node = xmlDocGetRootElement(xpathDocument);
        !          2288:        if (expr)
        !          2289:            res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
        !          2290:        else {
        !          2291:            /* res = xmlXPathEval(BAD_CAST str, ctxt); */
        !          2292:            xmlXPathCompExprPtr comp;
        !          2293: 
        !          2294:            comp = xmlXPathCompile(BAD_CAST str);
        !          2295:            if (comp != NULL) {
        !          2296:                res = xmlXPathCompiledEval(comp, ctxt);
        !          2297:                xmlXPathFreeCompExpr(comp);
        !          2298:            } else
        !          2299:                res = NULL;
        !          2300:        }
        !          2301: #if defined(LIBXML_XPTR_ENABLED)
        !          2302:     }
        !          2303: #endif
        !          2304:     xmlXPathDebugDumpObject(xpathOutput, res, 0);
        !          2305:     xmlXPathFreeObject(res);
        !          2306:     xmlXPathFreeContext(ctxt);
        !          2307: }
        !          2308: 
        !          2309: /**
        !          2310:  * xpathExprTest:
        !          2311:  * @filename: the file to parse
        !          2312:  * @result: the file with expected result
        !          2313:  * @err: the file with error messages
        !          2314:  *
        !          2315:  * Parse a file containing XPath standalone expressions and evaluate them
        !          2316:  *
        !          2317:  * Returns 0 in case of success, an error code otherwise
        !          2318:  */
        !          2319: static int
        !          2320: xpathCommonTest(const char *filename, const char *result,
        !          2321:                 int xptr, int expr) {
        !          2322:     FILE *input;
        !          2323:     char expression[5000];
        !          2324:     int len, ret = 0;
        !          2325:     char *temp;
        !          2326: 
        !          2327:     temp = resultFilename(filename, "", ".res");
        !          2328:     if (temp == NULL) {
        !          2329:         fprintf(stderr, "Out of memory\n");
        !          2330:         fatalError();
        !          2331:     }
        !          2332:     xpathOutput = fopen(temp, "wb");
        !          2333:     if (xpathOutput == NULL) {
        !          2334:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          2335:         free(temp);
        !          2336:        return(-1);
        !          2337:     }
        !          2338: 
        !          2339:     input = fopen(filename, "rb");
        !          2340:     if (input == NULL) {
        !          2341:         xmlGenericError(xmlGenericErrorContext,
        !          2342:                "Cannot open %s for reading\n", filename);
        !          2343:         free(temp);
        !          2344:        return(-1);
        !          2345:     }
        !          2346:     while (fgets(expression, 4500, input) != NULL) {
        !          2347:        len = strlen(expression);
        !          2348:        len--;
        !          2349:        while ((len >= 0) &&
        !          2350:               ((expression[len] == '\n') || (expression[len] == '\t') ||
        !          2351:                (expression[len] == '\r') || (expression[len] == ' '))) len--;
        !          2352:        expression[len + 1] = 0;
        !          2353:        if (len >= 0) {
        !          2354:            fprintf(xpathOutput,
        !          2355:                    "\n========================\nExpression: %s\n",
        !          2356:                    expression) ;
        !          2357:            testXPath(expression, xptr, expr);
        !          2358:        }
        !          2359:     }
        !          2360: 
        !          2361:     fclose(input);
        !          2362:     fclose(xpathOutput);
        !          2363:     if (result != NULL) {
        !          2364:        ret = compareFiles(temp, result);
        !          2365:        if (ret) {
        !          2366:            fprintf(stderr, "Result for %s failed\n", filename);
        !          2367:        }
        !          2368:     }
        !          2369: 
        !          2370:     if (temp != NULL) {
        !          2371:         unlink(temp);
        !          2372:         free(temp);
        !          2373:     }
        !          2374:     return(ret);
        !          2375: }
        !          2376: 
        !          2377: /**
        !          2378:  * xpathExprTest:
        !          2379:  * @filename: the file to parse
        !          2380:  * @result: the file with expected result
        !          2381:  * @err: the file with error messages
        !          2382:  *
        !          2383:  * Parse a file containing XPath standalone expressions and evaluate them
        !          2384:  *
        !          2385:  * Returns 0 in case of success, an error code otherwise
        !          2386:  */
        !          2387: static int
        !          2388: xpathExprTest(const char *filename, const char *result,
        !          2389:               const char *err ATTRIBUTE_UNUSED,
        !          2390:               int options ATTRIBUTE_UNUSED) {
        !          2391:     return(xpathCommonTest(filename, result, 0, 1));
        !          2392: }
        !          2393: 
        !          2394: /**
        !          2395:  * xpathDocTest:
        !          2396:  * @filename: the file to parse
        !          2397:  * @result: the file with expected result
        !          2398:  * @err: the file with error messages
        !          2399:  *
        !          2400:  * Parse a file containing XPath expressions and evaluate them against
        !          2401:  * a set of corresponding documents.
        !          2402:  *
        !          2403:  * Returns 0 in case of success, an error code otherwise
        !          2404:  */
        !          2405: static int
        !          2406: xpathDocTest(const char *filename,
        !          2407:              const char *resul ATTRIBUTE_UNUSED,
        !          2408:              const char *err ATTRIBUTE_UNUSED,
        !          2409:              int options) {
        !          2410: 
        !          2411:     char pattern[500];
        !          2412:     char result[500];
        !          2413:     glob_t globbuf;
        !          2414:     size_t i;
        !          2415:     int ret = 0, res;
        !          2416: 
        !          2417:     xpathDocument = xmlReadFile(filename, NULL,
        !          2418:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
        !          2419:     if (xpathDocument == NULL) {
        !          2420:         fprintf(stderr, "Failed to load %s\n", filename);
        !          2421:        return(-1);
        !          2422:     }
        !          2423: 
        !          2424:     snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
        !          2425:     pattern[499] = 0;
        !          2426:     globbuf.gl_offs = 0;
        !          2427:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
        !          2428:     for (i = 0;i < globbuf.gl_pathc;i++) {
        !          2429:         snprintf(result, 499, "result/XPath/tests/%s",
        !          2430:                 baseFilename(globbuf.gl_pathv[i]));
        !          2431:        res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
        !          2432:        if (res != 0)
        !          2433:            ret = res;
        !          2434:     }
        !          2435:     globfree(&globbuf);
        !          2436: 
        !          2437:     xmlFreeDoc(xpathDocument);
        !          2438:     return(ret);
        !          2439: }
        !          2440: 
        !          2441: #ifdef LIBXML_XPTR_ENABLED
        !          2442: /**
        !          2443:  * xptrDocTest:
        !          2444:  * @filename: the file to parse
        !          2445:  * @result: the file with expected result
        !          2446:  * @err: the file with error messages
        !          2447:  *
        !          2448:  * Parse a file containing XPath expressions and evaluate them against
        !          2449:  * a set of corresponding documents.
        !          2450:  *
        !          2451:  * Returns 0 in case of success, an error code otherwise
        !          2452:  */
        !          2453: static int
        !          2454: xptrDocTest(const char *filename,
        !          2455:             const char *resul ATTRIBUTE_UNUSED,
        !          2456:             const char *err ATTRIBUTE_UNUSED,
        !          2457:             int options) {
        !          2458: 
        !          2459:     char pattern[500];
        !          2460:     char result[500];
        !          2461:     glob_t globbuf;
        !          2462:     size_t i;
        !          2463:     int ret = 0, res;
        !          2464: 
        !          2465:     xpathDocument = xmlReadFile(filename, NULL,
        !          2466:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
        !          2467:     if (xpathDocument == NULL) {
        !          2468:         fprintf(stderr, "Failed to load %s\n", filename);
        !          2469:        return(-1);
        !          2470:     }
        !          2471: 
        !          2472:     snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
        !          2473:     pattern[499] = 0;
        !          2474:     globbuf.gl_offs = 0;
        !          2475:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
        !          2476:     for (i = 0;i < globbuf.gl_pathc;i++) {
        !          2477:         snprintf(result, 499, "result/XPath/xptr/%s",
        !          2478:                 baseFilename(globbuf.gl_pathv[i]));
        !          2479:        res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
        !          2480:        if (res != 0)
        !          2481:            ret = res;
        !          2482:     }
        !          2483:     globfree(&globbuf);
        !          2484: 
        !          2485:     xmlFreeDoc(xpathDocument);
        !          2486:     return(ret);
        !          2487: }
        !          2488: #endif /* LIBXML_XPTR_ENABLED */
        !          2489: 
        !          2490: /**
        !          2491:  * xmlidDocTest:
        !          2492:  * @filename: the file to parse
        !          2493:  * @result: the file with expected result
        !          2494:  * @err: the file with error messages
        !          2495:  *
        !          2496:  * Parse a file containing xml:id and check for errors and verify
        !          2497:  * that XPath queries will work on them as expected.
        !          2498:  *
        !          2499:  * Returns 0 in case of success, an error code otherwise
        !          2500:  */
        !          2501: static int
        !          2502: xmlidDocTest(const char *filename,
        !          2503:              const char *result,
        !          2504:              const char *err,
        !          2505:              int options) {
        !          2506: 
        !          2507:     int res = 0;
        !          2508:     int ret = 0;
        !          2509:     char *temp;
        !          2510: 
        !          2511:     xpathDocument = xmlReadFile(filename, NULL,
        !          2512:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
        !          2513:     if (xpathDocument == NULL) {
        !          2514:         fprintf(stderr, "Failed to load %s\n", filename);
        !          2515:        return(-1);
        !          2516:     }
        !          2517: 
        !          2518:     temp = resultFilename(filename, "", ".res");
        !          2519:     if (temp == NULL) {
        !          2520:         fprintf(stderr, "Out of memory\n");
        !          2521:         fatalError();
        !          2522:     }
        !          2523:     xpathOutput = fopen(temp, "wb");
        !          2524:     if (xpathOutput == NULL) {
        !          2525:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          2526:         xmlFreeDoc(xpathDocument);
        !          2527:         free(temp);
        !          2528:        return(-1);
        !          2529:     }
        !          2530: 
        !          2531:     testXPath("id('bar')", 0, 0);
        !          2532: 
        !          2533:     fclose(xpathOutput);
        !          2534:     if (result != NULL) {
        !          2535:        ret = compareFiles(temp, result);
        !          2536:        if (ret) {
        !          2537:            fprintf(stderr, "Result for %s failed\n", filename);
        !          2538:            res = 1;
        !          2539:        }
        !          2540:     }
        !          2541: 
        !          2542:     if (temp != NULL) {
        !          2543:         unlink(temp);
        !          2544:         free(temp);
        !          2545:     }
        !          2546:     xmlFreeDoc(xpathDocument);
        !          2547: 
        !          2548:     if (err != NULL) {
        !          2549:        ret = compareFileMem(err, testErrors, testErrorsSize);
        !          2550:        if (ret != 0) {
        !          2551:            fprintf(stderr, "Error for %s failed\n", filename);
        !          2552:            res = 1;
        !          2553:        }
        !          2554:     }
        !          2555:     return(res);
        !          2556: }
        !          2557: 
        !          2558: #endif /* LIBXML_DEBUG_ENABLED */
        !          2559: #endif /* XPATH */
        !          2560: /************************************************************************
        !          2561:  *                                                                     *
        !          2562:  *                     URI based tests                                 *
        !          2563:  *                                                                     *
        !          2564:  ************************************************************************/
        !          2565: 
        !          2566: static void
        !          2567: handleURI(const char *str, const char *base, FILE *o) {
        !          2568:     int ret;
        !          2569:     xmlURIPtr uri;
        !          2570:     xmlChar *res = NULL;
        !          2571: 
        !          2572:     uri = xmlCreateURI();
        !          2573: 
        !          2574:     if (base == NULL) {
        !          2575:        ret = xmlParseURIReference(uri, str);
        !          2576:        if (ret != 0)
        !          2577:            fprintf(o, "%s : error %d\n", str, ret);
        !          2578:        else {
        !          2579:            xmlNormalizeURIPath(uri->path);
        !          2580:            xmlPrintURI(o, uri);
        !          2581:            fprintf(o, "\n");
        !          2582:        }
        !          2583:     } else {
        !          2584:        res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
        !          2585:        if (res != NULL) {
        !          2586:            fprintf(o, "%s\n", (char *) res);
        !          2587:        }
        !          2588:        else
        !          2589:            fprintf(o, "::ERROR::\n");
        !          2590:     }
        !          2591:     if (res != NULL)
        !          2592:        xmlFree(res);
        !          2593:     xmlFreeURI(uri);
        !          2594: }
        !          2595: 
        !          2596: /**
        !          2597:  * uriCommonTest:
        !          2598:  * @filename: the file to parse
        !          2599:  * @result: the file with expected result
        !          2600:  * @err: the file with error messages
        !          2601:  *
        !          2602:  * Parse a file containing URI and check for errors
        !          2603:  *
        !          2604:  * Returns 0 in case of success, an error code otherwise
        !          2605:  */
        !          2606: static int
        !          2607: uriCommonTest(const char *filename,
        !          2608:              const char *result,
        !          2609:              const char *err,
        !          2610:              const char *base) {
        !          2611:     char *temp;
        !          2612:     FILE *o, *f;
        !          2613:     char str[1024];
        !          2614:     int res = 0, i, ret;
        !          2615: 
        !          2616:     temp = resultFilename(filename, "", ".res");
        !          2617:     if (temp == NULL) {
        !          2618:         fprintf(stderr, "Out of memory\n");
        !          2619:         fatalError();
        !          2620:     }
        !          2621:     o = fopen(temp, "wb");
        !          2622:     if (o == NULL) {
        !          2623:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          2624:         free(temp);
        !          2625:        return(-1);
        !          2626:     }
        !          2627:     f = fopen(filename, "rb");
        !          2628:     if (f == NULL) {
        !          2629:        fprintf(stderr, "failed to open input file %s\n", filename);
        !          2630:        fclose(o);
        !          2631:         if (temp != NULL) {
        !          2632:             unlink(temp);
        !          2633:             free(temp);
        !          2634:         }
        !          2635:        return(-1);
        !          2636:     }
        !          2637: 
        !          2638:     while (1) {
        !          2639:        /*
        !          2640:         * read one line in string buffer.
        !          2641:         */
        !          2642:        if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
        !          2643:           break;
        !          2644: 
        !          2645:        /*
        !          2646:         * remove the ending spaces
        !          2647:         */
        !          2648:        i = strlen(str);
        !          2649:        while ((i > 0) &&
        !          2650:               ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
        !          2651:                (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
        !          2652:            i--;
        !          2653:            str[i] = 0;
        !          2654:        }
        !          2655:        nb_tests++;
        !          2656:        handleURI(str, base, o);
        !          2657:     }
        !          2658: 
        !          2659:     fclose(f);
        !          2660:     fclose(o);
        !          2661: 
        !          2662:     if (result != NULL) {
        !          2663:        ret = compareFiles(temp, result);
        !          2664:        if (ret) {
        !          2665:            fprintf(stderr, "Result for %s failed\n", filename);
        !          2666:            res = 1;
        !          2667:        }
        !          2668:     }
        !          2669:     if (err != NULL) {
        !          2670:        ret = compareFileMem(err, testErrors, testErrorsSize);
        !          2671:        if (ret != 0) {
        !          2672:            fprintf(stderr, "Error for %s failed\n", filename);
        !          2673:            res = 1;
        !          2674:        }
        !          2675:     }
        !          2676: 
        !          2677:     if (temp != NULL) {
        !          2678:         unlink(temp);
        !          2679:         free(temp);
        !          2680:     }
        !          2681:     return(res);
        !          2682: }
        !          2683: 
        !          2684: /**
        !          2685:  * uriParseTest:
        !          2686:  * @filename: the file to parse
        !          2687:  * @result: the file with expected result
        !          2688:  * @err: the file with error messages
        !          2689:  *
        !          2690:  * Parse a file containing URI and check for errors
        !          2691:  *
        !          2692:  * Returns 0 in case of success, an error code otherwise
        !          2693:  */
        !          2694: static int
        !          2695: uriParseTest(const char *filename,
        !          2696:              const char *result,
        !          2697:              const char *err,
        !          2698:              int options ATTRIBUTE_UNUSED) {
        !          2699:     return(uriCommonTest(filename, result, err, NULL));
        !          2700: }
        !          2701: 
        !          2702: /**
        !          2703:  * uriBaseTest:
        !          2704:  * @filename: the file to parse
        !          2705:  * @result: the file with expected result
        !          2706:  * @err: the file with error messages
        !          2707:  *
        !          2708:  * Parse a file containing URI, compose them against a fixed base and
        !          2709:  * check for errors
        !          2710:  *
        !          2711:  * Returns 0 in case of success, an error code otherwise
        !          2712:  */
        !          2713: static int
        !          2714: uriBaseTest(const char *filename,
        !          2715:              const char *result,
        !          2716:              const char *err,
        !          2717:              int options ATTRIBUTE_UNUSED) {
        !          2718:     return(uriCommonTest(filename, result, err,
        !          2719:                          "http://foo.com/path/to/index.html?orig#help"));
        !          2720: }
        !          2721: 
        !          2722: static int urip_success = 1;
        !          2723: static int urip_current = 0;
        !          2724: static const char *urip_testURLs[] = {
        !          2725:     "urip://example.com/a b.html",
        !          2726:     "urip://example.com/a%20b.html",
        !          2727:     "file:///path/to/a b.html",
        !          2728:     "file:///path/to/a%20b.html",
        !          2729:     "/path/to/a b.html",
        !          2730:     "/path/to/a%20b.html",
        !          2731:     "urip://example.com/résumé.html",
        !          2732:     "urip://example.com/test?a=1&b=2%263&c=4#foo",
        !          2733:     NULL
        !          2734: };
        !          2735: static const char *urip_rcvsURLs[] = {
        !          2736:     /* it is an URI the strings must be escaped */
        !          2737:     "urip://example.com/a%20b.html",
        !          2738:     /* check that % escaping is not broken */
        !          2739:     "urip://example.com/a%20b.html",
        !          2740:     /* it's an URI path the strings must be escaped */
        !          2741:     "file:///path/to/a%20b.html",
        !          2742:     /* check that % escaping is not broken */
        !          2743:     "file:///path/to/a%20b.html",
        !          2744:     /* this is not an URI, this is a path, so this should not be escaped */
        !          2745:     "/path/to/a b.html",
        !          2746:     /* check that paths with % are not broken */
        !          2747:     "/path/to/a%20b.html",
        !          2748:     /* out of context the encoding can't be guessed byte by byte conversion */
        !          2749:     "urip://example.com/r%E9sum%E9.html",
        !          2750:     /* verify we don't destroy URIs especially the query part */
        !          2751:     "urip://example.com/test?a=1&b=2%263&c=4#foo",
        !          2752:     NULL
        !          2753: };
        !          2754: static const char *urip_res = "<list/>";
        !          2755: static const char *urip_cur = NULL;
        !          2756: static int urip_rlen;
        !          2757: 
        !          2758: /**
        !          2759:  * uripMatch:
        !          2760:  * @URI: an URI to test
        !          2761:  *
        !          2762:  * Check for an urip: query
        !          2763:  *
        !          2764:  * Returns 1 if yes and 0 if another Input module should be used
        !          2765:  */
        !          2766: static int
        !          2767: uripMatch(const char * URI) {
        !          2768:     if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
        !          2769:         return(0);
        !          2770:     /* Verify we received the escaped URL */
        !          2771:     if (strcmp(urip_rcvsURLs[urip_current], URI))
        !          2772:        urip_success = 0;
        !          2773:     return(1);
        !          2774: }
        !          2775: 
        !          2776: /**
        !          2777:  * uripOpen:
        !          2778:  * @URI: an URI to test
        !          2779:  *
        !          2780:  * Return a pointer to the urip: query handler, in this example simply
        !          2781:  * the urip_current pointer...
        !          2782:  *
        !          2783:  * Returns an Input context or NULL in case or error
        !          2784:  */
        !          2785: static void *
        !          2786: uripOpen(const char * URI) {
        !          2787:     if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
        !          2788:         return(NULL);
        !          2789:     /* Verify we received the escaped URL */
        !          2790:     if (strcmp(urip_rcvsURLs[urip_current], URI))
        !          2791:        urip_success = 0;
        !          2792:     urip_cur = urip_res;
        !          2793:     urip_rlen = strlen(urip_res);
        !          2794:     return((void *) urip_cur);
        !          2795: }
        !          2796: 
        !          2797: /**
        !          2798:  * uripClose:
        !          2799:  * @context: the read context
        !          2800:  *
        !          2801:  * Close the urip: query handler
        !          2802:  *
        !          2803:  * Returns 0 or -1 in case of error
        !          2804:  */
        !          2805: static int
        !          2806: uripClose(void * context) {
        !          2807:     if (context == NULL) return(-1);
        !          2808:     urip_cur = NULL;
        !          2809:     urip_rlen = 0;
        !          2810:     return(0);
        !          2811: }
        !          2812: 
        !          2813: /**
        !          2814:  * uripRead:
        !          2815:  * @context: the read context
        !          2816:  * @buffer: where to store data
        !          2817:  * @len: number of bytes to read
        !          2818:  *
        !          2819:  * Implement an urip: query read.
        !          2820:  *
        !          2821:  * Returns the number of bytes read or -1 in case of error
        !          2822:  */
        !          2823: static int
        !          2824: uripRead(void * context, char * buffer, int len) {
        !          2825:    const char *ptr = (const char *) context;
        !          2826: 
        !          2827:    if ((context == NULL) || (buffer == NULL) || (len < 0))
        !          2828:        return(-1);
        !          2829: 
        !          2830:    if (len > urip_rlen) len = urip_rlen;
        !          2831:    memcpy(buffer, ptr, len);
        !          2832:    urip_rlen -= len;
        !          2833:    return(len);
        !          2834: }
        !          2835: 
        !          2836: static int
        !          2837: urip_checkURL(const char *URL) {
        !          2838:     xmlDocPtr doc;
        !          2839: 
        !          2840:     doc = xmlReadFile(URL, NULL, 0);
        !          2841:     if (doc == NULL)
        !          2842:         return(-1);
        !          2843:     xmlFreeDoc(doc);
        !          2844:     return(1);
        !          2845: }
        !          2846: 
        !          2847: /**
        !          2848:  * uriPathTest:
        !          2849:  * @filename: ignored
        !          2850:  * @result: ignored
        !          2851:  * @err: ignored
        !          2852:  *
        !          2853:  * Run a set of tests to check how Path and URI are handled before
        !          2854:  * being passed to the I/O layer
        !          2855:  *
        !          2856:  * Returns 0 in case of success, an error code otherwise
        !          2857:  */
        !          2858: static int
        !          2859: uriPathTest(const char *filename ATTRIBUTE_UNUSED,
        !          2860:              const char *result ATTRIBUTE_UNUSED,
        !          2861:              const char *err ATTRIBUTE_UNUSED,
        !          2862:              int options ATTRIBUTE_UNUSED) {
        !          2863:     int parsed;
        !          2864:     int failures = 0;
        !          2865: 
        !          2866:     /*
        !          2867:      * register the new I/O handlers
        !          2868:      */
        !          2869:     if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
        !          2870:     {
        !          2871:         fprintf(stderr, "failed to register HTTP handler\n");
        !          2872:        return(-1);
        !          2873:     }
        !          2874: 
        !          2875:     for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
        !          2876:         urip_success = 1;
        !          2877:         parsed = urip_checkURL(urip_testURLs[urip_current]);
        !          2878:        if (urip_success != 1) {
        !          2879:            fprintf(stderr, "failed the URL passing test for %s",
        !          2880:                    urip_testURLs[urip_current]);
        !          2881:            failures++;
        !          2882:        } else if (parsed != 1) {
        !          2883:            fprintf(stderr, "failed the parsing test for %s",
        !          2884:                    urip_testURLs[urip_current]);
        !          2885:            failures++;
        !          2886:        }
        !          2887:        nb_tests++;
        !          2888:     }
        !          2889: 
        !          2890:     xmlPopInputCallbacks();
        !          2891:     return(failures);
        !          2892: }
        !          2893: 
        !          2894: #ifdef LIBXML_SCHEMAS_ENABLED
        !          2895: /************************************************************************
        !          2896:  *                                                                     *
        !          2897:  *                     Schemas tests                                   *
        !          2898:  *                                                                     *
        !          2899:  ************************************************************************/
        !          2900: static int
        !          2901: schemasOneTest(const char *sch,
        !          2902:                const char *filename,
        !          2903:                const char *result,
        !          2904:               const char *err,
        !          2905:               int options,
        !          2906:               xmlSchemaPtr schemas) {
        !          2907:     xmlDocPtr doc;
        !          2908:     xmlSchemaValidCtxtPtr ctxt;
        !          2909:     int ret = 0;
        !          2910:     int validResult = 0;
        !          2911:     char *temp;
        !          2912:     FILE *schemasOutput;
        !          2913: 
        !          2914:     doc = xmlReadFile(filename, NULL, options);
        !          2915:     if (doc == NULL) {
        !          2916:         fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
        !          2917:        return(-1);
        !          2918:     }
        !          2919: 
        !          2920:     temp = resultFilename(result, "", ".res");
        !          2921:     if (temp == NULL) {
        !          2922:         fprintf(stderr, "Out of memory\n");
        !          2923:         fatalError();
        !          2924:     }
        !          2925:     schemasOutput = fopen(temp, "wb");
        !          2926:     if (schemasOutput == NULL) {
        !          2927:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          2928:        xmlFreeDoc(doc);
        !          2929:         free(temp);
        !          2930:        return(-1);
        !          2931:     }
        !          2932: 
        !          2933:     ctxt = xmlSchemaNewValidCtxt(schemas);
        !          2934:     xmlSchemaSetValidErrors(ctxt,
        !          2935:          (xmlSchemaValidityErrorFunc) testErrorHandler,
        !          2936:          (xmlSchemaValidityWarningFunc) testErrorHandler,
        !          2937:         ctxt);
        !          2938:     validResult = xmlSchemaValidateDoc(ctxt, doc);
        !          2939:     if (validResult == 0) {
        !          2940:        fprintf(schemasOutput, "%s validates\n", filename);
        !          2941:     } else if (validResult > 0) {
        !          2942:        fprintf(schemasOutput, "%s fails to validate\n", filename);
        !          2943:     } else {
        !          2944:        fprintf(schemasOutput, "%s validation generated an internal error\n",
        !          2945:               filename);
        !          2946:     }
        !          2947:     fclose(schemasOutput);
        !          2948:     if (result) {
        !          2949:        if (compareFiles(temp, result)) {
        !          2950:            fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
        !          2951:            ret = 1;
        !          2952:        }
        !          2953:     }
        !          2954:     if (temp != NULL) {
        !          2955:         unlink(temp);
        !          2956:         free(temp);
        !          2957:     }
        !          2958: 
        !          2959:     if ((validResult != 0) && (err != NULL)) {
        !          2960:        if (compareFileMem(err, testErrors, testErrorsSize)) {
        !          2961:            fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
        !          2962:            ret = 1;
        !          2963:        }
        !          2964:     }
        !          2965: 
        !          2966:     xmlSchemaFreeValidCtxt(ctxt);
        !          2967:     xmlFreeDoc(doc);
        !          2968:     return(ret);
        !          2969: }
        !          2970: /**
        !          2971:  * schemasTest:
        !          2972:  * @filename: the schemas file
        !          2973:  * @result: the file with expected result
        !          2974:  * @err: the file with error messages
        !          2975:  *
        !          2976:  * Parse a file containing URI, compose them against a fixed base and
        !          2977:  * check for errors
        !          2978:  *
        !          2979:  * Returns 0 in case of success, an error code otherwise
        !          2980:  */
        !          2981: static int
        !          2982: schemasTest(const char *filename,
        !          2983:             const char *resul ATTRIBUTE_UNUSED,
        !          2984:             const char *errr ATTRIBUTE_UNUSED,
        !          2985:             int options) {
        !          2986:     const char *base = baseFilename(filename);
        !          2987:     const char *base2;
        !          2988:     const char *instance;
        !          2989:     xmlSchemaParserCtxtPtr ctxt;
        !          2990:     xmlSchemaPtr schemas;
        !          2991:     int res = 0, len, ret;
        !          2992:     char pattern[500];
        !          2993:     char prefix[500];
        !          2994:     char result[500];
        !          2995:     char err[500];
        !          2996:     glob_t globbuf;
        !          2997:     size_t i;
        !          2998:     char count = 0;
        !          2999: 
        !          3000:     /* first compile the schemas if possible */
        !          3001:     ctxt = xmlSchemaNewParserCtxt(filename);
        !          3002:     xmlSchemaSetParserErrors(ctxt,
        !          3003:          (xmlSchemaValidityErrorFunc) testErrorHandler,
        !          3004:          (xmlSchemaValidityWarningFunc) testErrorHandler,
        !          3005:         ctxt);
        !          3006:     schemas = xmlSchemaParse(ctxt);
        !          3007:     xmlSchemaFreeParserCtxt(ctxt);
        !          3008: 
        !          3009:     /*
        !          3010:      * most of the mess is about the output filenames generated by the Makefile
        !          3011:      */
        !          3012:     len = strlen(base);
        !          3013:     if ((len > 499) || (len < 5)) {
        !          3014:         xmlSchemaFree(schemas);
        !          3015:        return(-1);
        !          3016:     }
        !          3017:     len -= 4; /* remove trailing .xsd */
        !          3018:     if (base[len - 2] == '_') {
        !          3019:         len -= 2; /* remove subtest number */
        !          3020:     }
        !          3021:     if (base[len - 2] == '_') {
        !          3022:         len -= 2; /* remove subtest number */
        !          3023:     }
        !          3024:     memcpy(prefix, base, len);
        !          3025:     prefix[len] = 0;
        !          3026: 
        !          3027:     snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
        !          3028:     pattern[499] = 0;
        !          3029: 
        !          3030:     if (base[len] == '_') {
        !          3031:         len += 2;
        !          3032:        memcpy(prefix, base, len);
        !          3033:        prefix[len] = 0;
        !          3034:     }
        !          3035: 
        !          3036:     globbuf.gl_offs = 0;
        !          3037:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
        !          3038:     for (i = 0;i < globbuf.gl_pathc;i++) {
        !          3039:         testErrorsSize = 0;
        !          3040:        testErrors[0] = 0;
        !          3041:         instance = globbuf.gl_pathv[i];
        !          3042:        base2 = baseFilename(instance);
        !          3043:        len = strlen(base2);
        !          3044:        if ((len > 6) && (base2[len - 6] == '_')) {
        !          3045:            count = base2[len - 5];
        !          3046:            snprintf(result, 499, "result/schemas/%s_%c",
        !          3047:                     prefix, count);
        !          3048:            result[499] = 0;
        !          3049:            snprintf(err, 499, "result/schemas/%s_%c.err",
        !          3050:                     prefix, count);
        !          3051:            err[499] = 0;
        !          3052:        } else {
        !          3053:            fprintf(stderr, "don't know how to process %s\n", instance);
        !          3054:            continue;
        !          3055:        }
        !          3056:        if (schemas == NULL) {
        !          3057:        } else {
        !          3058:            nb_tests++;
        !          3059:            ret = schemasOneTest(filename, instance, result, err,
        !          3060:                                 options, schemas);
        !          3061:            if (ret != 0)
        !          3062:                res = ret;
        !          3063:        }
        !          3064:     }
        !          3065:     globfree(&globbuf);
        !          3066:     xmlSchemaFree(schemas);
        !          3067: 
        !          3068:     return(res);
        !          3069: }
        !          3070: 
        !          3071: /************************************************************************
        !          3072:  *                                                                     *
        !          3073:  *                     Schemas tests                                   *
        !          3074:  *                                                                     *
        !          3075:  ************************************************************************/
        !          3076: static int
        !          3077: rngOneTest(const char *sch,
        !          3078:                const char *filename,
        !          3079:                const char *result,
        !          3080:               const char *err,
        !          3081:               int options,
        !          3082:               xmlRelaxNGPtr schemas) {
        !          3083:     xmlDocPtr doc;
        !          3084:     xmlRelaxNGValidCtxtPtr ctxt;
        !          3085:     int ret = 0;
        !          3086:     char *temp;
        !          3087:     FILE *schemasOutput;
        !          3088: 
        !          3089:     doc = xmlReadFile(filename, NULL, options);
        !          3090:     if (doc == NULL) {
        !          3091:         fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
        !          3092:        return(-1);
        !          3093:     }
        !          3094: 
        !          3095:     temp = resultFilename(result, "", ".res");
        !          3096:     if (temp == NULL) {
        !          3097:         fprintf(stderr, "Out of memory\n");
        !          3098:         fatalError();
        !          3099:     }
        !          3100:     schemasOutput = fopen(temp, "wb");
        !          3101:     if (schemasOutput == NULL) {
        !          3102:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          3103:        xmlFreeDoc(doc);
        !          3104:         free(temp);
        !          3105:        return(-1);
        !          3106:     }
        !          3107: 
        !          3108:     ctxt = xmlRelaxNGNewValidCtxt(schemas);
        !          3109:     xmlRelaxNGSetValidErrors(ctxt,
        !          3110:          (xmlRelaxNGValidityErrorFunc) testErrorHandler,
        !          3111:          (xmlRelaxNGValidityWarningFunc) testErrorHandler,
        !          3112:         ctxt);
        !          3113:     ret = xmlRelaxNGValidateDoc(ctxt, doc);
        !          3114:     if (ret == 0) {
        !          3115:        testErrorHandler(NULL, "%s validates\n", filename);
        !          3116:     } else if (ret > 0) {
        !          3117:        testErrorHandler(NULL, "%s fails to validate\n", filename);
        !          3118:     } else {
        !          3119:        testErrorHandler(NULL, "%s validation generated an internal error\n",
        !          3120:               filename);
        !          3121:     }
        !          3122:     fclose(schemasOutput);
        !          3123:     ret = 0;
        !          3124:     if (result) {
        !          3125:        if (compareFiles(temp, result)) {
        !          3126:            fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
        !          3127:            ret = 1;
        !          3128:        }
        !          3129:     }
        !          3130:     if (temp != NULL) {
        !          3131:         unlink(temp);
        !          3132:         free(temp);
        !          3133:     }
        !          3134: 
        !          3135:     if (err != NULL) {
        !          3136:        if (compareFileMem(err, testErrors, testErrorsSize)) {
        !          3137:            fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
        !          3138:            ret = 1;
        !          3139:            printf("%s", testErrors);
        !          3140:        }
        !          3141:     }
        !          3142: 
        !          3143: 
        !          3144:     xmlRelaxNGFreeValidCtxt(ctxt);
        !          3145:     xmlFreeDoc(doc);
        !          3146:     return(ret);
        !          3147: }
        !          3148: /**
        !          3149:  * rngTest:
        !          3150:  * @filename: the schemas file
        !          3151:  * @result: the file with expected result
        !          3152:  * @err: the file with error messages
        !          3153:  *
        !          3154:  * Parse an RNG schemas and then apply it to the related .xml
        !          3155:  *
        !          3156:  * Returns 0 in case of success, an error code otherwise
        !          3157:  */
        !          3158: static int
        !          3159: rngTest(const char *filename,
        !          3160:             const char *resul ATTRIBUTE_UNUSED,
        !          3161:             const char *errr ATTRIBUTE_UNUSED,
        !          3162:             int options) {
        !          3163:     const char *base = baseFilename(filename);
        !          3164:     const char *base2;
        !          3165:     const char *instance;
        !          3166:     xmlRelaxNGParserCtxtPtr ctxt;
        !          3167:     xmlRelaxNGPtr schemas;
        !          3168:     int res = 0, len, ret = 0;
        !          3169:     char pattern[500];
        !          3170:     char prefix[500];
        !          3171:     char result[500];
        !          3172:     char err[500];
        !          3173:     glob_t globbuf;
        !          3174:     size_t i;
        !          3175:     char count = 0;
        !          3176: 
        !          3177:     /* first compile the schemas if possible */
        !          3178:     ctxt = xmlRelaxNGNewParserCtxt(filename);
        !          3179:     xmlRelaxNGSetParserErrors(ctxt,
        !          3180:          (xmlRelaxNGValidityErrorFunc) testErrorHandler,
        !          3181:          (xmlRelaxNGValidityWarningFunc) testErrorHandler,
        !          3182:         ctxt);
        !          3183:     schemas = xmlRelaxNGParse(ctxt);
        !          3184:     xmlRelaxNGFreeParserCtxt(ctxt);
        !          3185: 
        !          3186:     /*
        !          3187:      * most of the mess is about the output filenames generated by the Makefile
        !          3188:      */
        !          3189:     len = strlen(base);
        !          3190:     if ((len > 499) || (len < 5)) {
        !          3191:         xmlRelaxNGFree(schemas);
        !          3192:        return(-1);
        !          3193:     }
        !          3194:     len -= 4; /* remove trailing .rng */
        !          3195:     memcpy(prefix, base, len);
        !          3196:     prefix[len] = 0;
        !          3197: 
        !          3198:     snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
        !          3199:     pattern[499] = 0;
        !          3200: 
        !          3201:     globbuf.gl_offs = 0;
        !          3202:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
        !          3203:     for (i = 0;i < globbuf.gl_pathc;i++) {
        !          3204:         testErrorsSize = 0;
        !          3205:        testErrors[0] = 0;
        !          3206:         instance = globbuf.gl_pathv[i];
        !          3207:        base2 = baseFilename(instance);
        !          3208:        len = strlen(base2);
        !          3209:        if ((len > 6) && (base2[len - 6] == '_')) {
        !          3210:            count = base2[len - 5];
        !          3211:            snprintf(result, 499, "result/relaxng/%s_%c",
        !          3212:                     prefix, count);
        !          3213:            result[499] = 0;
        !          3214:            snprintf(err, 499, "result/relaxng/%s_%c.err",
        !          3215:                     prefix, count);
        !          3216:            err[499] = 0;
        !          3217:        } else {
        !          3218:            fprintf(stderr, "don't know how to process %s\n", instance);
        !          3219:            continue;
        !          3220:        }
        !          3221:        if (schemas == NULL) {
        !          3222:        } else {
        !          3223:            nb_tests++;
        !          3224:            ret = rngOneTest(filename, instance, result, err,
        !          3225:                                 options, schemas);
        !          3226:            if (res != 0)
        !          3227:                ret = res;
        !          3228:        }
        !          3229:     }
        !          3230:     globfree(&globbuf);
        !          3231:     xmlRelaxNGFree(schemas);
        !          3232: 
        !          3233:     return(ret);
        !          3234: }
        !          3235: 
        !          3236: #ifdef LIBXML_READER_ENABLED
        !          3237: /**
        !          3238:  * rngStreamTest:
        !          3239:  * @filename: the schemas file
        !          3240:  * @result: the file with expected result
        !          3241:  * @err: the file with error messages
        !          3242:  *
        !          3243:  * Parse a set of files with streaming, applying an RNG schemas
        !          3244:  *
        !          3245:  * Returns 0 in case of success, an error code otherwise
        !          3246:  */
        !          3247: static int
        !          3248: rngStreamTest(const char *filename,
        !          3249:             const char *resul ATTRIBUTE_UNUSED,
        !          3250:             const char *errr ATTRIBUTE_UNUSED,
        !          3251:             int options) {
        !          3252:     const char *base = baseFilename(filename);
        !          3253:     const char *base2;
        !          3254:     const char *instance;
        !          3255:     int res = 0, len, ret;
        !          3256:     char pattern[500];
        !          3257:     char prefix[500];
        !          3258:     char result[500];
        !          3259:     char err[500];
        !          3260:     glob_t globbuf;
        !          3261:     size_t i;
        !          3262:     char count = 0;
        !          3263:     xmlTextReaderPtr reader;
        !          3264:     int disable_err = 0;
        !          3265: 
        !          3266:     /*
        !          3267:      * most of the mess is about the output filenames generated by the Makefile
        !          3268:      */
        !          3269:     len = strlen(base);
        !          3270:     if ((len > 499) || (len < 5)) {
        !          3271:        fprintf(stderr, "len(base) == %d !\n", len);
        !          3272:        return(-1);
        !          3273:     }
        !          3274:     len -= 4; /* remove trailing .rng */
        !          3275:     memcpy(prefix, base, len);
        !          3276:     prefix[len] = 0;
        !          3277: 
        !          3278:     /*
        !          3279:      * strictly unifying the error messages is nearly impossible this
        !          3280:      * hack is also done in the Makefile
        !          3281:      */
        !          3282:     if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
        !          3283:         (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
        !          3284:         (!strcmp(prefix, "tutor8_2")))
        !          3285:        disable_err = 1;
        !          3286: 
        !          3287:     snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
        !          3288:     pattern[499] = 0;
        !          3289: 
        !          3290:     globbuf.gl_offs = 0;
        !          3291:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
        !          3292:     for (i = 0;i < globbuf.gl_pathc;i++) {
        !          3293:         testErrorsSize = 0;
        !          3294:        testErrors[0] = 0;
        !          3295:         instance = globbuf.gl_pathv[i];
        !          3296:        base2 = baseFilename(instance);
        !          3297:        len = strlen(base2);
        !          3298:        if ((len > 6) && (base2[len - 6] == '_')) {
        !          3299:            count = base2[len - 5];
        !          3300:            snprintf(result, 499, "result/relaxng/%s_%c",
        !          3301:                     prefix, count);
        !          3302:            result[499] = 0;
        !          3303:            snprintf(err, 499, "result/relaxng/%s_%c.err",
        !          3304:                     prefix, count);
        !          3305:            err[499] = 0;
        !          3306:        } else {
        !          3307:            fprintf(stderr, "don't know how to process %s\n", instance);
        !          3308:            continue;
        !          3309:        }
        !          3310:        reader = xmlReaderForFile(instance, NULL, options);
        !          3311:        if (reader == NULL) {
        !          3312:            fprintf(stderr, "Failed to build reder for %s\n", instance);
        !          3313:        }
        !          3314:        if (disable_err == 1)
        !          3315:            ret = streamProcessTest(instance, result, NULL, reader, filename);
        !          3316:        else
        !          3317:            ret = streamProcessTest(instance, result, err, reader, filename);
        !          3318:        xmlFreeTextReader(reader);
        !          3319:        if (ret != 0) {
        !          3320:            fprintf(stderr, "instance %s failed\n", instance);
        !          3321:            res = ret;
        !          3322:        }
        !          3323:     }
        !          3324:     globfree(&globbuf);
        !          3325: 
        !          3326:     return(res);
        !          3327: }
        !          3328: #endif /* READER */
        !          3329: 
        !          3330: #endif
        !          3331: 
        !          3332: #ifdef LIBXML_PATTERN_ENABLED
        !          3333: #ifdef LIBXML_READER_ENABLED
        !          3334: /************************************************************************
        !          3335:  *                                                                     *
        !          3336:  *                     Patterns tests                                  *
        !          3337:  *                                                                     *
        !          3338:  ************************************************************************/
        !          3339: static void patternNode(FILE *out, xmlTextReaderPtr reader,
        !          3340:                         const char *pattern, xmlPatternPtr patternc,
        !          3341:                        xmlStreamCtxtPtr patstream) {
        !          3342:     xmlChar *path = NULL;
        !          3343:     int match = -1;
        !          3344:     int type, empty;
        !          3345: 
        !          3346:     type = xmlTextReaderNodeType(reader);
        !          3347:     empty = xmlTextReaderIsEmptyElement(reader);
        !          3348: 
        !          3349:     if (type == XML_READER_TYPE_ELEMENT) {
        !          3350:        /* do the check only on element start */
        !          3351:        match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
        !          3352: 
        !          3353:        if (match) {
        !          3354:            path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
        !          3355:            fprintf(out, "Node %s matches pattern %s\n", path, pattern);
        !          3356:        }
        !          3357:     }
        !          3358:     if (patstream != NULL) {
        !          3359:        int ret;
        !          3360: 
        !          3361:        if (type == XML_READER_TYPE_ELEMENT) {
        !          3362:            ret = xmlStreamPush(patstream,
        !          3363:                                xmlTextReaderConstLocalName(reader),
        !          3364:                                xmlTextReaderConstNamespaceUri(reader));
        !          3365:            if (ret < 0) {
        !          3366:                fprintf(out, "xmlStreamPush() failure\n");
        !          3367:                xmlFreeStreamCtxt(patstream);
        !          3368:                patstream = NULL;
        !          3369:            } else if (ret != match) {
        !          3370:                if (path == NULL) {
        !          3371:                    path = xmlGetNodePath(
        !          3372:                                   xmlTextReaderCurrentNode(reader));
        !          3373:                }
        !          3374:                fprintf(out,
        !          3375:                        "xmlPatternMatch and xmlStreamPush disagree\n");
        !          3376:                fprintf(out,
        !          3377:                        "  pattern %s node %s\n",
        !          3378:                        pattern, path);
        !          3379:            }
        !          3380: 
        !          3381: 
        !          3382:        }
        !          3383:        if ((type == XML_READER_TYPE_END_ELEMENT) ||
        !          3384:            ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
        !          3385:            ret = xmlStreamPop(patstream);
        !          3386:            if (ret < 0) {
        !          3387:                fprintf(out, "xmlStreamPop() failure\n");
        !          3388:                xmlFreeStreamCtxt(patstream);
        !          3389:                patstream = NULL;
        !          3390:            }
        !          3391:        }
        !          3392:     }
        !          3393:     if (path != NULL)
        !          3394:        xmlFree(path);
        !          3395: }
        !          3396: 
        !          3397: /**
        !          3398:  * patternTest:
        !          3399:  * @filename: the schemas file
        !          3400:  * @result: the file with expected result
        !          3401:  * @err: the file with error messages
        !          3402:  *
        !          3403:  * Parse a set of files with streaming, applying an RNG schemas
        !          3404:  *
        !          3405:  * Returns 0 in case of success, an error code otherwise
        !          3406:  */
        !          3407: static int
        !          3408: patternTest(const char *filename,
        !          3409:             const char *resul ATTRIBUTE_UNUSED,
        !          3410:             const char *err ATTRIBUTE_UNUSED,
        !          3411:             int options) {
        !          3412:     xmlPatternPtr patternc = NULL;
        !          3413:     xmlStreamCtxtPtr patstream = NULL;
        !          3414:     FILE *o, *f;
        !          3415:     char str[1024];
        !          3416:     char xml[500];
        !          3417:     char result[500];
        !          3418:     int len, i;
        !          3419:     int ret = 0, res;
        !          3420:     char *temp;
        !          3421:     xmlTextReaderPtr reader;
        !          3422:     xmlDocPtr doc;
        !          3423: 
        !          3424:     len = strlen(filename);
        !          3425:     len -= 4;
        !          3426:     memcpy(xml, filename, len);
        !          3427:     xml[len] = 0;
        !          3428:     snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
        !          3429:     result[499] = 0;
        !          3430:     memcpy(xml + len, ".xml", 5);
        !          3431: 
        !          3432:     if (!checkTestFile(xml)) {
        !          3433:        fprintf(stderr, "Missing xml file %s\n", xml);
        !          3434:        return(-1);
        !          3435:     }
        !          3436:     if (!checkTestFile(result)) {
        !          3437:        fprintf(stderr, "Missing result file %s\n", result);
        !          3438:        return(-1);
        !          3439:     }
        !          3440:     f = fopen(filename, "rb");
        !          3441:     if (f == NULL) {
        !          3442:         fprintf(stderr, "Failed to open %s\n", filename);
        !          3443:        return(-1);
        !          3444:     }
        !          3445:     temp = resultFilename(filename, "", ".res");
        !          3446:     if (temp == NULL) {
        !          3447:         fprintf(stderr, "Out of memory\n");
        !          3448:         fatalError();
        !          3449:     }
        !          3450:     o = fopen(temp, "wb");
        !          3451:     if (o == NULL) {
        !          3452:        fprintf(stderr, "failed to open output file %s\n", temp);
        !          3453:        fclose(f);
        !          3454:         free(temp);
        !          3455:        return(-1);
        !          3456:     }
        !          3457:     while (1) {
        !          3458:        /*
        !          3459:         * read one line in string buffer.
        !          3460:         */
        !          3461:        if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
        !          3462:           break;
        !          3463: 
        !          3464:        /*
        !          3465:         * remove the ending spaces
        !          3466:         */
        !          3467:        i = strlen(str);
        !          3468:        while ((i > 0) &&
        !          3469:               ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
        !          3470:                (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
        !          3471:            i--;
        !          3472:            str[i] = 0;
        !          3473:        }
        !          3474:        doc = xmlReadFile(xml, NULL, options);
        !          3475:        if (doc == NULL) {
        !          3476:            fprintf(stderr, "Failed to parse %s\n", xml);
        !          3477:            ret = 1;
        !          3478:        } else {
        !          3479:            xmlNodePtr root;
        !          3480:            const xmlChar *namespaces[22];
        !          3481:            int j;
        !          3482:            xmlNsPtr ns;
        !          3483: 
        !          3484:            root = xmlDocGetRootElement(doc);
        !          3485:            for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
        !          3486:                namespaces[j++] = ns->href;
        !          3487:                namespaces[j++] = ns->prefix;
        !          3488:            }
        !          3489:            namespaces[j++] = NULL;
        !          3490:            namespaces[j] = NULL;
        !          3491: 
        !          3492:            patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
        !          3493:                                         0, &namespaces[0]);
        !          3494:            if (patternc == NULL) {
        !          3495:                testErrorHandler(NULL,
        !          3496:                        "Pattern %s failed to compile\n", str);
        !          3497:                xmlFreeDoc(doc);
        !          3498:                ret = 1;
        !          3499:                continue;
        !          3500:            }
        !          3501:            patstream = xmlPatternGetStreamCtxt(patternc);
        !          3502:            if (patstream != NULL) {
        !          3503:                ret = xmlStreamPush(patstream, NULL, NULL);
        !          3504:                if (ret < 0) {
        !          3505:                    fprintf(stderr, "xmlStreamPush() failure\n");
        !          3506:                    xmlFreeStreamCtxt(patstream);
        !          3507:                    patstream = NULL;
        !          3508:                }
        !          3509:            }
        !          3510:            nb_tests++;
        !          3511: 
        !          3512:            reader = xmlReaderWalker(doc);
        !          3513:            res = xmlTextReaderRead(reader);
        !          3514:            while (res == 1) {
        !          3515:                patternNode(o, reader, str, patternc, patstream);
        !          3516:                res = xmlTextReaderRead(reader);
        !          3517:            }
        !          3518:            if (res != 0) {
        !          3519:                fprintf(o, "%s : failed to parse\n", filename);
        !          3520:            }
        !          3521:            xmlFreeTextReader(reader);
        !          3522:            xmlFreeDoc(doc);
        !          3523:            xmlFreeStreamCtxt(patstream);
        !          3524:            patstream = NULL;
        !          3525:            xmlFreePattern(patternc);
        !          3526: 
        !          3527:        }
        !          3528:     }
        !          3529: 
        !          3530:     fclose(f);
        !          3531:     fclose(o);
        !          3532: 
        !          3533:     ret = compareFiles(temp, result);
        !          3534:     if (ret) {
        !          3535:        fprintf(stderr, "Result for %s failed\n", filename);
        !          3536:        ret = 1;
        !          3537:     }
        !          3538:     if (temp != NULL) {
        !          3539:         unlink(temp);
        !          3540:         free(temp);
        !          3541:     }
        !          3542:     return(ret);
        !          3543: }
        !          3544: #endif /* READER */
        !          3545: #endif /* PATTERN */
        !          3546: #ifdef LIBXML_C14N_ENABLED
        !          3547: /************************************************************************
        !          3548:  *                                                                     *
        !          3549:  *                     Canonicalization tests                          *
        !          3550:  *                                                                     *
        !          3551:  ************************************************************************/
        !          3552: static xmlXPathObjectPtr
        !          3553: load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
        !          3554:     xmlXPathObjectPtr xpath;
        !          3555:     xmlDocPtr doc;
        !          3556:     xmlChar *expr;
        !          3557:     xmlXPathContextPtr ctx;
        !          3558:     xmlNodePtr node;
        !          3559:     xmlNsPtr ns;
        !          3560: 
        !          3561:     /*
        !          3562:      * load XPath expr as a file
        !          3563:      */
        !          3564:     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
        !          3565:     xmlSubstituteEntitiesDefault(1);
        !          3566: 
        !          3567:     doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
        !          3568:     if (doc == NULL) {
        !          3569:        fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
        !          3570:        return(NULL);
        !          3571:     }
        !          3572: 
        !          3573:     /*
        !          3574:      * Check the document is of the right kind
        !          3575:      */
        !          3576:     if(xmlDocGetRootElement(doc) == NULL) {
        !          3577:         fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
        !          3578:        xmlFreeDoc(doc);
        !          3579:        return(NULL);
        !          3580:     }
        !          3581: 
        !          3582:     node = doc->children;
        !          3583:     while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
        !          3584:        node = node->next;
        !          3585:     }
        !          3586: 
        !          3587:     if(node == NULL) {
        !          3588:         fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
        !          3589:        xmlFreeDoc(doc);
        !          3590:        return(NULL);
        !          3591:     }
        !          3592: 
        !          3593:     expr = xmlNodeGetContent(node);
        !          3594:     if(expr == NULL) {
        !          3595:         fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
        !          3596:        xmlFreeDoc(doc);
        !          3597:        return(NULL);
        !          3598:     }
        !          3599: 
        !          3600:     ctx = xmlXPathNewContext(parent_doc);
        !          3601:     if(ctx == NULL) {
        !          3602:         fprintf(stderr,"Error: unable to create new context\n");
        !          3603:         xmlFree(expr);
        !          3604:         xmlFreeDoc(doc);
        !          3605:         return(NULL);
        !          3606:     }
        !          3607: 
        !          3608:     /*
        !          3609:      * Register namespaces
        !          3610:      */
        !          3611:     ns = node->nsDef;
        !          3612:     while(ns != NULL) {
        !          3613:        if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
        !          3614:            fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
        !          3615:     xmlFree(expr);
        !          3616:            xmlXPathFreeContext(ctx);
        !          3617:            xmlFreeDoc(doc);
        !          3618:            return(NULL);
        !          3619:        }
        !          3620:        ns = ns->next;
        !          3621:     }
        !          3622: 
        !          3623:     /*
        !          3624:      * Evaluate xpath
        !          3625:      */
        !          3626:     xpath = xmlXPathEvalExpression(expr, ctx);
        !          3627:     if(xpath == NULL) {
        !          3628:         fprintf(stderr,"Error: unable to evaluate xpath expression\n");
        !          3629: xmlFree(expr);
        !          3630:         xmlXPathFreeContext(ctx);
        !          3631:         xmlFreeDoc(doc);
        !          3632:         return(NULL);
        !          3633:     }
        !          3634: 
        !          3635:     /* print_xpath_nodes(xpath->nodesetval); */
        !          3636: 
        !          3637:     xmlFree(expr);
        !          3638:     xmlXPathFreeContext(ctx);
        !          3639:     xmlFreeDoc(doc);
        !          3640:     return(xpath);
        !          3641: }
        !          3642: 
        !          3643: /*
        !          3644:  * Macro used to grow the current buffer.
        !          3645:  */
        !          3646: #define xxx_growBufferReentrant() {                                            \
        !          3647:     buffer_size *= 2;                                                  \
        !          3648:     buffer = (xmlChar **)                                              \
        !          3649:        xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));     \
        !          3650:     if (buffer == NULL) {                                              \
        !          3651:        perror("realloc failed");                                       \
        !          3652:        return(NULL);                                                   \
        !          3653:     }                                                                  \
        !          3654: }
        !          3655: 
        !          3656: static xmlChar **
        !          3657: parse_list(xmlChar *str) {
        !          3658:     xmlChar **buffer;
        !          3659:     xmlChar **out = NULL;
        !          3660:     int buffer_size = 0;
        !          3661:     int len;
        !          3662: 
        !          3663:     if(str == NULL) {
        !          3664:        return(NULL);
        !          3665:     }
        !          3666: 
        !          3667:     len = xmlStrlen(str);
        !          3668:     if((str[0] == '\'') && (str[len - 1] == '\'')) {
        !          3669:        str[len - 1] = '\0';
        !          3670:        str++;
        !          3671:     }
        !          3672:     /*
        !          3673:      * allocate an translation buffer.
        !          3674:      */
        !          3675:     buffer_size = 1000;
        !          3676:     buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
        !          3677:     if (buffer == NULL) {
        !          3678:        perror("malloc failed");
        !          3679:        return(NULL);
        !          3680:     }
        !          3681:     out = buffer;
        !          3682: 
        !          3683:     while(*str != '\0') {
        !          3684:        if (out - buffer > buffer_size - 10) {
        !          3685:            int indx = out - buffer;
        !          3686: 
        !          3687:            xxx_growBufferReentrant();
        !          3688:            out = &buffer[indx];
        !          3689:        }
        !          3690:        (*out++) = str;
        !          3691:        while(*str != ',' && *str != '\0') ++str;
        !          3692:        if(*str == ',') *(str++) = '\0';
        !          3693:     }
        !          3694:     (*out) = NULL;
        !          3695:     return buffer;
        !          3696: }
        !          3697: 
        !          3698: static int
        !          3699: c14nRunTest(const char* xml_filename, int with_comments, int mode,
        !          3700:            const char* xpath_filename, const char *ns_filename,
        !          3701:            const char* result_file) {
        !          3702:     xmlDocPtr doc;
        !          3703:     xmlXPathObjectPtr xpath = NULL;
        !          3704:     xmlChar *result = NULL;
        !          3705:     int ret;
        !          3706:     xmlChar **inclusive_namespaces = NULL;
        !          3707:     const char *nslist = NULL;
        !          3708:     int nssize;
        !          3709: 
        !          3710: 
        !          3711:     /*
        !          3712:      * build an XML tree from a the file; we need to add default
        !          3713:      * attributes and resolve all character and entities references
        !          3714:      */
        !          3715:     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
        !          3716:     xmlSubstituteEntitiesDefault(1);
        !          3717: 
        !          3718:     doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
        !          3719:     if (doc == NULL) {
        !          3720:        fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
        !          3721:        return(-1);
        !          3722:     }
        !          3723: 
        !          3724:     /*
        !          3725:      * Check the document is of the right kind
        !          3726:      */
        !          3727:     if(xmlDocGetRootElement(doc) == NULL) {
        !          3728:         fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
        !          3729:        xmlFreeDoc(doc);
        !          3730:        return(-1);
        !          3731:     }
        !          3732: 
        !          3733:     /*
        !          3734:      * load xpath file if specified
        !          3735:      */
        !          3736:     if(xpath_filename) {
        !          3737:        xpath = load_xpath_expr(doc, xpath_filename);
        !          3738:        if(xpath == NULL) {
        !          3739:            fprintf(stderr,"Error: unable to evaluate xpath expression\n");
        !          3740:            xmlFreeDoc(doc);
        !          3741:            return(-1);
        !          3742:        }
        !          3743:     }
        !          3744: 
        !          3745:     if (ns_filename != NULL) {
        !          3746:         if (loadMem(ns_filename, &nslist, &nssize)) {
        !          3747:            fprintf(stderr,"Error: unable to evaluate xpath expression\n");
        !          3748:            if(xpath != NULL) xmlXPathFreeObject(xpath);
        !          3749:            xmlFreeDoc(doc);
        !          3750:            return(-1);
        !          3751:        }
        !          3752:         inclusive_namespaces = parse_list((xmlChar *) nslist);
        !          3753:     }
        !          3754: 
        !          3755:     /*
        !          3756:      * Canonical form
        !          3757:      */
        !          3758:     /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
        !          3759:     ret = xmlC14NDocDumpMemory(doc,
        !          3760:            (xpath) ? xpath->nodesetval : NULL,
        !          3761:            mode, inclusive_namespaces,
        !          3762:            with_comments, &result);
        !          3763:     if (ret >= 0) {
        !          3764:        if(result != NULL) {
        !          3765:            if (compareFileMem(result_file, (const char *) result, ret)) {
        !          3766:                fprintf(stderr, "Result mismatch for %s\n", xml_filename);
        !          3767:                fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
        !          3768:                ret = -1;
        !          3769:            }
        !          3770:        }
        !          3771:     } else {
        !          3772:        fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
        !          3773:        ret = -1;
        !          3774:     }
        !          3775: 
        !          3776:     /*
        !          3777:      * Cleanup
        !          3778:      */
        !          3779:     if (result != NULL) xmlFree(result);
        !          3780:     if(xpath != NULL) xmlXPathFreeObject(xpath);
        !          3781:     if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
        !          3782:     if (nslist != NULL) free((char *) nslist);
        !          3783:     xmlFreeDoc(doc);
        !          3784: 
        !          3785:     return(ret);
        !          3786: }
        !          3787: 
        !          3788: static int
        !          3789: c14nCommonTest(const char *filename, int with_comments, int mode,
        !          3790:                const char *subdir) {
        !          3791:     char buf[500];
        !          3792:     char prefix[500];
        !          3793:     const char *base;
        !          3794:     int len;
        !          3795:     char *result = NULL;
        !          3796:     char *xpath = NULL;
        !          3797:     char *ns = NULL;
        !          3798:     int ret = 0;
        !          3799: 
        !          3800:     base = baseFilename(filename);
        !          3801:     len = strlen(base);
        !          3802:     len -= 4;
        !          3803:     memcpy(prefix, base, len);
        !          3804:     prefix[len] = 0;
        !          3805: 
        !          3806:     snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
        !          3807:     if (!checkTestFile(buf)) {
        !          3808:         fprintf(stderr, "Missing result file %s", buf);
        !          3809:        return(-1);
        !          3810:     }
        !          3811:     result = strdup(buf);
        !          3812:     snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
        !          3813:     if (checkTestFile(buf)) {
        !          3814:        xpath = strdup(buf);
        !          3815:     }
        !          3816:     snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
        !          3817:     if (checkTestFile(buf)) {
        !          3818:        ns = strdup(buf);
        !          3819:     }
        !          3820: 
        !          3821:     nb_tests++;
        !          3822:     if (c14nRunTest(filename, with_comments, mode,
        !          3823:                     xpath, ns, result) < 0)
        !          3824:         ret = 1;
        !          3825: 
        !          3826:     if (result != NULL) free(result);
        !          3827:     if (xpath != NULL) free(xpath);
        !          3828:     if (ns != NULL) free(ns);
        !          3829:     return(ret);
        !          3830: }
        !          3831: 
        !          3832: static int
        !          3833: c14nWithCommentTest(const char *filename,
        !          3834:                     const char *resul ATTRIBUTE_UNUSED,
        !          3835:                    const char *err ATTRIBUTE_UNUSED,
        !          3836:                    int options ATTRIBUTE_UNUSED) {
        !          3837:     return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
        !          3838: }
        !          3839: static int
        !          3840: c14nWithoutCommentTest(const char *filename,
        !          3841:                     const char *resul ATTRIBUTE_UNUSED,
        !          3842:                    const char *err ATTRIBUTE_UNUSED,
        !          3843:                    int options ATTRIBUTE_UNUSED) {
        !          3844:     return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
        !          3845: }
        !          3846: static int
        !          3847: c14nExcWithoutCommentTest(const char *filename,
        !          3848:                     const char *resul ATTRIBUTE_UNUSED,
        !          3849:                    const char *err ATTRIBUTE_UNUSED,
        !          3850:                    int options ATTRIBUTE_UNUSED) {
        !          3851:     return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
        !          3852: }
        !          3853: static int
        !          3854: c14n11WithoutCommentTest(const char *filename,
        !          3855:                     const char *resul ATTRIBUTE_UNUSED,
        !          3856:                    const char *err ATTRIBUTE_UNUSED,
        !          3857:                    int options ATTRIBUTE_UNUSED) {
        !          3858:     return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
        !          3859: }
        !          3860: #endif
        !          3861: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
        !          3862: /************************************************************************
        !          3863:  *                                                                     *
        !          3864:  *                     Catalog and threads test                        *
        !          3865:  *                                                                     *
        !          3866:  ************************************************************************/
        !          3867: 
        !          3868: /*
        !          3869:  * mostly a cut and paste from testThreads.c
        !          3870:  */
        !          3871: #define        MAX_ARGC        20
        !          3872: 
        !          3873: static const char *catalog = "test/threads/complex.xml";
        !          3874: static const char *testfiles[] = {
        !          3875:     "test/threads/abc.xml",
        !          3876:     "test/threads/acb.xml",
        !          3877:     "test/threads/bac.xml",
        !          3878:     "test/threads/bca.xml",
        !          3879:     "test/threads/cab.xml",
        !          3880:     "test/threads/cba.xml",
        !          3881:     "test/threads/invalid.xml",
        !          3882: };
        !          3883: 
        !          3884: static const char *Okay = "OK";
        !          3885: static const char *Failed = "Failed";
        !          3886: 
        !          3887: #ifndef xmlDoValidityCheckingDefaultValue
        !          3888: #error xmlDoValidityCheckingDefaultValue is not a macro
        !          3889: #endif
        !          3890: #ifndef xmlGenericErrorContext
        !          3891: #error xmlGenericErrorContext is not a macro
        !          3892: #endif
        !          3893: 
        !          3894: static void *
        !          3895: thread_specific_data(void *private_data)
        !          3896: {
        !          3897:     xmlDocPtr myDoc;
        !          3898:     const char *filename = (const char *) private_data;
        !          3899:     int okay = 1;
        !          3900: 
        !          3901:     if (!strcmp(filename, "test/threads/invalid.xml")) {
        !          3902:         xmlDoValidityCheckingDefaultValue = 0;
        !          3903:         xmlGenericErrorContext = stdout;
        !          3904:     } else {
        !          3905:         xmlDoValidityCheckingDefaultValue = 1;
        !          3906:         xmlGenericErrorContext = stderr;
        !          3907:     }
        !          3908:     myDoc = xmlParseFile(filename);
        !          3909:     if (myDoc) {
        !          3910:         xmlFreeDoc(myDoc);
        !          3911:     } else {
        !          3912:         printf("parse failed\n");
        !          3913:         okay = 0;
        !          3914:     }
        !          3915:     if (!strcmp(filename, "test/threads/invalid.xml")) {
        !          3916:         if (xmlDoValidityCheckingDefaultValue != 0) {
        !          3917:             printf("ValidityCheckingDefaultValue override failed\n");
        !          3918:             okay = 0;
        !          3919:         }
        !          3920:         if (xmlGenericErrorContext != stdout) {
        !          3921:             printf("xmlGenericErrorContext override failed\n");
        !          3922:             okay = 0;
        !          3923:         }
        !          3924:     } else {
        !          3925:         if (xmlDoValidityCheckingDefaultValue != 1) {
        !          3926:             printf("ValidityCheckingDefaultValue override failed\n");
        !          3927:             okay = 0;
        !          3928:         }
        !          3929:         if (xmlGenericErrorContext != stderr) {
        !          3930:             printf("xmlGenericErrorContext override failed\n");
        !          3931:             okay = 0;
        !          3932:         }
        !          3933:     }
        !          3934:     if (okay == 0)
        !          3935:         return ((void *) Failed);
        !          3936:     return ((void *) Okay);
        !          3937: }
        !          3938: 
        !          3939: #if defined(linux) || defined(__sun) || defined(__APPLE_CC__)
        !          3940: 
        !          3941: #include <pthread.h>
        !          3942: 
        !          3943: static pthread_t tid[MAX_ARGC];
        !          3944: 
        !          3945: static int
        !          3946: testThread(void)
        !          3947: {
        !          3948:     unsigned int i, repeat;
        !          3949:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
        !          3950:     void *results[MAX_ARGC];
        !          3951:     int ret;
        !          3952:     int res = 0;
        !          3953: 
        !          3954:     xmlInitParser();
        !          3955: 
        !          3956:     for (repeat = 0; repeat < 500; repeat++) {
        !          3957:         xmlLoadCatalog(catalog);
        !          3958:         nb_tests++;
        !          3959: 
        !          3960:         for (i = 0; i < num_threads; i++) {
        !          3961:             results[i] = NULL;
        !          3962:             tid[i] = (pthread_t) - 1;
        !          3963:         }
        !          3964: 
        !          3965:         for (i = 0; i < num_threads; i++) {
        !          3966:             ret = pthread_create(&tid[i], 0, thread_specific_data,
        !          3967:                                  (void *) testfiles[i]);
        !          3968:             if (ret != 0) {
        !          3969:                 fprintf(stderr, "pthread_create failed\n");
        !          3970:                 return (1);
        !          3971:             }
        !          3972:         }
        !          3973:         for (i = 0; i < num_threads; i++) {
        !          3974:             ret = pthread_join(tid[i], &results[i]);
        !          3975:             if (ret != 0) {
        !          3976:                 fprintf(stderr, "pthread_join failed\n");
        !          3977:                 return (1);
        !          3978:             }
        !          3979:         }
        !          3980: 
        !          3981:         xmlCatalogCleanup();
        !          3982:         for (i = 0; i < num_threads; i++)
        !          3983:             if (results[i] != (void *) Okay) {
        !          3984:                 fprintf(stderr, "Thread %d handling %s failed\n",
        !          3985:                         i, testfiles[i]);
        !          3986:                 res = 1;
        !          3987:             }
        !          3988:     }
        !          3989:     return (res);
        !          3990: }
        !          3991: 
        !          3992: #elif defined WIN32
        !          3993: #include <windows.h>
        !          3994: #include <string.h>
        !          3995: 
        !          3996: #define TEST_REPEAT_COUNT 500
        !          3997: 
        !          3998: static HANDLE tid[MAX_ARGC];
        !          3999: 
        !          4000: static DWORD WINAPI
        !          4001: win32_thread_specific_data(void *private_data)
        !          4002: {
        !          4003:     return((DWORD) thread_specific_data(private_data));
        !          4004: }
        !          4005: 
        !          4006: static int
        !          4007: testThread(void)
        !          4008: {
        !          4009:     unsigned int i, repeat;
        !          4010:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
        !          4011:     DWORD results[MAX_ARGC];
        !          4012:     BOOL ret;
        !          4013:     int res = 0;
        !          4014: 
        !          4015:     xmlInitParser();
        !          4016:     for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
        !          4017:         xmlLoadCatalog(catalog);
        !          4018:         nb_tests++;
        !          4019: 
        !          4020:         for (i = 0; i < num_threads; i++) {
        !          4021:             results[i] = 0;
        !          4022:             tid[i] = (HANDLE) - 1;
        !          4023:         }
        !          4024: 
        !          4025:         for (i = 0; i < num_threads; i++) {
        !          4026:             DWORD useless;
        !          4027: 
        !          4028:             tid[i] = CreateThread(NULL, 0,
        !          4029:                                   win32_thread_specific_data,
        !          4030:                                  (void *) testfiles[i], 0,
        !          4031:                                   &useless);
        !          4032:             if (tid[i] == NULL) {
        !          4033:                 fprintf(stderr, "CreateThread failed\n");
        !          4034:                 return(1);
        !          4035:             }
        !          4036:         }
        !          4037: 
        !          4038:         if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
        !          4039:             WAIT_FAILED) {
        !          4040:             fprintf(stderr, "WaitForMultipleObjects failed\n");
        !          4041:            return(1);
        !          4042:        }
        !          4043: 
        !          4044:         for (i = 0; i < num_threads; i++) {
        !          4045:             ret = GetExitCodeThread(tid[i], &results[i]);
        !          4046:             if (ret == 0) {
        !          4047:                 fprintf(stderr, "GetExitCodeThread failed\n");
        !          4048:                 return(1);
        !          4049:             }
        !          4050:             CloseHandle(tid[i]);
        !          4051:         }
        !          4052: 
        !          4053:         xmlCatalogCleanup();
        !          4054:         for (i = 0; i < num_threads; i++) {
        !          4055:             if (results[i] != (DWORD) Okay) {
        !          4056:                 fprintf(stderr, "Thread %d handling %s failed\n",
        !          4057:                        i, testfiles[i]);
        !          4058:                res = 1;
        !          4059:            }
        !          4060:         }
        !          4061:     }
        !          4062: 
        !          4063:     return (res);
        !          4064: }
        !          4065: 
        !          4066: #elif defined __BEOS__
        !          4067: #include <OS.h>
        !          4068: 
        !          4069: static thread_id tid[MAX_ARGC];
        !          4070: 
        !          4071: static int
        !          4072: testThread(void)
        !          4073: {
        !          4074:     unsigned int i, repeat;
        !          4075:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
        !          4076:     void *results[MAX_ARGC];
        !          4077:     status_t ret;
        !          4078:     int res = 0;
        !          4079: 
        !          4080:     xmlInitParser();
        !          4081:     for (repeat = 0; repeat < 500; repeat++) {
        !          4082:         xmlLoadCatalog(catalog);
        !          4083:         for (i = 0; i < num_threads; i++) {
        !          4084:             results[i] = NULL;
        !          4085:             tid[i] = (thread_id) - 1;
        !          4086:         }
        !          4087:         for (i = 0; i < num_threads; i++) {
        !          4088:             tid[i] =
        !          4089:                 spawn_thread(thread_specific_data, "xmlTestThread",
        !          4090:                              B_NORMAL_PRIORITY, (void *) testfiles[i]);
        !          4091:             if (tid[i] < B_OK) {
        !          4092:                 fprintf(stderr, "beos_thread_create failed\n");
        !          4093:                 return (1);
        !          4094:             }
        !          4095:             printf("beos_thread_create %d -> %d\n", i, tid[i]);
        !          4096:         }
        !          4097:         for (i = 0; i < num_threads; i++) {
        !          4098:             ret = wait_for_thread(tid[i], &results[i]);
        !          4099:             printf("beos_thread_wait %d -> %d\n", i, ret);
        !          4100:             if (ret != B_OK) {
        !          4101:                 fprintf(stderr, "beos_thread_wait failed\n");
        !          4102:                 return (1);
        !          4103:             }
        !          4104:         }
        !          4105: 
        !          4106:         xmlCatalogCleanup();
        !          4107:         ret = B_OK;
        !          4108:         for (i = 0; i < num_threads; i++)
        !          4109:             if (results[i] != (void *) Okay) {
        !          4110:                 printf("Thread %d handling %s failed\n", i, testfiles[i]);
        !          4111:                 ret = B_ERROR;
        !          4112:             }
        !          4113:     }
        !          4114:     if (ret != B_OK)
        !          4115:         return(1);
        !          4116:     return (0);
        !          4117: }
        !          4118: #else
        !          4119: static int
        !          4120: testThread(void)
        !          4121: {
        !          4122:     fprintf(stderr,
        !          4123:             "Specific platform thread support not detected\n");
        !          4124:     return (-1);
        !          4125: }
        !          4126: #endif
        !          4127: static int
        !          4128: threadsTest(const char *filename ATTRIBUTE_UNUSED,
        !          4129:            const char *resul ATTRIBUTE_UNUSED,
        !          4130:            const char *err ATTRIBUTE_UNUSED,
        !          4131:            int options ATTRIBUTE_UNUSED) {
        !          4132:     return(testThread());
        !          4133: }
        !          4134: #endif
        !          4135: /************************************************************************
        !          4136:  *                                                                     *
        !          4137:  *                     Tests Descriptions                              *
        !          4138:  *                                                                     *
        !          4139:  ************************************************************************/
        !          4140: 
        !          4141: static
        !          4142: testDesc testDescriptions[] = {
        !          4143:     { "XML regression tests" ,
        !          4144:       oldParseTest, "./test/*", "result/", "", NULL,
        !          4145:       0 },
        !          4146:     { "XML regression tests on memory" ,
        !          4147:       memParseTest, "./test/*", "result/", "", NULL,
        !          4148:       0 },
        !          4149:     { "XML entity subst regression tests" ,
        !          4150:       noentParseTest, "./test/*", "result/noent/", "", NULL,
        !          4151:       XML_PARSE_NOENT },
        !          4152:     { "XML Namespaces regression tests",
        !          4153:       errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
        !          4154:       0 },
        !          4155:     { "Error cases regression tests",
        !          4156:       errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
        !          4157:       0 },
        !          4158: #ifdef LIBXML_READER_ENABLED
        !          4159:     { "Error cases stream regression tests",
        !          4160:       streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
        !          4161:       0 },
        !          4162:     { "Reader regression tests",
        !          4163:       streamParseTest, "./test/*", "result/", ".rdr", NULL,
        !          4164:       0 },
        !          4165:     { "Reader entities substitution regression tests",
        !          4166:       streamParseTest, "./test/*", "result/", ".rde", NULL,
        !          4167:       XML_PARSE_NOENT },
        !          4168:     { "Reader on memory regression tests",
        !          4169:       streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
        !          4170:       0 },
        !          4171:     { "Walker regression tests",
        !          4172:       walkerParseTest, "./test/*", "result/", ".rdr", NULL,
        !          4173:       0 },
        !          4174: #endif
        !          4175: #ifdef LIBXML_SAX1_ENABLED
        !          4176:     { "SAX1 callbacks regression tests" ,
        !          4177:       saxParseTest, "./test/*", "result/", ".sax", NULL,
        !          4178:       XML_PARSE_SAX1 },
        !          4179:     { "SAX2 callbacks regression tests" ,
        !          4180:       saxParseTest, "./test/*", "result/", ".sax2", NULL,
        !          4181:       0 },
        !          4182: #endif
        !          4183: #ifdef LIBXML_PUSH_ENABLED
        !          4184:     { "XML push regression tests" ,
        !          4185:       pushParseTest, "./test/*", "result/", "", NULL,
        !          4186:       0 },
        !          4187: #endif
        !          4188: #ifdef LIBXML_HTML_ENABLED
        !          4189:     { "HTML regression tests" ,
        !          4190:       errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
        !          4191:       XML_PARSE_HTML },
        !          4192: #ifdef LIBXML_PUSH_ENABLED
        !          4193:     { "Push HTML regression tests" ,
        !          4194:       pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
        !          4195:       XML_PARSE_HTML },
        !          4196: #endif
        !          4197: #ifdef LIBXML_SAX1_ENABLED
        !          4198:     { "HTML SAX regression tests" ,
        !          4199:       saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
        !          4200:       XML_PARSE_HTML },
        !          4201: #endif
        !          4202: #endif
        !          4203: #ifdef LIBXML_VALID_ENABLED
        !          4204:     { "Valid documents regression tests" ,
        !          4205:       errParseTest, "./test/VCM/*", NULL, NULL, NULL,
        !          4206:       XML_PARSE_DTDVALID },
        !          4207:     { "Validity checking regression tests" ,
        !          4208:       errParseTest, "./test/VC/*", "result/VC/", NULL, "",
        !          4209:       XML_PARSE_DTDVALID },
        !          4210:     { "General documents valid regression tests" ,
        !          4211:       errParseTest, "./test/valid/*", "result/valid/", "", ".err",
        !          4212:       XML_PARSE_DTDVALID },
        !          4213: #endif
        !          4214: #ifdef LIBXML_XINCLUDE_ENABLED
        !          4215:     { "XInclude regression tests" ,
        !          4216:       errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
        !          4217:       /* Ignore errors at this point ".err", */
        !          4218:       XML_PARSE_XINCLUDE },
        !          4219: #ifdef LIBXML_READER_ENABLED
        !          4220:     { "XInclude xmlReader regression tests",
        !          4221:       streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
        !          4222:       /* Ignore errors at this point ".err", */
        !          4223:       NULL, XML_PARSE_XINCLUDE },
        !          4224: #endif
        !          4225:     { "XInclude regression tests stripping include nodes" ,
        !          4226:       errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
        !          4227:       /* Ignore errors at this point ".err", */
        !          4228:       XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
        !          4229: #ifdef LIBXML_READER_ENABLED
        !          4230:     { "XInclude xmlReader regression tests stripping include nodes",
        !          4231:       streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
        !          4232:       /* Ignore errors at this point ".err", */
        !          4233:       NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
        !          4234: #endif
        !          4235: #endif
        !          4236: #ifdef LIBXML_XPATH_ENABLED
        !          4237: #ifdef LIBXML_DEBUG_ENABLED
        !          4238:     { "XPath expressions regression tests" ,
        !          4239:       xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
        !          4240:       0 },
        !          4241:     { "XPath document queries regression tests" ,
        !          4242:       xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
        !          4243:       0 },
        !          4244: #ifdef LIBXML_XPTR_ENABLED
        !          4245:     { "XPointer document queries regression tests" ,
        !          4246:       xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
        !          4247:       0 },
        !          4248: #endif
        !          4249:     { "xml:id regression tests" ,
        !          4250:       xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
        !          4251:       0 },
        !          4252: #endif
        !          4253: #endif
        !          4254:     { "URI parsing tests" ,
        !          4255:       uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
        !          4256:       0 },
        !          4257:     { "URI base composition tests" ,
        !          4258:       uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
        !          4259:       0 },
        !          4260:     { "Path URI conversion tests" ,
        !          4261:       uriPathTest, NULL, NULL, NULL, NULL,
        !          4262:       0 },
        !          4263: #ifdef LIBXML_SCHEMAS_ENABLED
        !          4264:     { "Schemas regression tests" ,
        !          4265:       schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
        !          4266:       0 },
        !          4267:     { "Relax-NG regression tests" ,
        !          4268:       rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
        !          4269:       XML_PARSE_DTDATTR | XML_PARSE_NOENT },
        !          4270: #ifdef LIBXML_READER_ENABLED
        !          4271:     { "Relax-NG streaming regression tests" ,
        !          4272:       rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
        !          4273:       XML_PARSE_DTDATTR | XML_PARSE_NOENT },
        !          4274: #endif
        !          4275: #endif
        !          4276: #ifdef LIBXML_PATTERN_ENABLED
        !          4277: #ifdef LIBXML_READER_ENABLED
        !          4278:     { "Pattern regression tests" ,
        !          4279:       patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
        !          4280:       0 },
        !          4281: #endif
        !          4282: #endif
        !          4283: #ifdef LIBXML_C14N_ENABLED
        !          4284:     { "C14N with comments regression tests" ,
        !          4285:       c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
        !          4286:       0 },
        !          4287:     { "C14N without comments regression tests" ,
        !          4288:       c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
        !          4289:       0 },
        !          4290:     { "C14N exclusive without comments regression tests" ,
        !          4291:       c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
        !          4292:       0 },
        !          4293:     { "C14N 1.1 without comments regression tests" ,
        !          4294:       c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
        !          4295:       0 },
        !          4296: #endif
        !          4297: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
        !          4298:     { "Catalog and Threads regression tests" ,
        !          4299:       threadsTest, NULL, NULL, NULL, NULL,
        !          4300:       0 },
        !          4301: #endif
        !          4302:     {NULL, NULL, NULL, NULL, NULL, NULL, 0}
        !          4303: };
        !          4304: 
        !          4305: /************************************************************************
        !          4306:  *                                                                     *
        !          4307:  *             The main code driving the tests                         *
        !          4308:  *                                                                     *
        !          4309:  ************************************************************************/
        !          4310: 
        !          4311: static int
        !          4312: launchTests(testDescPtr tst) {
        !          4313:     int res = 0, err = 0;
        !          4314:     size_t i;
        !          4315:     char *result;
        !          4316:     char *error;
        !          4317:     int mem;
        !          4318: 
        !          4319:     if (tst == NULL) return(-1);
        !          4320:     if (tst->in != NULL) {
        !          4321:        glob_t globbuf;
        !          4322: 
        !          4323:        globbuf.gl_offs = 0;
        !          4324:        glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
        !          4325:        for (i = 0;i < globbuf.gl_pathc;i++) {
        !          4326:            if (!checkTestFile(globbuf.gl_pathv[i]))
        !          4327:                continue;
        !          4328:            if (tst->suffix != NULL) {
        !          4329:                result = resultFilename(globbuf.gl_pathv[i], tst->out,
        !          4330:                                        tst->suffix);
        !          4331:                if (result == NULL) {
        !          4332:                    fprintf(stderr, "Out of memory !\n");
        !          4333:                    fatalError();
        !          4334:                }
        !          4335:            } else {
        !          4336:                result = NULL;
        !          4337:            }
        !          4338:            if (tst->err != NULL) {
        !          4339:                error = resultFilename(globbuf.gl_pathv[i], tst->out,
        !          4340:                                        tst->err);
        !          4341:                if (error == NULL) {
        !          4342:                    fprintf(stderr, "Out of memory !\n");
        !          4343:                    fatalError();
        !          4344:                }
        !          4345:            } else {
        !          4346:                error = NULL;
        !          4347:            }
        !          4348:            if ((result) &&(!checkTestFile(result))) {
        !          4349:                fprintf(stderr, "Missing result file %s\n", result);
        !          4350:            } else if ((error) &&(!checkTestFile(error))) {
        !          4351:                fprintf(stderr, "Missing error file %s\n", error);
        !          4352:            } else {
        !          4353:                mem = xmlMemUsed();
        !          4354:                extraMemoryFromResolver = 0;
        !          4355:                testErrorsSize = 0;
        !          4356:                testErrors[0] = 0;
        !          4357:                res = tst->func(globbuf.gl_pathv[i], result, error,
        !          4358:                                tst->options | XML_PARSE_COMPACT);
        !          4359:                xmlResetLastError();
        !          4360:                if (res != 0) {
        !          4361:                    fprintf(stderr, "File %s generated an error\n",
        !          4362:                            globbuf.gl_pathv[i]);
        !          4363:                    nb_errors++;
        !          4364:                    err++;
        !          4365:                }
        !          4366:                else if (xmlMemUsed() != mem) {
        !          4367:                    if ((xmlMemUsed() != mem) &&
        !          4368:                        (extraMemoryFromResolver == 0)) {
        !          4369:                        fprintf(stderr, "File %s leaked %d bytes\n",
        !          4370:                                globbuf.gl_pathv[i], xmlMemUsed() - mem);
        !          4371:                        nb_leaks++;
        !          4372:                        err++;
        !          4373:                    }
        !          4374:                }
        !          4375:                testErrorsSize = 0;
        !          4376:            }
        !          4377:            if (result)
        !          4378:                free(result);
        !          4379:            if (error)
        !          4380:                free(error);
        !          4381:        }
        !          4382:        globfree(&globbuf);
        !          4383:     } else {
        !          4384:         testErrorsSize = 0;
        !          4385:        testErrors[0] = 0;
        !          4386:        extraMemoryFromResolver = 0;
        !          4387:         res = tst->func(NULL, NULL, NULL, tst->options);
        !          4388:        if (res != 0) {
        !          4389:            nb_errors++;
        !          4390:            err++;
        !          4391:        }
        !          4392:     }
        !          4393:     return(err);
        !          4394: }
        !          4395: 
        !          4396: static int verbose = 0;
        !          4397: static int tests_quiet = 0;
        !          4398: 
        !          4399: static int
        !          4400: runtest(int i) {
        !          4401:     int ret = 0, res;
        !          4402:     int old_errors, old_tests, old_leaks;
        !          4403: 
        !          4404:     old_errors = nb_errors;
        !          4405:     old_tests = nb_tests;
        !          4406:     old_leaks = nb_leaks;
        !          4407:     if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
        !          4408:        printf("## %s\n", testDescriptions[i].desc);
        !          4409:     res = launchTests(&testDescriptions[i]);
        !          4410:     if (res != 0)
        !          4411:        ret++;
        !          4412:     if (verbose) {
        !          4413:        if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
        !          4414:            printf("Ran %d tests, no errors\n", nb_tests - old_tests);
        !          4415:        else
        !          4416:            printf("Ran %d tests, %d errors, %d leaks\n",
        !          4417:                   nb_tests - old_tests,
        !          4418:                   nb_errors - old_errors,
        !          4419:                   nb_leaks - old_leaks);
        !          4420:     }
        !          4421:     return(ret);
        !          4422: }
        !          4423: 
        !          4424: int
        !          4425: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
        !          4426:     int i, a, ret = 0;
        !          4427:     int subset = 0;
        !          4428: 
        !          4429:     initializeLibxml2();
        !          4430: 
        !          4431:     for (a = 1; a < argc;a++) {
        !          4432:         if (!strcmp(argv[a], "-v"))
        !          4433:            verbose = 1;
        !          4434:         else if (!strcmp(argv[a], "-quiet"))
        !          4435:            tests_quiet = 1;
        !          4436:        else {
        !          4437:            for (i = 0; testDescriptions[i].func != NULL; i++) {
        !          4438:                if (strstr(testDescriptions[i].desc, argv[a])) {
        !          4439:                    ret += runtest(i);
        !          4440:                    subset++;
        !          4441:                }
        !          4442:            }
        !          4443:        }
        !          4444:     }
        !          4445:     if (subset == 0) {
        !          4446:        for (i = 0; testDescriptions[i].func != NULL; i++) {
        !          4447:            ret += runtest(i);
        !          4448:        }
        !          4449:     }
        !          4450:     if ((nb_errors == 0) && (nb_leaks == 0)) {
        !          4451:         ret = 0;
        !          4452:        printf("Total %d tests, no errors\n",
        !          4453:               nb_tests);
        !          4454:     } else {
        !          4455:         ret = 1;
        !          4456:        printf("Total %d tests, %d errors, %d leaks\n",
        !          4457:               nb_tests, nb_errors, nb_leaks);
        !          4458:     }
        !          4459:     xmlCleanupParser();
        !          4460:     xmlMemoryDump();
        !          4461: 
        !          4462:     return(ret);
        !          4463: }
        !          4464: 
        !          4465: #else /* ! LIBXML_OUTPUT_ENABLED */
        !          4466: int
        !          4467: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
        !          4468:     fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
        !          4469:     return(1);
        !          4470: }
        !          4471: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>