1
/*
2
 * xmllint.c : a small tester program for XML input.
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * daniel@veillard.com
7
 */
8
9
#include "libxml.h"
10
11
#include <string.h>
12
#include <stdarg.h>
13
#include <assert.h>
14
15
#if defined (_WIN32) && !defined(__CYGWIN__)
16
#if defined (_MSC_VER) || defined(__BORLANDC__)
17
#include <winsock2.h>
18
#pragma comment(lib, "ws2_32.lib")
19
#define gettimeofday(p1,p2)
20
#endif /* _MSC_VER */
21
#endif /* _WIN32 */
22
23
#ifdef HAVE_SYS_TIME_H
24
#include <sys/time.h>
25
#endif
26
#ifdef HAVE_TIME_H
27
#include <time.h>
28
#endif
29
30
#ifdef __MINGW32__
31
#define _WINSOCKAPI_
32
#include <wsockcompat.h>
33
#include <winsock2.h>
34
#undef XML_SOCKLEN_T
35
#define XML_SOCKLEN_T unsigned int
36
#endif
37
38
#ifdef HAVE_SYS_TIMEB_H
39
#include <sys/timeb.h>
40
#endif
41
42
#ifdef HAVE_SYS_TYPES_H
43
#include <sys/types.h>
44
#endif
45
#ifdef HAVE_SYS_STAT_H
46
#include <sys/stat.h>
47
#endif
48
#ifdef HAVE_FCNTL_H
49
#include <fcntl.h>
50
#endif
51
#ifdef HAVE_UNISTD_H
52
#include <unistd.h>
53
#endif
54
#ifdef HAVE_SYS_MMAN_H
55
#include <sys/mman.h>
56
/* seems needed for Solaris */
57
#ifndef MAP_FAILED
58
#define MAP_FAILED ((void *) -1)
59
#endif
60
#endif
61
#ifdef HAVE_STDLIB_H
62
#include <stdlib.h>
63
#endif
64
#ifdef HAVE_LIBREADLINE
65
#include <readline/readline.h>
66
#ifdef HAVE_LIBHISTORY
67
#include <readline/history.h>
68
#endif
69
#endif
70
71
#include <libxml/xmlmemory.h>
72
#include <libxml/parser.h>
73
#include <libxml/parserInternals.h>
74
#include <libxml/HTMLparser.h>
75
#include <libxml/HTMLtree.h>
76
#include <libxml/tree.h>
77
#include <libxml/xpath.h>
78
#include <libxml/debugXML.h>
79
#include <libxml/xmlerror.h>
80
#ifdef LIBXML_XINCLUDE_ENABLED
81
#include <libxml/xinclude.h>
82
#endif
83
#ifdef LIBXML_CATALOG_ENABLED
84
#include <libxml/catalog.h>
85
#endif
86
#include <libxml/globals.h>
87
#include <libxml/xmlreader.h>
88
#ifdef LIBXML_SCHEMATRON_ENABLED
89
#include <libxml/schematron.h>
90
#endif
91
#ifdef LIBXML_SCHEMAS_ENABLED
92
#include <libxml/relaxng.h>
93
#include <libxml/xmlschemas.h>
94
#endif
95
#ifdef LIBXML_PATTERN_ENABLED
96
#include <libxml/pattern.h>
97
#endif
98
#ifdef LIBXML_C14N_ENABLED
99
#include <libxml/c14n.h>
100
#endif
101
#ifdef LIBXML_OUTPUT_ENABLED
102
#include <libxml/xmlsave.h>
103
#endif
104
105
#ifndef XML_XML_DEFAULT_CATALOG
106
#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
107
#endif
108
109
typedef enum {
110
    XMLLINT_RETURN_OK = 0,	/* No error */
111
    XMLLINT_ERR_UNCLASS,	/* Unclassified */
112
    XMLLINT_ERR_DTD,		/* Error in DTD */
113
    XMLLINT_ERR_VALID,		/* Validation error */
114
    XMLLINT_ERR_RDFILE,		/* CtxtReadFile error */
115
    XMLLINT_ERR_SCHEMACOMP,	/* Schema compilation */
116
    XMLLINT_ERR_OUT,		/* Error writing output */
117
    XMLLINT_ERR_SCHEMAPAT,	/* Error in schema pattern */
118
    XMLLINT_ERR_RDREGIS,	/* Error in Reader registration */
119
    XMLLINT_ERR_MEM		/* Out of memory error */
120
} xmllintReturnCode;
121
#ifdef LIBXML_DEBUG_ENABLED
122
static int shell = 0;
123
static int debugent = 0;
124
#endif
125
static int debug = 0;
126
static int maxmem = 0;
127
#ifdef LIBXML_TREE_ENABLED
128
static int copy = 0;
129
#endif /* LIBXML_TREE_ENABLED */
130
static int recovery = 0;
131
static int noent = 0;
132
static int noblanks = 0;
133
static int noout = 0;
134
static int nowrap = 0;
135
#ifdef LIBXML_OUTPUT_ENABLED
136
static int format = 0;
137
static const char *output = NULL;
138
static int compress = 0;
139
static int oldout = 0;
140
#endif /* LIBXML_OUTPUT_ENABLED */
141
#ifdef LIBXML_VALID_ENABLED
142
static int valid = 0;
143
static int postvalid = 0;
144
static char * dtdvalid = NULL;
145
static char * dtdvalidfpi = NULL;
146
#endif
147
#ifdef LIBXML_SCHEMAS_ENABLED
148
static char * relaxng = NULL;
149
static xmlRelaxNGPtr relaxngschemas = NULL;
150
static char * schema = NULL;
151
static xmlSchemaPtr wxschemas = NULL;
152
#endif
153
#ifdef LIBXML_SCHEMATRON_ENABLED
154
static char * schematron = NULL;
155
static xmlSchematronPtr wxschematron = NULL;
156
#endif
157
static int repeat = 0;
158
static int insert = 0;
159
#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
160
static int html = 0;
161
static int xmlout = 0;
162
#endif
163
static int htmlout = 0;
164
#ifdef LIBXML_PUSH_ENABLED
165
static int push = 0;
166
#endif /* LIBXML_PUSH_ENABLED */
167
#ifdef HAVE_SYS_MMAN_H
168
static int memory = 0;
169
#endif
170
static int testIO = 0;
171
static char *encoding = NULL;
172
#ifdef LIBXML_XINCLUDE_ENABLED
173
static int xinclude = 0;
174
#endif
175
static int dtdattrs = 0;
176
static int loaddtd = 0;
177
static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
178
static int timing = 0;
179
static int generate = 0;
180
static int dropdtd = 0;
181
#ifdef LIBXML_CATALOG_ENABLED
182
static int catalogs = 0;
183
static int nocatalogs = 0;
184
#endif
185
#ifdef LIBXML_C14N_ENABLED
186
static int canonical = 0;
187
static int exc_canonical = 0;
188
#endif
189
#ifdef LIBXML_READER_ENABLED
190
static int stream = 0;
191
static int walker = 0;
192
#endif /* LIBXML_READER_ENABLED */
193
static int chkregister = 0;
194
static int nbregister = 0;
195
#ifdef LIBXML_SAX1_ENABLED
196
static int sax1 = 0;
197
#endif /* LIBXML_SAX1_ENABLED */
198
#ifdef LIBXML_PATTERN_ENABLED
199
static const char *pattern = NULL;
200
static xmlPatternPtr patternc = NULL;
201
static xmlStreamCtxtPtr patstream = NULL;
202
#endif
203
static int options = XML_PARSE_COMPACT;
204
static int sax = 0;
205
static int oldxml10 = 0;
206
207
/************************************************************************
208
 *									*
209
 *		 Entity loading control and customization.		*
210
 *									*
211
 ************************************************************************/
212
#define MAX_PATHS 64
213
#ifdef _WIN32
214
# define PATH_SEPARATOR ';'
215
#else
216
# define PATH_SEPARATOR ':'
217
#endif
218
static xmlChar *paths[MAX_PATHS + 1];
219
static int nbpaths = 0;
220
static int load_trace = 0;
221
222
static
223
void parsePath(const xmlChar *path) {
224
    const xmlChar *cur;
225
226
    if (path == NULL)
227
	return;
228
    while (*path != 0) {
229
	if (nbpaths >= MAX_PATHS) {
230
	    fprintf(stderr, "MAX_PATHS reached: too many paths\n");
231
	    return;
232
	}
233
	cur = path;
234
	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
235
	    cur++;
236
	path = cur;
237
	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
238
	    cur++;
239
	if (cur != path) {
240
	    paths[nbpaths] = xmlStrndup(path, cur - path);
241
	    if (paths[nbpaths] != NULL)
242
		nbpaths++;
243
	    path = cur;
244
	}
245
    }
246
}
247
248
static xmlExternalEntityLoader defaultEntityLoader = NULL;
249
250
static xmlParserInputPtr 
251
xmllintExternalEntityLoader(const char *URL, const char *ID,
252
			     xmlParserCtxtPtr ctxt) {
253
    xmlParserInputPtr ret;
254
    warningSAXFunc warning = NULL;
255
    errorSAXFunc err = NULL;
256
257
    int i;
258
    const char *lastsegment = URL;
259
    const char *iter = URL;
260
261
    if ((nbpaths > 0) && (iter != NULL)) {
262
	while (*iter != 0) {
263
	    if (*iter == '/')
264
		lastsegment = iter + 1;
265
	    iter++;
266
	}
267
    }
268
269
    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
270
	warning = ctxt->sax->warning;
271
	err = ctxt->sax->error;
272
	ctxt->sax->warning = NULL;
273
	ctxt->sax->error = NULL;
274
    }
275
276
    if (defaultEntityLoader != NULL) {
277
	ret = defaultEntityLoader(URL, ID, ctxt);
278
	if (ret != NULL) {
279
	    if (warning != NULL)
280
		ctxt->sax->warning = warning;
281
	    if (err != NULL)
282
		ctxt->sax->error = err;
283
	    if (load_trace) {
284
		fprintf \
285
			(stderr,
286
			 "Loaded URL=\"%s\" ID=\"%s\"\n",
287
			 URL ? URL : "(null)",
288
			 ID ? ID : "(null)");
289
	    }
290
	    return(ret);
291
	}
292
    }
293
    for (i = 0;i < nbpaths;i++) {
294
	xmlChar *newURL;
295
296
	newURL = xmlStrdup((const xmlChar *) paths[i]);
297
	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
298
	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
299
	if (newURL != NULL) {
300
	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
301
	    if (ret != NULL) {
302
		if (warning != NULL)
303
		    ctxt->sax->warning = warning;
304
		if (err != NULL)
305
		    ctxt->sax->error = err;
306
		if (load_trace) {
307
		    fprintf \
308
		    	(stderr,
309
		    	 "Loaded URL=\"%s\" ID=\"%s\"\n",
310
			 newURL,
311
		    	 ID ? ID : "(null)");
312
		}
313
		xmlFree(newURL);
314
		return(ret);
315
	    }
316
	    xmlFree(newURL);
317
	}
318
    }
319
    if (err != NULL)
320
        ctxt->sax->error = err;
321
    if (warning != NULL) {
322
	ctxt->sax->warning = warning;
323
	if (URL != NULL)
324
	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
325
	else if (ID != NULL)
326
	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
327
    }
328
    return(NULL);
329
}
330
/************************************************************************
331
 * 									*
332
 * Memory allocation consumption debugging				*
333
 * 									*
334
 ************************************************************************/
335
336
static void
337
OOM(void)
338
{
339
    fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem);
340
    progresult = XMLLINT_ERR_MEM;
341
}
342
343
static void
344
myFreeFunc(void *mem)
345
{
346
    xmlMemFree(mem);
347
}
348
static void *
349
myMallocFunc(size_t size)
350
{
351
    void *ret;
352
353
    ret = xmlMemMalloc(size);
354
    if (ret != NULL) {
355
        if (xmlMemUsed() > maxmem) {
356
            OOM();
357
            xmlMemFree(ret);
358
            return (NULL);
359
        }
360
    }
361
    return (ret);
362
}
363
static void *
364
myReallocFunc(void *mem, size_t size)
365
{
366
    void *ret;
367
368
    ret = xmlMemRealloc(mem, size);
369
    if (ret != NULL) {
370
        if (xmlMemUsed() > maxmem) {
371
            OOM();
372
            xmlMemFree(ret);
373
            return (NULL);
374
        }
375
    }
376
    return (ret);
377
}
378
static char *
379
myStrdupFunc(const char *str)
380
{
381
    char *ret;
382
383
    ret = xmlMemoryStrdup(str);
384
    if (ret != NULL) {
385
        if (xmlMemUsed() > maxmem) {
386
            OOM();
387
            xmlFree(ret);
388
            return (NULL);
389
        }
390
    }
391
    return (ret);
392
}
393
/************************************************************************
394
 * 									*
395
 * Internal timing routines to remove the necessity to have		*
396
 * unix-specific function calls.					*
397
 * 									*
398
 ************************************************************************/
399
400
#ifndef HAVE_GETTIMEOFDAY 
401
#ifdef HAVE_SYS_TIMEB_H
402
#ifdef HAVE_SYS_TIME_H
403
#ifdef HAVE_FTIME
404
405
static int
406
my_gettimeofday(struct timeval *tvp, void *tzp)
407
{
408
	struct timeb timebuffer;
409
410
	ftime(&timebuffer);
411
	if (tvp) {
412
		tvp->tv_sec = timebuffer.time;
413
		tvp->tv_usec = timebuffer.millitm * 1000L;
414
	}
415
	return (0);
416
}
417
#define HAVE_GETTIMEOFDAY 1
418
#define gettimeofday my_gettimeofday
419
420
#endif /* HAVE_FTIME */
421
#endif /* HAVE_SYS_TIME_H */
422
#endif /* HAVE_SYS_TIMEB_H */
423
#endif /* !HAVE_GETTIMEOFDAY */
424
425
#if defined(HAVE_GETTIMEOFDAY)
426
static struct timeval begin, end;
427
428
/*
429
 * startTimer: call where you want to start timing
430
 */
431
static void
432
startTimer(void)
433
{
434
    gettimeofday(&begin, NULL);
435
}
436
437
/*
438
 * endTimer: call where you want to stop timing and to print out a
439
 *           message about the timing performed; format is a printf
440
 *           type argument
441
 */
442
static void XMLCDECL
443
endTimer(const char *fmt, ...)
444
{
445
    long msec;
446
    va_list ap;
447
448
    gettimeofday(&end, NULL);
449
    msec = end.tv_sec - begin.tv_sec;
450
    msec *= 1000;
451
    msec += (end.tv_usec - begin.tv_usec) / 1000;
452
453
#ifndef HAVE_STDARG_H
454
#error "endTimer required stdarg functions"
455
#endif
456
    va_start(ap, fmt);
457
    vfprintf(stderr, fmt, ap);
458
    va_end(ap);
459
460
    fprintf(stderr, " took %ld ms\n", msec);
461
}
462
#elif defined(HAVE_TIME_H)
463
/*
464
 * No gettimeofday function, so we have to make do with calling clock.
465
 * This is obviously less accurate, but there's little we can do about
466
 * that.
467
 */
468
#ifndef CLOCKS_PER_SEC
469
#define CLOCKS_PER_SEC 100
470
#endif
471
472
static clock_t begin, end;
473
static void
474
startTimer(void)
475
{
476
    begin = clock();
477
}
478
static void XMLCDECL
479
endTimer(const char *fmt, ...)
480
{
481
    long msec;
482
    va_list ap;
483
484
    end = clock();
485
    msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
486
487
#ifndef HAVE_STDARG_H
488
#error "endTimer required stdarg functions"
489
#endif
490
    va_start(ap, fmt);
491
    vfprintf(stderr, fmt, ap);
492
    va_end(ap);
493
    fprintf(stderr, " took %ld ms\n", msec);
494
}
495
#else
496
497
/*
498
 * We don't have a gettimeofday or time.h, so we just don't do timing
499
 */
500
static void
501
startTimer(void)
502
{
503
    /*
504
     * Do nothing
505
     */
506
}
507
static void XMLCDECL
508
endTimer(char *format, ...)
509
{
510
    /*
511
     * We cannot do anything because we don't have a timing function
512
     */
513
#ifdef HAVE_STDARG_H
514
    va_start(ap, format);
515
    vfprintf(stderr, format, ap);
516
    va_end(ap);
517
    fprintf(stderr, " was not timed\n", msec);
518
#else
519
    /* We don't have gettimeofday, time or stdarg.h, what crazy world is
520
     * this ?!
521
     */
522
#endif
523
}
524
#endif
525
/************************************************************************
526
 * 									*
527
 * 			HTML ouput					*
528
 * 									*
529
 ************************************************************************/
530
static char buffer[50000];
531
532
static void
533
xmlHTMLEncodeSend(void) {
534
    char *result;
535
536
    result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
537
    if (result) {
538
	xmlGenericError(xmlGenericErrorContext, "%s", result);
539
	xmlFree(result);
540
    }
541
    buffer[0] = 0;
542
}
543
544
/**
545
 * xmlHTMLPrintFileInfo:
546
 * @input:  an xmlParserInputPtr input
547
 * 
548
 * Displays the associated file and line informations for the current input
549
 */
550
551
static void
552
xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
553
    int len;
554
    xmlGenericError(xmlGenericErrorContext, "<p>");
555
556
    len = strlen(buffer);
557
    if (input != NULL) {
558
	if (input->filename) {
559
	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
560
		    input->line);
561
	} else {
562
	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
563
	}
564
    }
565
    xmlHTMLEncodeSend();
566
}
567
568
/**
569
 * xmlHTMLPrintFileContext:
570
 * @input:  an xmlParserInputPtr input
571
 * 
572
 * Displays current context within the input content for error tracking
573
 */
574
575
static void
576
xmlHTMLPrintFileContext(xmlParserInputPtr input) {
577
    const xmlChar *cur, *base;
578
    int len;
579
    int n;
580
581
    if (input == NULL) return;
582
    xmlGenericError(xmlGenericErrorContext, "<pre>\n");
583
    cur = input->cur;
584
    base = input->base;
585
    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
586
	cur--;
587
    }
588
    n = 0;
589
    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
590
        cur--;
591
    if ((*cur == '\n') || (*cur == '\r')) cur++;
592
    base = cur;
593
    n = 0;
594
    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
595
	len = strlen(buffer);
596
        snprintf(&buffer[len], sizeof(buffer) - len, "%c", 
597
		    (unsigned char) *cur++);
598
	n++;
599
    }
600
    len = strlen(buffer);
601
    snprintf(&buffer[len], sizeof(buffer) - len, "\n");
602
    cur = input->cur;
603
    while ((*cur == '\n') || (*cur == '\r'))
604
	cur--;
605
    n = 0;
606
    while ((cur != base) && (n++ < 80)) {
607
	len = strlen(buffer);
608
        snprintf(&buffer[len], sizeof(buffer) - len, " ");
609
        base++;
610
    }
611
    len = strlen(buffer);
612
    snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
613
    xmlHTMLEncodeSend();
614
    xmlGenericError(xmlGenericErrorContext, "</pre>");
615
}
616
617
/**
618
 * xmlHTMLError:
619
 * @ctx:  an XML parser context
620
 * @msg:  the message to display/transmit
621
 * @...:  extra parameters for the message display
622
 * 
623
 * Display and format an error messages, gives file, line, position and
624
 * extra parameters.
625
 */
626
static void XMLCDECL
627
xmlHTMLError(void *ctx, const char *msg, ...)
628
{
629
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
630
    xmlParserInputPtr input;
631
    va_list args;
632
    int len;
633
634
    buffer[0] = 0;
635
    input = ctxt->input;
636
    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
637
        input = ctxt->inputTab[ctxt->inputNr - 2];
638
    }
639
        
640
    xmlHTMLPrintFileInfo(input);
641
642
    xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
643
    va_start(args, msg);
644
    len = strlen(buffer);
645
    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
646
    va_end(args);
647
    xmlHTMLEncodeSend();
648
    xmlGenericError(xmlGenericErrorContext, "</p>\n");
649
650
    xmlHTMLPrintFileContext(input);
651
    xmlHTMLEncodeSend();
652
}
653
654
/**
655
 * xmlHTMLWarning:
656
 * @ctx:  an XML parser context
657
 * @msg:  the message to display/transmit
658
 * @...:  extra parameters for the message display
659
 * 
660
 * Display and format a warning messages, gives file, line, position and
661
 * extra parameters.
662
 */
663
static void XMLCDECL
664
xmlHTMLWarning(void *ctx, const char *msg, ...)
665
{
666
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
667
    xmlParserInputPtr input;
668
    va_list args;
669
    int len;
670
671
    buffer[0] = 0;
672
    input = ctxt->input;
673
    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
674
        input = ctxt->inputTab[ctxt->inputNr - 2];
675
    }
676
        
677
678
    xmlHTMLPrintFileInfo(input);
679
        
680
    xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
681
    va_start(args, msg);
682
    len = strlen(buffer);    
683
    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
684
    va_end(args);
685
    xmlHTMLEncodeSend();
686
    xmlGenericError(xmlGenericErrorContext, "</p>\n");
687
688
    xmlHTMLPrintFileContext(input);
689
    xmlHTMLEncodeSend();
690
}
691
692
/**
693
 * xmlHTMLValidityError:
694
 * @ctx:  an XML parser context
695
 * @msg:  the message to display/transmit
696
 * @...:  extra parameters for the message display
697
 * 
698
 * Display and format an validity error messages, gives file,
699
 * line, position and extra parameters.
700
 */
701
static void XMLCDECL
702
xmlHTMLValidityError(void *ctx, const char *msg, ...)
703
{
704
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
705
    xmlParserInputPtr input;
706
    va_list args;
707
    int len;
708
709
    buffer[0] = 0;
710
    input = ctxt->input;
711
    if ((input->filename == NULL) && (ctxt->inputNr > 1))
712
        input = ctxt->inputTab[ctxt->inputNr - 2];
713
        
714
    xmlHTMLPrintFileInfo(input);
715
716
    xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
717
    len = strlen(buffer);
718
    va_start(args, msg);
719
    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
720
    va_end(args);
721
    xmlHTMLEncodeSend();
722
    xmlGenericError(xmlGenericErrorContext, "</p>\n");
723
724
    xmlHTMLPrintFileContext(input);
725
    xmlHTMLEncodeSend();
726
    progresult = XMLLINT_ERR_VALID;
727
}
728
729
/**
730
 * xmlHTMLValidityWarning:
731
 * @ctx:  an XML parser context
732
 * @msg:  the message to display/transmit
733
 * @...:  extra parameters for the message display
734
 * 
735
 * Display and format a validity warning messages, gives file, line,
736
 * position and extra parameters.
737
 */
738
static void XMLCDECL
739
xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
740
{
741
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
742
    xmlParserInputPtr input;
743
    va_list args;
744
    int len;
745
746
    buffer[0] = 0;
747
    input = ctxt->input;
748
    if ((input->filename == NULL) && (ctxt->inputNr > 1))
749
        input = ctxt->inputTab[ctxt->inputNr - 2];
750
751
    xmlHTMLPrintFileInfo(input);
752
        
753
    xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
754
    va_start(args, msg);
755
    len = strlen(buffer); 
756
    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
757
    va_end(args);
758
    xmlHTMLEncodeSend();
759
    xmlGenericError(xmlGenericErrorContext, "</p>\n");
760
761
    xmlHTMLPrintFileContext(input);
762
    xmlHTMLEncodeSend();
763
}
764
765
/************************************************************************
766
 * 									*
767
 * 			Shell Interface					*
768
 * 									*
769
 ************************************************************************/
770
#ifdef LIBXML_DEBUG_ENABLED
771
#ifdef LIBXML_XPATH_ENABLED
772
/**
773
 * xmlShellReadline:
774
 * @prompt:  the prompt value
775
 *
776
 * Read a string
777
 * 
778
 * Returns a pointer to it or NULL on EOF the caller is expected to
779
 *     free the returned string.
780
 */
781
static char *
782
xmlShellReadline(char *prompt) {
783
#ifdef HAVE_LIBREADLINE
784
    char *line_read;
785
786
    /* Get a line from the user. */
787
    line_read = readline (prompt);
788
789
    /* If the line has any text in it, save it on the history. */
790
    if (line_read && *line_read)
791
	add_history (line_read);
792
793
    return (line_read);
794
#else
795
    char line_read[501];
796
    char *ret;
797
    int len;
798
799
    if (prompt != NULL)
800
	fprintf(stdout, "%s", prompt);
801
    if (!fgets(line_read, 500, stdin))
802
        return(NULL);
803
    line_read[500] = 0;
804
    len = strlen(line_read);
805
    ret = (char *) malloc(len + 1);
806
    if (ret != NULL) {
807
	memcpy (ret, line_read, len + 1);
808
    }
809
    return(ret);
810
#endif
811
}
812
#endif /* LIBXML_XPATH_ENABLED */
813
#endif /* LIBXML_DEBUG_ENABLED */
814
815
/************************************************************************
816
 * 									*
817
 * 			I/O Interfaces					*
818
 * 									*
819
 ************************************************************************/
820
821
static int myRead(FILE *f, char * buf, int len) {
822
    return(fread(buf, 1, len, f));
823
}
824
static void myClose(FILE *f) {
825
  if (f != stdin) {
826
    fclose(f);
827
  }
828
}
829
830
/************************************************************************
831
 *									*
832
 *		 	SAX based tests					*
833
 *									*
834
 ************************************************************************/
835
836
/*
837
 * empty SAX block
838
 */
839
static xmlSAXHandler emptySAXHandlerStruct = {
840
    NULL, /* internalSubset */
841
    NULL, /* isStandalone */
842
    NULL, /* hasInternalSubset */
843
    NULL, /* hasExternalSubset */
844
    NULL, /* resolveEntity */
845
    NULL, /* getEntity */
846
    NULL, /* entityDecl */
847
    NULL, /* notationDecl */
848
    NULL, /* attributeDecl */
849
    NULL, /* elementDecl */
850
    NULL, /* unparsedEntityDecl */
851
    NULL, /* setDocumentLocator */
852
    NULL, /* startDocument */
853
    NULL, /* endDocument */
854
    NULL, /* startElement */
855
    NULL, /* endElement */
856
    NULL, /* reference */
857
    NULL, /* characters */
858
    NULL, /* ignorableWhitespace */
859
    NULL, /* processingInstruction */
860
    NULL, /* comment */
861
    NULL, /* xmlParserWarning */
862
    NULL, /* xmlParserError */
863
    NULL, /* xmlParserError */
864
    NULL, /* getParameterEntity */
865
    NULL, /* cdataBlock; */
866
    NULL, /* externalSubset; */
867
    XML_SAX2_MAGIC,
868
    NULL,
869
    NULL, /* startElementNs */
870
    NULL, /* endElementNs */
871
    NULL  /* xmlStructuredErrorFunc */
872
};
873
874
static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
875
extern xmlSAXHandlerPtr debugSAXHandler;
876
static int callbacks;
877
878
/**
879
 * isStandaloneDebug:
880
 * @ctxt:  An XML parser context
881
 *
882
 * Is this document tagged standalone ?
883
 *
884
 * Returns 1 if true
885
 */
886
static int
887
isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
888
{
889
    callbacks++;
890
    if (noout)
891
	return(0);
892
    fprintf(stdout, "SAX.isStandalone()\n");
893
    return(0);
894
}
895
896
/**
897
 * hasInternalSubsetDebug:
898
 * @ctxt:  An XML parser context
899
 *
900
 * Does this document has an internal subset
901
 *
902
 * Returns 1 if true
903
 */
904
static int
905
hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
906
{
907
    callbacks++;
908
    if (noout)
909
	return(0);
910
    fprintf(stdout, "SAX.hasInternalSubset()\n");
911
    return(0);
912
}
913
914
/**
915
 * hasExternalSubsetDebug:
916
 * @ctxt:  An XML parser context
917
 *
918
 * Does this document has an external subset
919
 *
920
 * Returns 1 if true
921
 */
922
static int
923
hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
924
{
925
    callbacks++;
926
    if (noout)
927
	return(0);
928
    fprintf(stdout, "SAX.hasExternalSubset()\n");
929
    return(0);
930
}
931
932
/**
933
 * internalSubsetDebug:
934
 * @ctxt:  An XML parser context
935
 *
936
 * Does this document has an internal subset
937
 */
938
static void
939
internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
940
	       const xmlChar *ExternalID, const xmlChar *SystemID)
941
{
942
    callbacks++;
943
    if (noout)
944
	return;
945
    fprintf(stdout, "SAX.internalSubset(%s,", name);
946
    if (ExternalID == NULL)
947
	fprintf(stdout, " ,");
948
    else
949
	fprintf(stdout, " %s,", ExternalID);
950
    if (SystemID == NULL)
951
	fprintf(stdout, " )\n");
952
    else
953
	fprintf(stdout, " %s)\n", SystemID);
954
}
955
956
/**
957
 * externalSubsetDebug:
958
 * @ctxt:  An XML parser context
959
 *
960
 * Does this document has an external subset
961
 */
962
static void
963
externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
964
	       const xmlChar *ExternalID, const xmlChar *SystemID)
965
{
966
    callbacks++;
967
    if (noout)
968
	return;
969
    fprintf(stdout, "SAX.externalSubset(%s,", name);
970
    if (ExternalID == NULL)
971
	fprintf(stdout, " ,");
972
    else
973
	fprintf(stdout, " %s,", ExternalID);
974
    if (SystemID == NULL)
975
	fprintf(stdout, " )\n");
976
    else
977
	fprintf(stdout, " %s)\n", SystemID);
978
}
979
980
/**
981
 * resolveEntityDebug:
982
 * @ctxt:  An XML parser context
983
 * @publicId: The public ID of the entity
984
 * @systemId: The system ID of the entity
985
 *
986
 * Special entity resolver, better left to the parser, it has
987
 * more context than the application layer.
988
 * The default behaviour is to NOT resolve the entities, in that case
989
 * the ENTITY_REF nodes are built in the structure (and the parameter
990
 * values).
991
 *
992
 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
993
 */
994
static xmlParserInputPtr
995
resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
996
{
997
    callbacks++;
998
    if (noout)
999
	return(NULL);
1000
    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1001
1002
    
1003
    fprintf(stdout, "SAX.resolveEntity(");
1004
    if (publicId != NULL)
1005
	fprintf(stdout, "%s", (char *)publicId);
1006
    else
1007
	fprintf(stdout, " ");
1008
    if (systemId != NULL)
1009
	fprintf(stdout, ", %s)\n", (char *)systemId);
1010
    else
1011
	fprintf(stdout, ", )\n");
1012
    return(NULL);
1013
}
1014
1015
/**
1016
 * getEntityDebug:
1017
 * @ctxt:  An XML parser context
1018
 * @name: The entity name
1019
 *
1020
 * Get an entity by name
1021
 *
1022
 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
1023
 */
1024
static xmlEntityPtr
1025
getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1026
{
1027
    callbacks++;
1028
    if (noout)
1029
	return(NULL);
1030
    fprintf(stdout, "SAX.getEntity(%s)\n", name);
1031
    return(NULL);
1032
}
1033
1034
/**
1035
 * getParameterEntityDebug:
1036
 * @ctxt:  An XML parser context
1037
 * @name: The entity name
1038
 *
1039
 * Get a parameter entity by name
1040
 *
1041
 * Returns the xmlParserInputPtr
1042
 */
1043
static xmlEntityPtr
1044
getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1045
{
1046
    callbacks++;
1047
    if (noout)
1048
	return(NULL);
1049
    fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
1050
    return(NULL);
1051
}
1052
1053
1054
/**
1055
 * entityDeclDebug:
1056
 * @ctxt:  An XML parser context
1057
 * @name:  the entity name 
1058
 * @type:  the entity type 
1059
 * @publicId: The public ID of the entity
1060
 * @systemId: The system ID of the entity
1061
 * @content: the entity value (without processing).
1062
 *
1063
 * An entity definition has been parsed
1064
 */
1065
static void
1066
entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1067
          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
1068
{
1069
const xmlChar *nullstr = BAD_CAST "(null)";
1070
    /* not all libraries handle printing null pointers nicely */
1071
    if (publicId == NULL)
1072
        publicId = nullstr;
1073
    if (systemId == NULL)
1074
        systemId = nullstr;
1075
    if (content == NULL)
1076
        content = (xmlChar *)nullstr;
1077
    callbacks++;
1078
    if (noout)
1079
	return;
1080
    fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
1081
            name, type, publicId, systemId, content);
1082
}
1083
1084
/**
1085
 * attributeDeclDebug:
1086
 * @ctxt:  An XML parser context
1087
 * @name:  the attribute name 
1088
 * @type:  the attribute type 
1089
 *
1090
 * An attribute definition has been parsed
1091
 */
1092
static void
1093
attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
1094
                   const xmlChar * name, int type, int def,
1095
                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
1096
{
1097
    callbacks++;
1098
    if (noout)
1099
        return;
1100
    if (defaultValue == NULL)
1101
        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1102
                elem, name, type, def);
1103
    else
1104
        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1105
                elem, name, type, def, defaultValue);
1106
    xmlFreeEnumeration(tree);
1107
}
1108
1109
/**
1110
 * elementDeclDebug:
1111
 * @ctxt:  An XML parser context
1112
 * @name:  the element name 
1113
 * @type:  the element type 
1114
 * @content: the element value (without processing).
1115
 *
1116
 * An element definition has been parsed
1117
 */
1118
static void
1119
elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1120
	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
1121
{
1122
    callbacks++;
1123
    if (noout)
1124
	return;
1125
    fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
1126
            name, type);
1127
}
1128
1129
/**
1130
 * notationDeclDebug:
1131
 * @ctxt:  An XML parser context
1132
 * @name: The name of the notation
1133
 * @publicId: The public ID of the entity
1134
 * @systemId: The system ID of the entity
1135
 *
1136
 * What to do when a notation declaration has been parsed.
1137
 */
1138
static void
1139
notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1140
	     const xmlChar *publicId, const xmlChar *systemId)
1141
{
1142
    callbacks++;
1143
    if (noout)
1144
	return;
1145
    fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
1146
            (char *) name, (char *) publicId, (char *) systemId);
1147
}
1148
1149
/**
1150
 * unparsedEntityDeclDebug:
1151
 * @ctxt:  An XML parser context
1152
 * @name: The name of the entity
1153
 * @publicId: The public ID of the entity
1154
 * @systemId: The system ID of the entity
1155
 * @notationName: the name of the notation
1156
 *
1157
 * What to do when an unparsed entity declaration is parsed
1158
 */
1159
static void
1160
unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1161
		   const xmlChar *publicId, const xmlChar *systemId,
1162
		   const xmlChar *notationName)
1163
{
1164
const xmlChar *nullstr = BAD_CAST "(null)";
1165
1166
    if (publicId == NULL)
1167
        publicId = nullstr;
1168
    if (systemId == NULL)
1169
        systemId = nullstr;
1170
    if (notationName == NULL)
1171
        notationName = nullstr;
1172
    callbacks++;
1173
    if (noout)
1174
	return;
1175
    fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1176
            (char *) name, (char *) publicId, (char *) systemId,
1177
	    (char *) notationName);
1178
}
1179
1180
/**
1181
 * setDocumentLocatorDebug:
1182
 * @ctxt:  An XML parser context
1183
 * @loc: A SAX Locator
1184
 *
1185
 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1186
 * Everything is available on the context, so this is useless in our case.
1187
 */
1188
static void
1189
setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1190
{
1191
    callbacks++;
1192
    if (noout)
1193
	return;
1194
    fprintf(stdout, "SAX.setDocumentLocator()\n");
1195
}
1196
1197
/**
1198
 * startDocumentDebug:
1199
 * @ctxt:  An XML parser context
1200
 *
1201
 * called when the document start being processed.
1202
 */
1203
static void
1204
startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1205
{
1206
    callbacks++;
1207
    if (noout)
1208
	return;
1209
    fprintf(stdout, "SAX.startDocument()\n");
1210
}
1211
1212
/**
1213
 * endDocumentDebug:
1214
 * @ctxt:  An XML parser context
1215
 *
1216
 * called when the document end has been detected.
1217
 */
1218
static void
1219
endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1220
{
1221
    callbacks++;
1222
    if (noout)
1223
	return;
1224
    fprintf(stdout, "SAX.endDocument()\n");
1225
}
1226
1227
/**
1228
 * startElementDebug:
1229
 * @ctxt:  An XML parser context
1230
 * @name:  The element name
1231
 *
1232
 * called when an opening tag has been processed.
1233
 */
1234
static void
1235
startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1236
{
1237
    int i;
1238
1239
    callbacks++;
1240
    if (noout)
1241
	return;
1242
    fprintf(stdout, "SAX.startElement(%s", (char *) name);
1243
    if (atts != NULL) {
1244
        for (i = 0;(atts[i] != NULL);i++) {
1245
	    fprintf(stdout, ", %s='", atts[i++]);
1246
	    if (atts[i] != NULL)
1247
	        fprintf(stdout, "%s'", atts[i]);
1248
	}
1249
    }
1250
    fprintf(stdout, ")\n");
1251
}
1252
1253
/**
1254
 * endElementDebug:
1255
 * @ctxt:  An XML parser context
1256
 * @name:  The element name
1257
 *
1258
 * called when the end of an element has been detected.
1259
 */
1260
static void
1261
endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1262
{
1263
    callbacks++;
1264
    if (noout)
1265
	return;
1266
    fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
1267
}
1268
1269
/**
1270
 * charactersDebug:
1271
 * @ctxt:  An XML parser context
1272
 * @ch:  a xmlChar string
1273
 * @len: the number of xmlChar
1274
 *
1275
 * receiving some chars from the parser.
1276
 * Question: how much at a time ???
1277
 */
1278
static void
1279
charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1280
{
1281
    char out[40];
1282
    int i;
1283
1284
    callbacks++;
1285
    if (noout)
1286
	return;
1287
    for (i = 0;(i<len) && (i < 30);i++)
1288
	out[i] = ch[i];
1289
    out[i] = 0;
1290
1291
    fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
1292
}
1293
1294
/**
1295
 * referenceDebug:
1296
 * @ctxt:  An XML parser context
1297
 * @name:  The entity name
1298
 *
1299
 * called when an entity reference is detected. 
1300
 */
1301
static void
1302
referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1303
{
1304
    callbacks++;
1305
    if (noout)
1306
	return;
1307
    fprintf(stdout, "SAX.reference(%s)\n", name);
1308
}
1309
1310
/**
1311
 * ignorableWhitespaceDebug:
1312
 * @ctxt:  An XML parser context
1313
 * @ch:  a xmlChar string
1314
 * @start: the first char in the string
1315
 * @len: the number of xmlChar
1316
 *
1317
 * receiving some ignorable whitespaces from the parser.
1318
 * Question: how much at a time ???
1319
 */
1320
static void
1321
ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1322
{
1323
    char out[40];
1324
    int i;
1325
1326
    callbacks++;
1327
    if (noout)
1328
	return;
1329
    for (i = 0;(i<len) && (i < 30);i++)
1330
	out[i] = ch[i];
1331
    out[i] = 0;
1332
    fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
1333
}
1334
1335
/**
1336
 * processingInstructionDebug:
1337
 * @ctxt:  An XML parser context
1338
 * @target:  the target name
1339
 * @data: the PI data's
1340
 * @len: the number of xmlChar
1341
 *
1342
 * A processing instruction has been parsed.
1343
 */
1344
static void
1345
processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1346
                      const xmlChar *data)
1347
{
1348
    callbacks++;
1349
    if (noout)
1350
	return;
1351
    if (data != NULL)
1352
	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
1353
		(char *) target, (char *) data);
1354
    else
1355
	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
1356
		(char *) target);
1357
}
1358
1359
/**
1360
 * cdataBlockDebug:
1361
 * @ctx: the user data (XML parser context)
1362
 * @value:  The pcdata content
1363
 * @len:  the block length
1364
 *
1365
 * called when a pcdata block has been parsed
1366
 */
1367
static void
1368
cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1369
{
1370
    callbacks++;
1371
    if (noout)
1372
	return;
1373
    fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
1374
	    (char *) value, len);
1375
}
1376
1377
/**
1378
 * commentDebug:
1379
 * @ctxt:  An XML parser context
1380
 * @value:  the comment content
1381
 *
1382
 * A comment has been parsed.
1383
 */
1384
static void
1385
commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1386
{
1387
    callbacks++;
1388
    if (noout)
1389
	return;
1390
    fprintf(stdout, "SAX.comment(%s)\n", value);
1391
}
1392
1393
/**
1394
 * warningDebug:
1395
 * @ctxt:  An XML parser context
1396
 * @msg:  the message to display/transmit
1397
 * @...:  extra parameters for the message display
1398
 *
1399
 * Display and format a warning messages, gives file, line, position and
1400
 * extra parameters.
1401
 */
1402
static void XMLCDECL
1403
warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1404
{
1405
    va_list args;
1406
1407
    callbacks++;
1408
    if (noout)
1409
	return;
1410
    va_start(args, msg);
1411
    fprintf(stdout, "SAX.warning: ");
1412
    vfprintf(stdout, msg, args);
1413
    va_end(args);
1414
}
1415
1416
/**
1417
 * errorDebug:
1418
 * @ctxt:  An XML parser context
1419
 * @msg:  the message to display/transmit
1420
 * @...:  extra parameters for the message display
1421
 *
1422
 * Display and format a error messages, gives file, line, position and
1423
 * extra parameters.
1424
 */
1425
static void XMLCDECL
1426
errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1427
{
1428
    va_list args;
1429
1430
    callbacks++;
1431
    if (noout)
1432
	return;
1433
    va_start(args, msg);
1434
    fprintf(stdout, "SAX.error: ");
1435
    vfprintf(stdout, msg, args);
1436
    va_end(args);
1437
}
1438
1439
/**
1440
 * fatalErrorDebug:
1441
 * @ctxt:  An XML parser context
1442
 * @msg:  the message to display/transmit
1443
 * @...:  extra parameters for the message display
1444
 *
1445
 * Display and format a fatalError messages, gives file, line, position and
1446
 * extra parameters.
1447
 */
1448
static void XMLCDECL
1449
fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1450
{
1451
    va_list args;
1452
1453
    callbacks++;
1454
    if (noout)
1455
	return;
1456
    va_start(args, msg);
1457
    fprintf(stdout, "SAX.fatalError: ");
1458
    vfprintf(stdout, msg, args);
1459
    va_end(args);
1460
}
1461
1462
static xmlSAXHandler debugSAXHandlerStruct = {
1463
    internalSubsetDebug,
1464
    isStandaloneDebug,
1465
    hasInternalSubsetDebug,
1466
    hasExternalSubsetDebug,
1467
    resolveEntityDebug,
1468
    getEntityDebug,
1469
    entityDeclDebug,
1470
    notationDeclDebug,
1471
    attributeDeclDebug,
1472
    elementDeclDebug,
1473
    unparsedEntityDeclDebug,
1474
    setDocumentLocatorDebug,
1475
    startDocumentDebug,
1476
    endDocumentDebug,
1477
    startElementDebug,
1478
    endElementDebug,
1479
    referenceDebug,
1480
    charactersDebug,
1481
    ignorableWhitespaceDebug,
1482
    processingInstructionDebug,
1483
    commentDebug,
1484
    warningDebug,
1485
    errorDebug,
1486
    fatalErrorDebug,
1487
    getParameterEntityDebug,
1488
    cdataBlockDebug,
1489
    externalSubsetDebug,
1490
    1,
1491
    NULL,
1492
    NULL,
1493
    NULL,
1494
    NULL
1495
};
1496
1497
xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1498
1499
/*
1500
 * SAX2 specific callbacks
1501
 */
1502
/**
1503
 * startElementNsDebug:
1504
 * @ctxt:  An XML parser context
1505
 * @name:  The element name
1506
 *
1507
 * called when an opening tag has been processed.
1508
 */
1509
static void
1510
startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1511
                    const xmlChar *localname,
1512
                    const xmlChar *prefix,
1513
                    const xmlChar *URI,
1514
		    int nb_namespaces,
1515
		    const xmlChar **namespaces,
1516
		    int nb_attributes,
1517
		    int nb_defaulted,
1518
		    const xmlChar **attributes)
1519
{
1520
    int i;
1521
1522
    callbacks++;
1523
    if (noout)
1524
	return;
1525
    fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
1526
    if (prefix == NULL)
1527
	fprintf(stdout, ", NULL");
1528
    else
1529
	fprintf(stdout, ", %s", (char *) prefix);
1530
    if (URI == NULL)
1531
	fprintf(stdout, ", NULL");
1532
    else
1533
	fprintf(stdout, ", '%s'", (char *) URI);
1534
    fprintf(stdout, ", %d", nb_namespaces);
1535
    
1536
    if (namespaces != NULL) {
1537
        for (i = 0;i < nb_namespaces * 2;i++) {
1538
	    fprintf(stdout, ", xmlns");
1539
	    if (namespaces[i] != NULL)
1540
	        fprintf(stdout, ":%s", namespaces[i]);
1541
	    i++;
1542
	    fprintf(stdout, "='%s'", namespaces[i]);
1543
	}
1544
    }
1545
    fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
1546
    if (attributes != NULL) {
1547
        for (i = 0;i < nb_attributes * 5;i += 5) {
1548
	    if (attributes[i + 1] != NULL)
1549
		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
1550
	    else
1551
		fprintf(stdout, ", %s='", attributes[i]);
1552
	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
1553
		    (int)(attributes[i + 4] - attributes[i + 3]));
1554
	}
1555
    }
1556
    fprintf(stdout, ")\n");
1557
}
1558
1559
/**
1560
 * endElementDebug:
1561
 * @ctxt:  An XML parser context
1562
 * @name:  The element name
1563
 *
1564
 * called when the end of an element has been detected.
1565
 */
1566
static void
1567
endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1568
                  const xmlChar *localname,
1569
                  const xmlChar *prefix,
1570
                  const xmlChar *URI)
1571
{
1572
    callbacks++;
1573
    if (noout)
1574
	return;
1575
    fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
1576
    if (prefix == NULL)
1577
	fprintf(stdout, ", NULL");
1578
    else
1579
	fprintf(stdout, ", %s", (char *) prefix);
1580
    if (URI == NULL)
1581
	fprintf(stdout, ", NULL)\n");
1582
    else
1583
	fprintf(stdout, ", '%s')\n", (char *) URI);
1584
}
1585
1586
static xmlSAXHandler debugSAX2HandlerStruct = {
1587
    internalSubsetDebug,
1588
    isStandaloneDebug,
1589
    hasInternalSubsetDebug,
1590
    hasExternalSubsetDebug,
1591
    resolveEntityDebug,
1592
    getEntityDebug,
1593
    entityDeclDebug,
1594
    notationDeclDebug,
1595
    attributeDeclDebug,
1596
    elementDeclDebug,
1597
    unparsedEntityDeclDebug,
1598
    setDocumentLocatorDebug,
1599
    startDocumentDebug,
1600
    endDocumentDebug,
1601
    NULL,
1602
    NULL,
1603
    referenceDebug,
1604
    charactersDebug,
1605
    ignorableWhitespaceDebug,
1606
    processingInstructionDebug,
1607
    commentDebug,
1608
    warningDebug,
1609
    errorDebug,
1610
    fatalErrorDebug,
1611
    getParameterEntityDebug,
1612
    cdataBlockDebug,
1613
    externalSubsetDebug,
1614
    XML_SAX2_MAGIC,
1615
    NULL,
1616
    startElementNsDebug,
1617
    endElementNsDebug,
1618
    NULL
1619
};
1620
1621
static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1622
1623
static void
1624
testSAX(const char *filename) {
1625
    xmlSAXHandlerPtr handler;
1626
    const char *user_data = "user_data"; /* mostly for debugging */
1627
    xmlParserInputBufferPtr buf = NULL;
1628
    xmlParserInputPtr inputStream;
1629
    xmlParserCtxtPtr ctxt = NULL;
1630
    xmlSAXHandlerPtr old_sax = NULL;
1631
1632
    callbacks = 0;
1633
1634
    if (noout) {
1635
        handler = emptySAXHandler;
1636
#ifdef LIBXML_SAX1_ENABLED
1637
    } else if (sax1) {
1638
        handler = debugSAXHandler;
1639
#endif
1640
    } else {
1641
        handler = debugSAX2Handler;
1642
    }
1643
1644
    /*
1645
     * it's not the simplest code but the most generic in term of I/O
1646
     */
1647
    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1648
    if (buf == NULL) {
1649
        goto error;
1650
    }
1651
1652
#ifdef LIBXML_SCHEMAS_ENABLED
1653
    if (wxschemas != NULL) {
1654
        int ret;
1655
	xmlSchemaValidCtxtPtr vctxt;
1656
1657
	vctxt = xmlSchemaNewValidCtxt(wxschemas);
1658
	xmlSchemaSetValidErrors(vctxt,
1659
		(xmlSchemaValidityErrorFunc) fprintf,
1660
		(xmlSchemaValidityWarningFunc) fprintf,
1661
		stderr);
1662
1663
	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
1664
	                              (void *)user_data);
1665
	if (repeat == 0) {
1666
	    if (ret == 0) {
1667
		fprintf(stderr, "%s validates\n", filename);
1668
	    } else if (ret > 0) {
1669
		fprintf(stderr, "%s fails to validate\n", filename);
1670
		progresult = XMLLINT_ERR_VALID;
1671
	    } else {
1672
		fprintf(stderr, "%s validation generated an internal error\n",
1673
		       filename);
1674
		progresult = XMLLINT_ERR_VALID;
1675
	    }
1676
	}
1677
	xmlSchemaFreeValidCtxt(vctxt);
1678
    } else
1679
#endif
1680
    {
1681
	/*
1682
	 * Create the parser context amd hook the input
1683
	 */
1684
	ctxt = xmlNewParserCtxt();
1685
	if (ctxt == NULL) {
1686
	    xmlFreeParserInputBuffer(buf);
1687
	    goto error;
1688
	}
1689
	old_sax = ctxt->sax;
1690
	ctxt->sax = handler;
1691
	ctxt->userData = (void *) user_data;
1692
	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
1693
	if (inputStream == NULL) {
1694
	    xmlFreeParserInputBuffer(buf);
1695
	    goto error;
1696
	}
1697
	inputPush(ctxt, inputStream);
1698
	
1699
	/* do the parsing */
1700
	xmlParseDocument(ctxt);
1701
1702
	if (ctxt->myDoc != NULL) {
1703
	    fprintf(stderr, "SAX generated a doc !\n");
1704
	    xmlFreeDoc(ctxt->myDoc);
1705
	    ctxt->myDoc = NULL;
1706
	}
1707
    }
1708
1709
error:
1710
    if (ctxt != NULL) {
1711
        ctxt->sax = old_sax;
1712
        xmlFreeParserCtxt(ctxt);
1713
    }
1714
}
1715
1716
/************************************************************************
1717
 * 									*
1718
 * 			Stream Test processing				*
1719
 * 									*
1720
 ************************************************************************/
1721
#ifdef LIBXML_READER_ENABLED
1722
static void processNode(xmlTextReaderPtr reader) {
1723
    const xmlChar *name, *value;
1724
    int type, empty;
1725
1726
    type = xmlTextReaderNodeType(reader);
1727
    empty = xmlTextReaderIsEmptyElement(reader);
1728
1729
    if (debug) {
1730
	name = xmlTextReaderConstName(reader);
1731
	if (name == NULL)
1732
	    name = BAD_CAST "--";
1733
1734
	value = xmlTextReaderConstValue(reader);
1735
1736
	
1737
	printf("%d %d %s %d %d", 
1738
		xmlTextReaderDepth(reader),
1739
		type,
1740
		name,
1741
		empty,
1742
		xmlTextReaderHasValue(reader));
1743
	if (value == NULL)
1744
	    printf("\n");
1745
	else {
1746
	    printf(" %s\n", value);
1747
	}
1748
    }
1749
#ifdef LIBXML_PATTERN_ENABLED
1750
    if (patternc) {
1751
        xmlChar *path = NULL;
1752
        int match = -1;
1753
	
1754
	if (type == XML_READER_TYPE_ELEMENT) {
1755
	    /* do the check only on element start */
1756
	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
1757
1758
	    if (match) {
1759
		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
1760
		printf("Node %s matches pattern %s\n", path, pattern);
1761
	    }
1762
	}
1763
	if (patstream != NULL) {
1764
	    int ret;
1765
1766
	    if (type == XML_READER_TYPE_ELEMENT) {
1767
		ret = xmlStreamPush(patstream,
1768
		                    xmlTextReaderConstLocalName(reader),
1769
				    xmlTextReaderConstNamespaceUri(reader));
1770
		if (ret < 0) {
1771
		    fprintf(stderr, "xmlStreamPush() failure\n");
1772
                    xmlFreeStreamCtxt(patstream);
1773
		    patstream = NULL;
1774
		} else if (ret != match) {
1775
		    if (path == NULL) {
1776
		        path = xmlGetNodePath(
1777
		                       xmlTextReaderCurrentNode(reader));
1778
		    }
1779
		    fprintf(stderr,
1780
		            "xmlPatternMatch and xmlStreamPush disagree\n");
1781
		    fprintf(stderr,
1782
		            "  pattern %s node %s\n",
1783
			    pattern, path);
1784
		}
1785
		
1786
1787
	    } 
1788
	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
1789
	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
1790
	        ret = xmlStreamPop(patstream);
1791
		if (ret < 0) {
1792
		    fprintf(stderr, "xmlStreamPop() failure\n");
1793
                    xmlFreeStreamCtxt(patstream);
1794
		    patstream = NULL;
1795
		}
1796
	    }
1797
	}
1798
	if (path != NULL)
1799
	    xmlFree(path);
1800
    }
1801
#endif
1802
}
1803
1804
static void streamFile(char *filename) {
1805
    xmlTextReaderPtr reader;
1806
    int ret;
1807
#ifdef HAVE_SYS_MMAN_H
1808
    int fd = -1;
1809
    struct stat info;
1810
    const char *base = NULL;
1811
    xmlParserInputBufferPtr input = NULL;
1812
1813
    if (memory) {
1814
	if (stat(filename, &info) < 0) 
1815
	    return;
1816
	if ((fd = open(filename, O_RDONLY)) < 0)
1817
	    return;
1818
	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
1819
	if (base == (void *) MAP_FAILED)
1820
	    return;
1821
1822
	reader = xmlReaderForMemory(base, info.st_size, filename,
1823
	                            NULL, options);
1824
    } else
1825
#endif
1826
	reader = xmlReaderForFile(filename, NULL, options);
1827
#ifdef LIBXML_PATTERN_ENABLED
1828
    if (pattern != NULL) {
1829
        patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
1830
	if (patternc == NULL) {
1831
	    xmlGenericError(xmlGenericErrorContext,
1832
		    "Pattern %s failed to compile\n", pattern);
1833
            progresult = XMLLINT_ERR_SCHEMAPAT;
1834
	    pattern = NULL;
1835
	}
1836
    }
1837
    if (patternc != NULL) {
1838
        patstream = xmlPatternGetStreamCtxt(patternc);
1839
	if (patstream != NULL) {
1840
	    ret = xmlStreamPush(patstream, NULL, NULL);
1841
	    if (ret < 0) {
1842
		fprintf(stderr, "xmlStreamPush() failure\n");
1843
		xmlFreeStreamCtxt(patstream);
1844
		patstream = NULL;
1845
            }
1846
	}
1847
    }
1848
#endif
1849
1850
1851
    if (reader != NULL) {
1852
#ifdef LIBXML_VALID_ENABLED
1853
	if (valid)
1854
	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
1855
	else
1856
#endif /* LIBXML_VALID_ENABLED */
1857
	    xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
1858
#ifdef LIBXML_SCHEMAS_ENABLED
1859
	if (relaxng != NULL) {
1860
	    if ((timing) && (!repeat)) {
1861
		startTimer();
1862
	    }
1863
	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
1864
	    if (ret < 0) {
1865
		xmlGenericError(xmlGenericErrorContext,
1866
			"Relax-NG schema %s failed to compile\n", relaxng);
1867
		progresult = XMLLINT_ERR_SCHEMACOMP;
1868
		relaxng = NULL;
1869
	    }
1870
	    if ((timing) && (!repeat)) {
1871
		endTimer("Compiling the schemas");
1872
	    }
1873
	}
1874
	if (schema != NULL) {
1875
	    if ((timing) && (!repeat)) {
1876
		startTimer();
1877
	    }
1878
	    ret = xmlTextReaderSchemaValidate(reader, schema);
1879
	    if (ret < 0) {
1880
		xmlGenericError(xmlGenericErrorContext,
1881
			"XSD schema %s failed to compile\n", schema);
1882
		progresult = XMLLINT_ERR_SCHEMACOMP;
1883
		schema = NULL;
1884
	    }
1885
	    if ((timing) && (!repeat)) {
1886
		endTimer("Compiling the schemas");
1887
	    }
1888
	}
1889
#endif
1890
1891
	/*
1892
	 * Process all nodes in sequence
1893
	 */
1894
	if ((timing) && (!repeat)) {
1895
	    startTimer();
1896
	}
1897
	ret = xmlTextReaderRead(reader);
1898
	while (ret == 1) {
1899
	    if ((debug)
1900
#ifdef LIBXML_PATTERN_ENABLED
1901
	        || (patternc)
1902
#endif
1903
	       )
1904
		processNode(reader);
1905
	    ret = xmlTextReaderRead(reader);
1906
	}
1907
	if ((timing) && (!repeat)) {
1908
#ifdef LIBXML_SCHEMAS_ENABLED
1909
	    if (relaxng != NULL)
1910
		endTimer("Parsing and validating");
1911
	    else
1912
#endif
1913
#ifdef LIBXML_VALID_ENABLED
1914
	    if (valid)
1915
		endTimer("Parsing and validating");
1916
	    else
1917
#endif
1918
	    endTimer("Parsing");
1919
	}
1920
1921
#ifdef LIBXML_VALID_ENABLED
1922
	if (valid) {
1923
	    if (xmlTextReaderIsValid(reader) != 1) {
1924
		xmlGenericError(xmlGenericErrorContext,
1925
			"Document %s does not validate\n", filename);
1926
		progresult = XMLLINT_ERR_VALID;
1927
	    }
1928
	}
1929
#endif /* LIBXML_VALID_ENABLED */
1930
#ifdef LIBXML_SCHEMAS_ENABLED
1931
	if ((relaxng != NULL) || (schema != NULL)) {
1932
	    if (xmlTextReaderIsValid(reader) != 1) {
1933
		fprintf(stderr, "%s fails to validate\n", filename);
1934
		progresult = XMLLINT_ERR_VALID;
1935
	    } else {
1936
		fprintf(stderr, "%s validates\n", filename);
1937
	    }
1938
	}
1939
#endif
1940
	/*
1941
	 * Done, cleanup and status
1942
	 */
1943
	xmlFreeTextReader(reader);
1944
	if (ret != 0) {
1945
	    fprintf(stderr, "%s : failed to parse\n", filename);
1946
	    progresult = XMLLINT_ERR_UNCLASS;
1947
	}
1948
    } else {
1949
	fprintf(stderr, "Unable to open %s\n", filename);
1950
	progresult = XMLLINT_ERR_UNCLASS;
1951
    }
1952
#ifdef LIBXML_PATTERN_ENABLED
1953
    if (patstream != NULL) {
1954
	xmlFreeStreamCtxt(patstream);
1955
	patstream = NULL;
1956
    }
1957
#endif
1958
#ifdef HAVE_SYS_MMAN_H
1959
    if (memory) {
1960
        xmlFreeParserInputBuffer(input);
1961
	munmap((char *) base, info.st_size);
1962
	close(fd);
1963
    }
1964
#endif
1965
}
1966
1967
static void walkDoc(xmlDocPtr doc) {
1968
    xmlTextReaderPtr reader;
1969
    int ret;
1970
1971
#ifdef LIBXML_PATTERN_ENABLED
1972
    xmlNodePtr root;
1973
    const xmlChar *namespaces[22];
1974
    int i;
1975
    xmlNsPtr ns;
1976
1977
    root = xmlDocGetRootElement(doc);
1978
    for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
1979
        namespaces[i++] = ns->href;
1980
        namespaces[i++] = ns->prefix;
1981
    }
1982
    namespaces[i++] = NULL;
1983
    namespaces[i++] = NULL;
1984
1985
    if (pattern != NULL) {
1986
        patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
1987
	                             0, &namespaces[0]);
1988
	if (patternc == NULL) {
1989
	    xmlGenericError(xmlGenericErrorContext,
1990
		    "Pattern %s failed to compile\n", pattern);
1991
            progresult = XMLLINT_ERR_SCHEMAPAT;
1992
	    pattern = NULL;
1993
	}
1994
    }
1995
    if (patternc != NULL) {
1996
        patstream = xmlPatternGetStreamCtxt(patternc);
1997
	if (patstream != NULL) {
1998
	    ret = xmlStreamPush(patstream, NULL, NULL);
1999
	    if (ret < 0) {
2000
		fprintf(stderr, "xmlStreamPush() failure\n");
2001
		xmlFreeStreamCtxt(patstream);
2002
		patstream = NULL;
2003
            }
2004
	}
2005
    }
2006
#endif /* LIBXML_PATTERN_ENABLED */
2007
    reader = xmlReaderWalker(doc);
2008
    if (reader != NULL) {
2009
	if ((timing) && (!repeat)) {
2010
	    startTimer();
2011
	}
2012
	ret = xmlTextReaderRead(reader);
2013
	while (ret == 1) {
2014
	    if ((debug)
2015
#ifdef LIBXML_PATTERN_ENABLED
2016
	        || (patternc)
2017
#endif
2018
	       )
2019
		processNode(reader);
2020
	    ret = xmlTextReaderRead(reader);
2021
	}
2022
	if ((timing) && (!repeat)) {
2023
	    endTimer("walking through the doc");
2024
	}
2025
	xmlFreeTextReader(reader);
2026
	if (ret != 0) {
2027
	    fprintf(stderr, "failed to walk through the doc\n");
2028
	    progresult = XMLLINT_ERR_UNCLASS;
2029
	}
2030
    } else {
2031
	fprintf(stderr, "Failed to crate a reader from the document\n");
2032
	progresult = XMLLINT_ERR_UNCLASS;
2033
    }
2034
#ifdef LIBXML_PATTERN_ENABLED
2035
    if (patstream != NULL) {
2036
	xmlFreeStreamCtxt(patstream);
2037
	patstream = NULL;
2038
    }
2039
#endif
2040
}
2041
#endif /* LIBXML_READER_ENABLED */
2042
2043
/************************************************************************
2044
 * 									*
2045
 * 			Tree Test processing				*
2046
 * 									*
2047
 ************************************************************************/
2048
static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
2049
    xmlDocPtr doc = NULL;
2050
#ifdef LIBXML_TREE_ENABLED
2051
    xmlDocPtr tmp;
2052
#endif /* LIBXML_TREE_ENABLED */
2053
2054
    if ((timing) && (!repeat))
2055
	startTimer();
2056
    
2057
2058
#ifdef LIBXML_TREE_ENABLED
2059
    if (filename == NULL) {
2060
	if (generate) {
2061
	    xmlNodePtr n;
2062
2063
	    doc = xmlNewDoc(BAD_CAST "1.0");
2064
	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2065
	    xmlNodeSetContent(n, BAD_CAST "abc");
2066
	    xmlDocSetRootElement(doc, n);
2067
	}
2068
    }
2069
#endif /* LIBXML_TREE_ENABLED */
2070
#ifdef LIBXML_HTML_ENABLED
2071
#ifdef LIBXML_PUSH_ENABLED
2072
    else if ((html) && (push)) {
2073
        FILE *f;
2074
2075
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2076
	f = fopen(filename, "rb");
2077
#else
2078
	f = fopen(filename, "r");
2079
#endif
2080
        if (f != NULL) {
2081
            int res, size = 3;
2082
            char chars[4096];
2083
            htmlParserCtxtPtr ctxt;
2084
2085
            /* if (repeat) */
2086
                size = 4096;
2087
            res = fread(chars, 1, 4, f);
2088
            if (res > 0) {
2089
                ctxt = htmlCreatePushParserCtxt(NULL, NULL,
2090
                            chars, res, filename, XML_CHAR_ENCODING_NONE);
2091
                while ((res = fread(chars, 1, size, f)) > 0) {
2092
                    htmlParseChunk(ctxt, chars, res, 0);
2093
                }
2094
                htmlParseChunk(ctxt, chars, 0, 1);
2095
                doc = ctxt->myDoc;
2096
                htmlFreeParserCtxt(ctxt);
2097
            }
2098
            fclose(f);
2099
        }
2100
    }
2101
#endif /* LIBXML_PUSH_ENABLED */
2102
#ifdef HAVE_SYS_MMAN_H
2103
    else if ((html) && (memory)) {
2104
	int fd;
2105
	struct stat info;
2106
	const char *base;
2107
	if (stat(filename, &info) < 0) 
2108
	    return;
2109
	if ((fd = open(filename, O_RDONLY)) < 0)
2110
	    return;
2111
	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2112
	if (base == (void *) MAP_FAILED)
2113
	    return;
2114
2115
	doc = htmlReadMemory((char *) base, info.st_size, filename,
2116
	                     NULL, options);
2117
	    
2118
	munmap((char *) base, info.st_size);
2119
	close(fd);
2120
    }
2121
#endif
2122
    else if (html) {
2123
	doc = htmlReadFile(filename, NULL, options);
2124
    }
2125
#endif /* LIBXML_HTML_ENABLED */
2126
    else {
2127
#ifdef LIBXML_PUSH_ENABLED
2128
	/*
2129
	 * build an XML tree from a string;
2130
	 */
2131
	if (push) {
2132
	    FILE *f;
2133
2134
	    /* '-' Usually means stdin -<sven@zen.org> */
2135
	    if ((filename[0] == '-') && (filename[1] == 0)) {
2136
	      f = stdin;
2137
	    } else {
2138
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2139
		f = fopen(filename, "rb");
2140
#else
2141
		f = fopen(filename, "r");
2142
#endif
2143
	    }
2144
	    if (f != NULL) {
2145
		int ret;
2146
	        int res, size = 1024;
2147
	        char chars[1024];
2148
                xmlParserCtxtPtr ctxt;
2149
2150
		/* if (repeat) size = 1024; */
2151
		res = fread(chars, 1, 4, f);
2152
		if (res > 0) {
2153
		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
2154
		                chars, res, filename);
2155
		    xmlCtxtUseOptions(ctxt, options);
2156
		    while ((res = fread(chars, 1, size, f)) > 0) {
2157
			xmlParseChunk(ctxt, chars, res, 0);
2158
		    }
2159
		    xmlParseChunk(ctxt, chars, 0, 1);
2160
		    doc = ctxt->myDoc;
2161
		    ret = ctxt->wellFormed;
2162
		    xmlFreeParserCtxt(ctxt);
2163
		    if (!ret) {
2164
			xmlFreeDoc(doc);
2165
			doc = NULL;
2166
		    }
2167
	        }
2168
	    }
2169
	} else
2170
#endif /* LIBXML_PUSH_ENABLED */
2171
        if (testIO) {
2172
	    if ((filename[0] == '-') && (filename[1] == 0)) {
2173
	        doc = xmlReadFd(0, NULL, NULL, options);
2174
	    } else {
2175
	        FILE *f;
2176
2177
#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2178
		f = fopen(filename, "rb");
2179
#else
2180
		f = fopen(filename, "r");
2181
#endif
2182
		if (f != NULL) {
2183
		    if (rectxt == NULL)
2184
			doc = xmlReadIO((xmlInputReadCallback) myRead,
2185
					(xmlInputCloseCallback) myClose, f,
2186
					filename, NULL, options);
2187
		    else
2188
			doc = xmlCtxtReadIO(rectxt,
2189
			                (xmlInputReadCallback) myRead,
2190
					(xmlInputCloseCallback) myClose, f,
2191
					filename, NULL, options);
2192
		} else
2193
		    doc = NULL;
2194
	    }
2195
	} else if (htmlout) {
2196
	    xmlParserCtxtPtr ctxt;
2197
2198
	    if (rectxt == NULL)
2199
		ctxt = xmlNewParserCtxt();
2200
	    else
2201
	        ctxt = rectxt;
2202
	    if (ctxt == NULL) {	      
2203
	        doc = NULL;
2204
	    } else {
2205
	        ctxt->sax->error = xmlHTMLError;
2206
	        ctxt->sax->warning = xmlHTMLWarning;
2207
	        ctxt->vctxt.error = xmlHTMLValidityError;
2208
	        ctxt->vctxt.warning = xmlHTMLValidityWarning;
2209
2210
		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2211
2212
		if (rectxt == NULL)
2213
		    xmlFreeParserCtxt(ctxt);
2214
	    }
2215
#ifdef HAVE_SYS_MMAN_H
2216
	} else if (memory) {
2217
	    int fd;
2218
	    struct stat info;
2219
	    const char *base;
2220
	    if (stat(filename, &info) < 0) 
2221
		return;
2222
	    if ((fd = open(filename, O_RDONLY)) < 0)
2223
		return;
2224
	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2225
	    if (base == (void *) MAP_FAILED)
2226
	        return;
2227
2228
	    if (rectxt == NULL)
2229
		doc = xmlReadMemory((char *) base, info.st_size,
2230
		                    filename, NULL, options);
2231
	    else
2232
		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
2233
			                filename, NULL, options);
2234
	        
2235
	    munmap((char *) base, info.st_size);
2236
	    close(fd);
2237
#endif
2238
#ifdef LIBXML_VALID_ENABLED
2239
	} else if (valid) {
2240
	    xmlParserCtxtPtr ctxt = NULL;
2241
2242
	    if (rectxt == NULL)
2243
		ctxt = xmlNewParserCtxt();
2244
	    else
2245
	        ctxt = rectxt;
2246
	    if (ctxt == NULL) {	      
2247
	        doc = NULL;
2248
	    } else {
2249
		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2250
2251
		if (ctxt->valid == 0)
2252
		    progresult = XMLLINT_ERR_RDFILE;
2253
		if (rectxt == NULL)
2254
		    xmlFreeParserCtxt(ctxt);
2255
	    }
2256
#endif /* LIBXML_VALID_ENABLED */
2257
	} else {
2258
	    if (rectxt != NULL)
2259
	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
2260
	    else {
2261
#ifdef LIBXML_SAX1_ENABLED
2262
                if (sax1)
2263
		    doc = xmlParseFile(filename);
2264
		else
2265
#endif /* LIBXML_SAX1_ENABLED */
2266
		doc = xmlReadFile(filename, NULL, options);
2267
	    }
2268
	}
2269
    }
2270
2271
    /*
2272
     * If we don't have a document we might as well give up.  Do we
2273
     * want an error message here?  <sven@zen.org> */
2274
    if (doc == NULL) {
2275
	progresult = XMLLINT_ERR_UNCLASS;
2276
	return;
2277
    }
2278
2279
    if ((timing) && (!repeat)) {
2280
	endTimer("Parsing");
2281
    }
2282
2283
    /*
2284
     * Remove DOCTYPE nodes
2285
     */
2286
    if (dropdtd) {
2287
	xmlDtdPtr dtd;
2288
2289
	dtd = xmlGetIntSubset(doc);
2290
	if (dtd != NULL) {
2291
	    xmlUnlinkNode((xmlNodePtr)dtd);
2292
	    xmlFreeDtd(dtd);
2293
	}
2294
    }
2295
2296
#ifdef LIBXML_XINCLUDE_ENABLED
2297
    if (xinclude) {
2298
	if ((timing) && (!repeat)) {
2299
	    startTimer();
2300
	}
2301
	if (xmlXIncludeProcessFlags(doc, options) < 0)
2302
	    progresult = XMLLINT_ERR_UNCLASS;
2303
	if ((timing) && (!repeat)) {
2304
	    endTimer("Xinclude processing");
2305
	}
2306
    }
2307
#endif
2308
2309
#ifdef LIBXML_DEBUG_ENABLED
2310
#ifdef LIBXML_XPATH_ENABLED
2311
    /*
2312
     * shell interaction
2313
     */
2314
    if (shell) {
2315
        xmlXPathOrderDocElems(doc);
2316
        xmlShell(doc, filename, xmlShellReadline, stdout);
2317
    }
2318
#endif
2319
#endif
2320
2321
#ifdef LIBXML_TREE_ENABLED
2322
    /*
2323
     * test intermediate copy if needed.
2324
     */
2325
    if (copy) {
2326
        tmp = doc;
2327
	if (timing) {
2328
	    startTimer();
2329
	}
2330
	doc = xmlCopyDoc(doc, 1);
2331
	if (timing) {
2332
	    endTimer("Copying");
2333
	}
2334
	if (timing) {
2335
	    startTimer();
2336
	}
2337
	xmlFreeDoc(tmp);
2338
	if (timing) {
2339
	    endTimer("Freeing original");
2340
	}
2341
    }
2342
#endif /* LIBXML_TREE_ENABLED */
2343
2344
#ifdef LIBXML_VALID_ENABLED
2345
    if ((insert) && (!html)) {
2346
        const xmlChar* list[256];
2347
	int nb, i;
2348
	xmlNodePtr node;
2349
2350
	if (doc->children != NULL) {
2351
	    node = doc->children;
2352
	    while ((node != NULL) && (node->last == NULL)) node = node->next;
2353
	    if (node != NULL) {
2354
		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2355
		if (nb < 0) {
2356
		    fprintf(stderr, "could not get valid list of elements\n");
2357
		} else if (nb == 0) {
2358
		    fprintf(stderr, "No element can be inserted under root\n");
2359
		} else {
2360
		    fprintf(stderr, "%d element types can be inserted under root:\n",
2361
		           nb);
2362
		    for (i = 0;i < nb;i++) {
2363
			 fprintf(stderr, "%s\n", (char *) list[i]);
2364
		    }
2365
		}
2366
	    }
2367
	}    
2368
    }else
2369
#endif /* LIBXML_VALID_ENABLED */
2370
#ifdef LIBXML_READER_ENABLED
2371
    if (walker) {
2372
        walkDoc(doc);
2373
    }
2374
#endif /* LIBXML_READER_ENABLED */
2375
#ifdef LIBXML_OUTPUT_ENABLED
2376
    if (noout == 0) {
2377
        int ret;
2378
2379
	/*
2380
	 * print it.
2381
	 */
2382
#ifdef LIBXML_DEBUG_ENABLED
2383
	if (!debug) {
2384
#endif
2385
	    if ((timing) && (!repeat)) {
2386
		startTimer();
2387
	    }
2388
#ifdef LIBXML_HTML_ENABLED
2389
            if ((html) && (!xmlout)) {
2390
		if (compress) {
2391
		    htmlSaveFile(output ? output : "-", doc);
2392
		}
2393
		else if (encoding != NULL) {
2394
		    if ( format ) {
2395
			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
2396
		    }
2397
		    else {
2398
			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
2399
		    }
2400
		}
2401
		else if (format) {
2402
		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
2403
		}
2404
		else {
2405
		    FILE *out;
2406
		    if (output == NULL)
2407
			out = stdout;
2408
		    else {
2409
			out = fopen(output,"wb");
2410
		    }
2411
		    if (out != NULL) {
2412
			if (htmlDocDump(out, doc) < 0)
2413
			    progresult = XMLLINT_ERR_OUT;
2414
2415
			if (output != NULL)
2416
			    fclose(out);
2417
		    } else {
2418
			fprintf(stderr, "failed to open %s\n", output);
2419
			progresult = XMLLINT_ERR_OUT;
2420
		    }
2421
		}
2422
		if ((timing) && (!repeat)) {
2423
		    endTimer("Saving");
2424
		}
2425
	    } else
2426
#endif
2427
#ifdef LIBXML_C14N_ENABLED
2428
            if (canonical) {
2429
	        xmlChar *result = NULL;
2430
		int size;
2431
2432
		size = xmlC14NDocDumpMemory(doc, NULL, 0, NULL, 1, &result);
2433
		if (size >= 0) {
2434
		    write(1, result, size);
2435
		    xmlFree(result);
2436
		} else {
2437
		    fprintf(stderr, "Failed to canonicalize\n");
2438
		    progresult = XMLLINT_ERR_OUT;
2439
		}
2440
	    } else
2441
            if (exc_canonical) {
2442
	        xmlChar *result = NULL;
2443
		int size;
2444
2445
		size = xmlC14NDocDumpMemory(doc, NULL, 1, NULL, 1, &result);
2446
		if (size >= 0) {
2447
		    write(1, result, size);
2448
		    xmlFree(result);
2449
		} else {
2450
		    fprintf(stderr, "Failed to canonicalize\n");
2451
		    progresult = XMLLINT_ERR_OUT;
2452
		}
2453
	    } else
2454
#endif
2455
#ifdef HAVE_SYS_MMAN_H
2456
	    if (memory) {
2457
		xmlChar *result;
2458
		int len;
2459
2460
		if (encoding != NULL) {
2461
		    if ( format ) {
2462
		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
2463
		    } else { 
2464
			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
2465
		    }
2466
		} else {
2467
		    if (format)
2468
			xmlDocDumpFormatMemory(doc, &result, &len, 1);
2469
		    else
2470
			xmlDocDumpMemory(doc, &result, &len);
2471
		}
2472
		if (result == NULL) {
2473
		    fprintf(stderr, "Failed to save\n");
2474
		    progresult = XMLLINT_ERR_OUT;
2475
		} else {
2476
		    write(1, result, len);
2477
		    xmlFree(result);
2478
		}
2479
2480
	    } else
2481
#endif /* HAVE_SYS_MMAN_H */
2482
	    if (compress) {
2483
		xmlSaveFile(output ? output : "-", doc);
2484
	    } else if (oldout) {
2485
	        if (encoding != NULL) {
2486
		    if ( format ) {
2487
			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
2488
						   encoding, 1);
2489
		    }
2490
		    else {
2491
			ret = xmlSaveFileEnc(output ? output : "-", doc,
2492
			                     encoding);
2493
		    }
2494
		    if (ret < 0) {
2495
			fprintf(stderr, "failed save to %s\n",
2496
				output ? output : "-");
2497
			progresult = XMLLINT_ERR_OUT;
2498
		    }
2499
		} else if (format) {
2500
		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
2501
		    if (ret < 0) {
2502
			fprintf(stderr, "failed save to %s\n",
2503
				output ? output : "-");
2504
			progresult = XMLLINT_ERR_OUT;
2505
		    }
2506
		} else {
2507
		    FILE *out;
2508
		    if (output == NULL)
2509
			out = stdout;
2510
		    else {
2511
			out = fopen(output,"wb");
2512
		    }
2513
		    if (out != NULL) {
2514
			if (xmlDocDump(out, doc) < 0)
2515
			    progresult = XMLLINT_ERR_OUT;
2516
2517
			if (output != NULL)
2518
			    fclose(out);
2519
		    } else {
2520
			fprintf(stderr, "failed to open %s\n", output);
2521
			progresult = XMLLINT_ERR_OUT;
2522
		    }
2523
		}
2524
	    } else {
2525
	        xmlSaveCtxtPtr ctxt;
2526
		int saveOpts = 0;
2527
2528
                if (format)
2529
		    saveOpts |= XML_SAVE_FORMAT;
2530
2531
		if (output == NULL)
2532
		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
2533
		else
2534
		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
2535
2536
		if (ctxt != NULL) {
2537
		    if (xmlSaveDoc(ctxt, doc) < 0) {
2538
			fprintf(stderr, "failed save to %s\n",
2539
				output ? output : "-");
2540
			progresult = XMLLINT_ERR_OUT;
2541
		    }
2542
		    xmlSaveClose(ctxt);
2543
		} else {
2544
		    progresult = XMLLINT_ERR_OUT;
2545
		}
2546
	    }
2547
	    if ((timing) && (!repeat)) {
2548
		endTimer("Saving");
2549
	    }
2550
#ifdef LIBXML_DEBUG_ENABLED
2551
	} else {
2552
	    FILE *out;
2553
	    if (output == NULL)
2554
	        out = stdout;
2555
	    else {
2556
		out = fopen(output,"wb");
2557
	    }
2558
	    if (out != NULL) {
2559
		xmlDebugDumpDocument(out, doc);
2560
2561
		if (output != NULL)
2562
		    fclose(out);
2563
	    } else {
2564
		fprintf(stderr, "failed to open %s\n", output);
2565
		progresult = XMLLINT_ERR_OUT;
2566
	    }
2567
	}
2568
#endif
2569
    }
2570
#endif /* LIBXML_OUTPUT_ENABLED */
2571
2572
#ifdef LIBXML_VALID_ENABLED
2573
    /*
2574
     * A posteriori validation test
2575
     */
2576
    if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
2577
	xmlDtdPtr dtd;
2578
2579
	if ((timing) && (!repeat)) {
2580
	    startTimer();
2581
	}
2582
	if (dtdvalid != NULL)
2583
	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid); 
2584
	else
2585
	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL); 
2586
	if ((timing) && (!repeat)) {
2587
	    endTimer("Parsing DTD");
2588
	}
2589
	if (dtd == NULL) {
2590
	    if (dtdvalid != NULL)
2591
		xmlGenericError(xmlGenericErrorContext,
2592
			"Could not parse DTD %s\n", dtdvalid);
2593
	    else
2594
		xmlGenericError(xmlGenericErrorContext,
2595
			"Could not parse DTD %s\n", dtdvalidfpi);
2596
	    progresult = XMLLINT_ERR_DTD;
2597
	} else {
2598
	    xmlValidCtxtPtr cvp;
2599
2600
	    if ((cvp = xmlNewValidCtxt()) == NULL) {
2601
		xmlGenericError(xmlGenericErrorContext,
2602
			"Couldn't allocate validation context\n");
2603
		exit(-1);
2604
	    }
2605
	    cvp->userData = (void *) stderr;
2606
	    cvp->error    = (xmlValidityErrorFunc) fprintf;
2607
	    cvp->warning  = (xmlValidityWarningFunc) fprintf;
2608
2609
	    if ((timing) && (!repeat)) {
2610
		startTimer();
2611
	    }
2612
	    if (!xmlValidateDtd(cvp, doc, dtd)) {
2613
		if (dtdvalid != NULL)
2614
		    xmlGenericError(xmlGenericErrorContext,
2615
			    "Document %s does not validate against %s\n",
2616
			    filename, dtdvalid);
2617
		else
2618
		    xmlGenericError(xmlGenericErrorContext,
2619
			    "Document %s does not validate against %s\n",
2620
			    filename, dtdvalidfpi);
2621
		progresult = XMLLINT_ERR_VALID;
2622
	    }
2623
	    if ((timing) && (!repeat)) {
2624
		endTimer("Validating against DTD");
2625
	    }
2626
	    xmlFreeValidCtxt(cvp);
2627
	    xmlFreeDtd(dtd);
2628
	}
2629
    } else if (postvalid) {
2630
	xmlValidCtxtPtr cvp;
2631
2632
	if ((cvp = xmlNewValidCtxt()) == NULL) {
2633
	    xmlGenericError(xmlGenericErrorContext,
2634
		    "Couldn't allocate validation context\n");
2635
	    exit(-1);
2636
	}
2637
2638
	if ((timing) && (!repeat)) {
2639
	    startTimer();
2640
	}
2641
	cvp->userData = (void *) stderr;
2642
	cvp->error    = (xmlValidityErrorFunc) fprintf;
2643
	cvp->warning  = (xmlValidityWarningFunc) fprintf;
2644
	if (!xmlValidateDocument(cvp, doc)) {
2645
	    xmlGenericError(xmlGenericErrorContext,
2646
		    "Document %s does not validate\n", filename);
2647
	    progresult = XMLLINT_ERR_VALID;
2648
	}
2649
	if ((timing) && (!repeat)) {
2650
	    endTimer("Validating");
2651
	}
2652
	xmlFreeValidCtxt(cvp);
2653
    }
2654
#endif /* LIBXML_VALID_ENABLED */
2655
#ifdef LIBXML_SCHEMATRON_ENABLED
2656
    if (wxschematron != NULL) {
2657
	xmlSchematronValidCtxtPtr ctxt;
2658
	int ret;
2659
	int flag;
2660
2661
	if ((timing) && (!repeat)) {
2662
	    startTimer();
2663
	}
2664
2665
	if (debug)
2666
	    flag = XML_SCHEMATRON_OUT_XML;
2667
	else
2668
	    flag = XML_SCHEMATRON_OUT_TEXT;
2669
	if (noout)
2670
	    flag |= XML_SCHEMATRON_OUT_QUIET;
2671
	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
2672
#if 0
2673
	xmlSchematronSetValidErrors(ctxt,
2674
		(xmlSchematronValidityErrorFunc) fprintf,
2675
		(xmlSchematronValidityWarningFunc) fprintf,
2676
		stderr);
2677
#endif
2678
	ret = xmlSchematronValidateDoc(ctxt, doc);
2679
	if (ret == 0) {
2680
	    fprintf(stderr, "%s validates\n", filename);
2681
	} else if (ret > 0) {
2682
	    fprintf(stderr, "%s fails to validate\n", filename);
2683
	    progresult = XMLLINT_ERR_VALID;
2684
	} else {
2685
	    fprintf(stderr, "%s validation generated an internal error\n",
2686
		   filename);
2687
	    progresult = XMLLINT_ERR_VALID;
2688
	}
2689
	xmlSchematronFreeValidCtxt(ctxt);
2690
	if ((timing) && (!repeat)) {
2691
	    endTimer("Validating");
2692
	}
2693
    }
2694
#endif
2695
#ifdef LIBXML_SCHEMAS_ENABLED
2696
    if (relaxngschemas != NULL) {
2697
	xmlRelaxNGValidCtxtPtr ctxt;
2698
	int ret;
2699
2700
	if ((timing) && (!repeat)) {
2701
	    startTimer();
2702
	}
2703
2704
	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2705
	xmlRelaxNGSetValidErrors(ctxt,
2706
		(xmlRelaxNGValidityErrorFunc) fprintf,
2707
		(xmlRelaxNGValidityWarningFunc) fprintf,
2708
		stderr);
2709
	ret = xmlRelaxNGValidateDoc(ctxt, doc);
2710
	if (ret == 0) {
2711
	    fprintf(stderr, "%s validates\n", filename);
2712
	} else if (ret > 0) {
2713
	    fprintf(stderr, "%s fails to validate\n", filename);
2714
	    progresult = XMLLINT_ERR_VALID;
2715
	} else {
2716
	    fprintf(stderr, "%s validation generated an internal error\n",
2717
		   filename);
2718
	    progresult = XMLLINT_ERR_VALID;
2719
	}
2720
	xmlRelaxNGFreeValidCtxt(ctxt);
2721
	if ((timing) && (!repeat)) {
2722
	    endTimer("Validating");
2723
	}
2724
    } else if (wxschemas != NULL) {
2725
	xmlSchemaValidCtxtPtr ctxt;
2726
	int ret;
2727
2728
	if ((timing) && (!repeat)) {
2729
	    startTimer();
2730
	}
2731
2732
	ctxt = xmlSchemaNewValidCtxt(wxschemas);
2733
	xmlSchemaSetValidErrors(ctxt,
2734
		(xmlSchemaValidityErrorFunc) fprintf,
2735
		(xmlSchemaValidityWarningFunc) fprintf,
2736
		stderr);
2737
	ret = xmlSchemaValidateDoc(ctxt, doc);
2738
	if (ret == 0) {
2739
	    fprintf(stderr, "%s validates\n", filename);
2740
	} else if (ret > 0) {
2741
	    fprintf(stderr, "%s fails to validate\n", filename);
2742
	    progresult = XMLLINT_ERR_VALID;
2743
	} else {
2744
	    fprintf(stderr, "%s validation generated an internal error\n",
2745
		   filename);
2746
	    progresult = XMLLINT_ERR_VALID;
2747
	}
2748
	xmlSchemaFreeValidCtxt(ctxt);
2749
	if ((timing) && (!repeat)) {
2750
	    endTimer("Validating");
2751
	}
2752
    }
2753
#endif
2754
2755
#ifdef LIBXML_DEBUG_ENABLED
2756
#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2757
    if ((debugent) && (!html))
2758
	xmlDebugDumpEntities(stderr, doc);
2759
#endif
2760
#endif
2761
2762
    /*
2763
     * free it.
2764
     */
2765
    if ((timing) && (!repeat)) {
2766
	startTimer();
2767
    }
2768
    xmlFreeDoc(doc);
2769
    if ((timing) && (!repeat)) {
2770
	endTimer("Freeing");
2771
    }
2772
}
2773
2774
/************************************************************************
2775
 * 									*
2776
 * 			Usage and Main					*
2777
 * 									*
2778
 ************************************************************************/
2779
2780
static void showVersion(const char *name) {
2781
    fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
2782
    fprintf(stderr, "   compiled with: ");
2783
    if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
2784
    if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
2785
    if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
2786
    if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
2787
    if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
2788
    if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
2789
    if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
2790
    if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
2791
    if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP "); 
2792
    if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP "); 
2793
    if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
2794
    if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML "); 
2795
    if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy "); 
2796
    if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N "); 
2797
    if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog "); 
2798
    if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath "); 
2799
    if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer "); 
2800
    if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude "); 
2801
    if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv "); 
2802
    if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X "); 
2803
    if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode "); 
2804
    if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps "); 
2805
    if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata "); 
2806
    if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr "); 
2807
    if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas "); 
2808
    if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron "); 
2809
    if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules "); 
2810
    if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug "); 
2811
    if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug "); 
2812
    if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug "); 
2813
    if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
2814
    fprintf(stderr, "\n");
2815
}
2816
2817
static void usage(const char *name) {
2818
    printf("Usage : %s [options] XMLfiles ...\n", name);
2819
#ifdef LIBXML_OUTPUT_ENABLED
2820
    printf("\tParse the XML files and output the result of the parsing\n");
2821
#else
2822
    printf("\tParse the XML files\n");
2823
#endif /* LIBXML_OUTPUT_ENABLED */
2824
    printf("\t--version : display the version of the XML library used\n");
2825
#ifdef LIBXML_DEBUG_ENABLED
2826
    printf("\t--debug : dump a debug tree of the in-memory document\n");
2827
    printf("\t--shell : run a navigating shell\n");
2828
    printf("\t--debugent : debug the entities defined in the document\n");
2829
#else
2830
#ifdef LIBXML_READER_ENABLED
2831
    printf("\t--debug : dump the nodes content when using --stream\n");
2832
#endif /* LIBXML_READER_ENABLED */
2833
#endif
2834
#ifdef LIBXML_TREE_ENABLED
2835
    printf("\t--copy : used to test the internal copy implementation\n");
2836
#endif /* LIBXML_TREE_ENABLED */
2837
    printf("\t--recover : output what was parsable on broken XML documents\n");
2838
    printf("\t--huge : remove any internal arbitrary parser limits\n");
2839
    printf("\t--noent : substitute entity references by their value\n");
2840
    printf("\t--noout : don't output the result tree\n");
2841
    printf("\t--path 'paths': provide a set of paths for resources\n");
2842
    printf("\t--load-trace : print trace of all external entites loaded\n");
2843
    printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
2844
    printf("\t--nocompact : do not generate compact text nodes\n");
2845
    printf("\t--htmlout : output results as HTML\n");
2846
    printf("\t--nowrap : do not put HTML doc wrapper\n");
2847
#ifdef LIBXML_VALID_ENABLED
2848
    printf("\t--valid : validate the document in addition to std well-formed check\n");
2849
    printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
2850
    printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
2851
    printf("\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
2852
#endif /* LIBXML_VALID_ENABLED */
2853
    printf("\t--timing : print some timings\n");
2854
    printf("\t--output file or -o file: save to a given file\n");
2855
    printf("\t--repeat : repeat 100 times, for timing or profiling\n");
2856
    printf("\t--insert : ad-hoc test for valid insertions\n");
2857
#ifdef LIBXML_OUTPUT_ENABLED
2858
#ifdef HAVE_ZLIB_H
2859
    printf("\t--compress : turn on gzip compression of output\n");
2860
#endif
2861
#endif /* LIBXML_OUTPUT_ENABLED */
2862
#ifdef LIBXML_HTML_ENABLED
2863
    printf("\t--html : use the HTML parser\n");
2864
    printf("\t--xmlout : force to use the XML serializer when using --html\n");
2865
#endif
2866
#ifdef LIBXML_PUSH_ENABLED
2867
    printf("\t--push : use the push mode of the parser\n");
2868
#endif /* LIBXML_PUSH_ENABLED */
2869
#ifdef HAVE_SYS_MMAN_H
2870
    printf("\t--memory : parse from memory\n");
2871
#endif
2872
    printf("\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
2873
    printf("\t--nowarning : do not emit warnings from parser/validator\n");
2874
    printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
2875
    printf("\t--nocdata : replace cdata section with text nodes\n");
2876
#ifdef LIBXML_OUTPUT_ENABLED
2877
    printf("\t--format : reformat/reindent the input\n");
2878
    printf("\t--encode encoding : output in the given encoding\n");
2879
    printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
2880
#endif /* LIBXML_OUTPUT_ENABLED */
2881
    printf("\t--c14n : save in W3C canonical format (with comments)\n");
2882
    printf("\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
2883
#ifdef LIBXML_C14N_ENABLED
2884
#endif /* LIBXML_C14N_ENABLED */
2885
    printf("\t--nsclean : remove redundant namespace declarations\n");
2886
    printf("\t--testIO : test user I/O support\n");
2887
#ifdef LIBXML_CATALOG_ENABLED
2888
    printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
2889
    printf("\t             otherwise XML Catalogs starting from \n");
2890
    printf("\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
2891
    printf("\t--nocatalogs: deactivate all catalogs\n");
2892
#endif
2893
    printf("\t--auto : generate a small doc on the fly\n");
2894
#ifdef LIBXML_XINCLUDE_ENABLED
2895
    printf("\t--xinclude : do XInclude processing\n");
2896
    printf("\t--noxincludenode : same but do not generate XInclude nodes\n");
2897
    printf("\t--nofixup-base-uris : do not fixup xml:base uris\n");
2898
#endif
2899
    printf("\t--loaddtd : fetch external DTD\n");
2900
    printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
2901
#ifdef LIBXML_READER_ENABLED
2902
    printf("\t--stream : use the streaming interface to process very large files\n");
2903
    printf("\t--walker : create a reader and walk though the resulting doc\n");
2904
#endif /* LIBXML_READER_ENABLED */
2905
#ifdef LIBXML_PATTERN_ENABLED
2906
    printf("\t--pattern pattern_value : test the pattern support\n");
2907
#endif
2908
    printf("\t--chkregister : verify the node registration code\n");
2909
#ifdef LIBXML_SCHEMAS_ENABLED
2910
    printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
2911
    printf("\t--schema schema : do validation against the WXS schema\n");
2912
#endif
2913
#ifdef LIBXML_SCHEMATRON_ENABLED
2914
    printf("\t--schematron schema : do validation against a schematron\n");
2915
#endif
2916
#ifdef LIBXML_SAX1_ENABLED
2917
    printf("\t--sax1: use the old SAX1 interfaces for processing\n");
2918
#endif
2919
    printf("\t--sax: do not build a tree but work just at the SAX level\n");
2920
    printf("\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
2921
2922
    printf("\nLibxml project home page: http://xmlsoft.org/\n");
2923
    printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
2924
}
2925
2926
static void registerNode(xmlNodePtr node)
2927
{
2928
    node->_private = malloc(sizeof(long));
2929
    *(long*)node->_private = (long) 0x81726354;
2930
    nbregister++;
2931
}
2932
2933
static void deregisterNode(xmlNodePtr node)
2934
{
2935
    assert(node->_private != NULL);
2936
    assert(*(long*)node->_private == (long) 0x81726354);
2937
    free(node->_private);
2938
    nbregister--;
2939
}
2940
2941
int
2942
main(int argc, char **argv) {
2943
    int i, acount;
2944
    int files = 0;
2945
    int version = 0;
2946
    const char* indent;
2947
    
2948
    if (argc <= 1) {
2949
	usage(argv[0]);
2950
	return(1);
2951
    }
2952
    LIBXML_TEST_VERSION
2953
    for (i = 1; i < argc ; i++) {
2954
	if (!strcmp(argv[i], "-"))
2955
	    break;
2956
2957
	if (argv[i][0] != '-')
2958
	    continue;
2959
	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
2960
	    debug++;
2961
	else
2962
#ifdef LIBXML_DEBUG_ENABLED
2963
	if ((!strcmp(argv[i], "-shell")) ||
2964
	         (!strcmp(argv[i], "--shell"))) {
2965
	    shell++;
2966
            noout = 1;
2967
        } else 
2968
#endif
2969
#ifdef LIBXML_TREE_ENABLED
2970
	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
2971
	    copy++;
2972
	else
2973
#endif /* LIBXML_TREE_ENABLED */
2974
	if ((!strcmp(argv[i], "-recover")) ||
2975
	         (!strcmp(argv[i], "--recover"))) {
2976
	    recovery++;
2977
	    options |= XML_PARSE_RECOVER;
2978
	} else if ((!strcmp(argv[i], "-huge")) ||
2979
	         (!strcmp(argv[i], "--huge"))) {
2980
	    options |= XML_PARSE_HUGE;
2981
	} else if ((!strcmp(argv[i], "-noent")) ||
2982
	         (!strcmp(argv[i], "--noent"))) {
2983
	    noent++;
2984
	    options |= XML_PARSE_NOENT;
2985
	} else if ((!strcmp(argv[i], "-nsclean")) ||
2986
	         (!strcmp(argv[i], "--nsclean"))) {
2987
	    options |= XML_PARSE_NSCLEAN;
2988
	} else if ((!strcmp(argv[i], "-nocdata")) ||
2989
	         (!strcmp(argv[i], "--nocdata"))) {
2990
	    options |= XML_PARSE_NOCDATA;
2991
	} else if ((!strcmp(argv[i], "-nodict")) ||
2992
	         (!strcmp(argv[i], "--nodict"))) {
2993
	    options |= XML_PARSE_NODICT;
2994
	} else if ((!strcmp(argv[i], "-version")) ||
2995
	         (!strcmp(argv[i], "--version"))) {
2996
	    showVersion(argv[0]);
2997
	    version = 1;
2998
	} else if ((!strcmp(argv[i], "-noout")) ||
2999
	         (!strcmp(argv[i], "--noout")))
3000
	    noout++;
3001
#ifdef LIBXML_OUTPUT_ENABLED
3002
	else if ((!strcmp(argv[i], "-o")) ||
3003
	         (!strcmp(argv[i], "-output")) ||
3004
	         (!strcmp(argv[i], "--output"))) {
3005
	    i++;
3006
	    output = argv[i];
3007
	}
3008
#endif /* LIBXML_OUTPUT_ENABLED */
3009
	else if ((!strcmp(argv[i], "-htmlout")) ||
3010
	         (!strcmp(argv[i], "--htmlout")))
3011
	    htmlout++;
3012
	else if ((!strcmp(argv[i], "-nowrap")) ||
3013
	         (!strcmp(argv[i], "--nowrap")))
3014
	    nowrap++;
3015
#ifdef LIBXML_HTML_ENABLED
3016
	else if ((!strcmp(argv[i], "-html")) ||
3017
	         (!strcmp(argv[i], "--html"))) {
3018
	    html++;
3019
        }
3020
	else if ((!strcmp(argv[i], "-xmlout")) ||
3021
	         (!strcmp(argv[i], "--xmlout"))) {
3022
	    xmlout++;
3023
        }
3024
#endif /* LIBXML_HTML_ENABLED */
3025
	else if ((!strcmp(argv[i], "-loaddtd")) ||
3026
	         (!strcmp(argv[i], "--loaddtd"))) {
3027
	    loaddtd++;
3028
	    options |= XML_PARSE_DTDLOAD;
3029
	} else if ((!strcmp(argv[i], "-dtdattr")) ||
3030
	         (!strcmp(argv[i], "--dtdattr"))) {
3031
	    loaddtd++;
3032
	    dtdattrs++;
3033
	    options |= XML_PARSE_DTDATTR;
3034
	}
3035
#ifdef LIBXML_VALID_ENABLED
3036
	else if ((!strcmp(argv[i], "-valid")) ||
3037
	         (!strcmp(argv[i], "--valid"))) {
3038
	    valid++;
3039
	    options |= XML_PARSE_DTDVALID;
3040
	} else if ((!strcmp(argv[i], "-postvalid")) ||
3041
	         (!strcmp(argv[i], "--postvalid"))) {
3042
	    postvalid++;
3043
	    loaddtd++;
3044
	    options |= XML_PARSE_DTDLOAD;
3045
	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
3046
	         (!strcmp(argv[i], "--dtdvalid"))) {
3047
	    i++;
3048
	    dtdvalid = argv[i];
3049
	    loaddtd++;
3050
	    options |= XML_PARSE_DTDLOAD;
3051
	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3052
	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3053
	    i++;
3054
	    dtdvalidfpi = argv[i];
3055
	    loaddtd++;
3056
	    options |= XML_PARSE_DTDLOAD;
3057
        }
3058
#endif /* LIBXML_VALID_ENABLED */
3059
	else if ((!strcmp(argv[i], "-dropdtd")) ||
3060
	         (!strcmp(argv[i], "--dropdtd")))
3061
	    dropdtd++;
3062
	else if ((!strcmp(argv[i], "-insert")) ||
3063
	         (!strcmp(argv[i], "--insert")))
3064
	    insert++;
3065
	else if ((!strcmp(argv[i], "-timing")) ||
3066
	         (!strcmp(argv[i], "--timing")))
3067
	    timing++;
3068
	else if ((!strcmp(argv[i], "-auto")) ||
3069
	         (!strcmp(argv[i], "--auto")))
3070
	    generate++;
3071
	else if ((!strcmp(argv[i], "-repeat")) ||
3072
	         (!strcmp(argv[i], "--repeat"))) {
3073
	    if (repeat)
3074
	        repeat *= 10;
3075
	    else
3076
	        repeat = 100;
3077
	}
3078
#ifdef LIBXML_PUSH_ENABLED
3079
	else if ((!strcmp(argv[i], "-push")) ||
3080
	         (!strcmp(argv[i], "--push")))
3081
	    push++;
3082
#endif /* LIBXML_PUSH_ENABLED */
3083
#ifdef HAVE_SYS_MMAN_H
3084
	else if ((!strcmp(argv[i], "-memory")) ||
3085
	         (!strcmp(argv[i], "--memory")))
3086
	    memory++;
3087
#endif
3088
	else if ((!strcmp(argv[i], "-testIO")) ||
3089
	         (!strcmp(argv[i], "--testIO")))
3090
	    testIO++;
3091
#ifdef LIBXML_XINCLUDE_ENABLED
3092
	else if ((!strcmp(argv[i], "-xinclude")) ||
3093
	         (!strcmp(argv[i], "--xinclude"))) {
3094
	    xinclude++;
3095
	    options |= XML_PARSE_XINCLUDE;
3096
	}
3097
	else if ((!strcmp(argv[i], "-noxincludenode")) ||
3098
	         (!strcmp(argv[i], "--noxincludenode"))) {
3099
	    xinclude++;
3100
	    options |= XML_PARSE_XINCLUDE;
3101
	    options |= XML_PARSE_NOXINCNODE;
3102
	}
3103
	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3104
	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
3105
	    xinclude++;
3106
	    options |= XML_PARSE_XINCLUDE;
3107
	    options |= XML_PARSE_NOBASEFIX;
3108
	}
3109
#endif
3110
#ifdef LIBXML_OUTPUT_ENABLED
3111
#ifdef HAVE_ZLIB_H
3112
	else if ((!strcmp(argv[i], "-compress")) ||
3113
	         (!strcmp(argv[i], "--compress"))) {
3114
	    compress++;
3115
	    xmlSetCompressMode(9);
3116
        }
3117
#endif
3118
#endif /* LIBXML_OUTPUT_ENABLED */
3119
	else if ((!strcmp(argv[i], "-nowarning")) ||
3120
	         (!strcmp(argv[i], "--nowarning"))) {
3121
	    xmlGetWarningsDefaultValue = 0;
3122
	    xmlPedanticParserDefault(0);
3123
	    options |= XML_PARSE_NOWARNING;
3124
        }
3125
	else if ((!strcmp(argv[i], "-pedantic")) ||
3126
	         (!strcmp(argv[i], "--pedantic"))) {
3127
	    xmlGetWarningsDefaultValue = 1;
3128
	    xmlPedanticParserDefault(1);
3129
	    options |= XML_PARSE_PEDANTIC;
3130
        }
3131
#ifdef LIBXML_DEBUG_ENABLED
3132
	else if ((!strcmp(argv[i], "-debugent")) ||
3133
		 (!strcmp(argv[i], "--debugent"))) {
3134
	    debugent++;
3135
	    xmlParserDebugEntities = 1;
3136
	} 
3137
#endif
3138
#ifdef LIBXML_C14N_ENABLED
3139
	else if ((!strcmp(argv[i], "-c14n")) ||
3140
		 (!strcmp(argv[i], "--c14n"))) {
3141
	    canonical++;
3142
	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3143
	} 
3144
	else if ((!strcmp(argv[i], "-exc-c14n")) ||
3145
		 (!strcmp(argv[i], "--exc-c14n"))) {
3146
	    exc_canonical++;
3147
	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3148
	} 
3149
#endif
3150
#ifdef LIBXML_CATALOG_ENABLED
3151
	else if ((!strcmp(argv[i], "-catalogs")) ||
3152
		 (!strcmp(argv[i], "--catalogs"))) {
3153
	    catalogs++;
3154
	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
3155
		 (!strcmp(argv[i], "--nocatalogs"))) {
3156
	    nocatalogs++;
3157
	} 
3158
#endif
3159
	else if ((!strcmp(argv[i], "-encode")) ||
3160
	         (!strcmp(argv[i], "--encode"))) {
3161
	    i++;
3162
	    encoding = argv[i];
3163
	    /*
3164
	     * OK it's for testing purposes
3165
	     */
3166
	    xmlAddEncodingAlias("UTF-8", "DVEnc");
3167
        }
3168
	else if ((!strcmp(argv[i], "-noblanks")) ||
3169
	         (!strcmp(argv[i], "--noblanks"))) {
3170
	     noblanks++;
3171
	     xmlKeepBlanksDefault(0);
3172
        }
3173
	else if ((!strcmp(argv[i], "-maxmem")) ||
3174
	         (!strcmp(argv[i], "--maxmem"))) {
3175
	     i++;
3176
	     if (sscanf(argv[i], "%d", &maxmem) == 1) {
3177
	         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
3178
		             myStrdupFunc);
3179
	     } else {
3180
	         maxmem = 0;
3181
	     }
3182
        }
3183
	else if ((!strcmp(argv[i], "-format")) ||
3184
	         (!strcmp(argv[i], "--format"))) {
3185
	     noblanks++;
3186
#ifdef LIBXML_OUTPUT_ENABLED
3187
	     format++;
3188
#endif /* LIBXML_OUTPUT_ENABLED */
3189
	     xmlKeepBlanksDefault(0);
3190
	}
3191
#ifdef LIBXML_READER_ENABLED
3192
	else if ((!strcmp(argv[i], "-stream")) ||
3193
	         (!strcmp(argv[i], "--stream"))) {
3194
	     stream++;
3195
	}
3196
	else if ((!strcmp(argv[i], "-walker")) ||
3197
	         (!strcmp(argv[i], "--walker"))) {
3198
	     walker++;
3199
             noout++;
3200
	}
3201
#endif /* LIBXML_READER_ENABLED */
3202
#ifdef LIBXML_SAX1_ENABLED
3203
	else if ((!strcmp(argv[i], "-sax1")) ||
3204
	         (!strcmp(argv[i], "--sax1"))) {
3205
	     sax1++;
3206
	}
3207
#endif /* LIBXML_SAX1_ENABLED */
3208
	else if ((!strcmp(argv[i], "-sax")) ||
3209
	         (!strcmp(argv[i], "--sax"))) {
3210
	     sax++;
3211
	}
3212
	else if ((!strcmp(argv[i], "-chkregister")) ||
3213
	         (!strcmp(argv[i], "--chkregister"))) {
3214
	     chkregister++;
3215
#ifdef LIBXML_SCHEMAS_ENABLED
3216
	} else if ((!strcmp(argv[i], "-relaxng")) ||
3217
	         (!strcmp(argv[i], "--relaxng"))) {
3218
	    i++;
3219
	    relaxng = argv[i];
3220
	    noent++;
3221
	    options |= XML_PARSE_NOENT;
3222
	} else if ((!strcmp(argv[i], "-schema")) ||
3223
	         (!strcmp(argv[i], "--schema"))) {
3224
	    i++;
3225
	    schema = argv[i];
3226
	    noent++;
3227
#endif
3228
#ifdef LIBXML_SCHEMATRON_ENABLED
3229
	} else if ((!strcmp(argv[i], "-schematron")) ||
3230
	         (!strcmp(argv[i], "--schematron"))) {
3231
	    i++;
3232
	    schematron = argv[i];
3233
	    noent++;
3234
#endif
3235
        } else if ((!strcmp(argv[i], "-nonet")) ||
3236
                   (!strcmp(argv[i], "--nonet"))) {
3237
	    options |= XML_PARSE_NONET;
3238
	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
3239
        } else if ((!strcmp(argv[i], "-nocompact")) ||
3240
                   (!strcmp(argv[i], "--nocompact"))) {
3241
	    options &= ~XML_PARSE_COMPACT;
3242
	} else if ((!strcmp(argv[i], "-load-trace")) ||
3243
	           (!strcmp(argv[i], "--load-trace"))) {
3244
	    load_trace++;
3245
        } else if ((!strcmp(argv[i], "-path")) ||
3246
                   (!strcmp(argv[i], "--path"))) {
3247
	    i++;
3248
	    parsePath(BAD_CAST argv[i]);
3249
#ifdef LIBXML_PATTERN_ENABLED
3250
        } else if ((!strcmp(argv[i], "-pattern")) ||
3251
                   (!strcmp(argv[i], "--pattern"))) {
3252
	    i++;
3253
	    pattern = argv[i];
3254
#endif
3255
	} else if ((!strcmp(argv[i], "-oldxml10")) ||
3256
	           (!strcmp(argv[i], "--oldxml10"))) {
3257
	    oldxml10++;
3258
	    options |= XML_PARSE_OLD10;
3259
	} else {
3260
	    fprintf(stderr, "Unknown option %s\n", argv[i]);
3261
	    usage(argv[0]);
3262
	    return(1);
3263
	}
3264
    }
3265
3266
#ifdef LIBXML_CATALOG_ENABLED
3267
    if (nocatalogs == 0) {
3268
	if (catalogs) {
3269
	    const char *catal;
3270
3271
	    catal = getenv("SGML_CATALOG_FILES");
3272
	    if (catal != NULL) {
3273
		xmlLoadCatalogs(catal);
3274
	    } else {
3275
		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
3276
	    }
3277
	}
3278
    }
3279
#endif
3280
3281
#ifdef LIBXML_SAX1_ENABLED
3282
    if (sax1)
3283
        xmlSAXDefaultVersion(1);
3284
    else
3285
        xmlSAXDefaultVersion(2);
3286
#endif /* LIBXML_SAX1_ENABLED */
3287
3288
    if (chkregister) {
3289
	xmlRegisterNodeDefault(registerNode);
3290
	xmlDeregisterNodeDefault(deregisterNode);
3291
    }
3292
    
3293
    indent = getenv("XMLLINT_INDENT");
3294
    if(indent != NULL) {
3295
	xmlTreeIndentString = indent;
3296
    }
3297
    
3298
3299
    defaultEntityLoader = xmlGetExternalEntityLoader();
3300
    xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
3301
3302
    xmlLineNumbersDefault(1);
3303
    if (loaddtd != 0)
3304
	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3305
    if (dtdattrs)
3306
	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
3307
    if (noent != 0) xmlSubstituteEntitiesDefault(1);
3308
#ifdef LIBXML_VALID_ENABLED
3309
    if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
3310
#endif /* LIBXML_VALID_ENABLED */
3311
    if ((htmlout) && (!nowrap)) {
3312
	xmlGenericError(xmlGenericErrorContext,
3313
         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3314
	xmlGenericError(xmlGenericErrorContext,
3315
		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3316
	xmlGenericError(xmlGenericErrorContext,
3317
	 "<html><head><title>%s output</title></head>\n",
3318
		argv[0]);
3319
	xmlGenericError(xmlGenericErrorContext, 
3320
	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3321
		argv[0]);
3322
    }
3323
3324
#ifdef LIBXML_SCHEMATRON_ENABLED
3325
    if ((schematron != NULL) && (sax == 0)
3326
#ifdef LIBXML_READER_ENABLED
3327
        && (stream == 0)
3328
#endif /* LIBXML_READER_ENABLED */
3329
	) {
3330
	xmlSchematronParserCtxtPtr ctxt;
3331
3332
        /* forces loading the DTDs */
3333
        xmlLoadExtDtdDefaultValue |= 1; 
3334
	options |= XML_PARSE_DTDLOAD;
3335
	if (timing) {
3336
	    startTimer();
3337
	}
3338
	ctxt = xmlSchematronNewParserCtxt(schematron);
3339
#if 0
3340
	xmlSchematronSetParserErrors(ctxt,
3341
		(xmlSchematronValidityErrorFunc) fprintf,
3342
		(xmlSchematronValidityWarningFunc) fprintf,
3343
		stderr);
3344
#endif
3345
	wxschematron = xmlSchematronParse(ctxt);
3346
	if (wxschematron == NULL) {
3347
	    xmlGenericError(xmlGenericErrorContext,
3348
		    "Schematron schema %s failed to compile\n", schematron);
3349
            progresult = XMLLINT_ERR_SCHEMACOMP;
3350
	    schematron = NULL;
3351
	}
3352
	xmlSchematronFreeParserCtxt(ctxt);
3353
	if (timing) {
3354
	    endTimer("Compiling the schemas");
3355
	}
3356
    }
3357
#endif
3358
#ifdef LIBXML_SCHEMAS_ENABLED
3359
    if ((relaxng != NULL) && (sax == 0)
3360
#ifdef LIBXML_READER_ENABLED
3361
        && (stream == 0)
3362
#endif /* LIBXML_READER_ENABLED */
3363
	) {
3364
	xmlRelaxNGParserCtxtPtr ctxt;
3365
3366
        /* forces loading the DTDs */
3367
        xmlLoadExtDtdDefaultValue |= 1; 
3368
	options |= XML_PARSE_DTDLOAD;
3369
	if (timing) {
3370
	    startTimer();
3371
	}
3372
	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
3373
	xmlRelaxNGSetParserErrors(ctxt,
3374
		(xmlRelaxNGValidityErrorFunc) fprintf,
3375
		(xmlRelaxNGValidityWarningFunc) fprintf,
3376
		stderr);
3377
	relaxngschemas = xmlRelaxNGParse(ctxt);
3378
	if (relaxngschemas == NULL) {
3379
	    xmlGenericError(xmlGenericErrorContext,
3380
		    "Relax-NG schema %s failed to compile\n", relaxng);
3381
            progresult = XMLLINT_ERR_SCHEMACOMP;
3382
	    relaxng = NULL;
3383
	}
3384
	xmlRelaxNGFreeParserCtxt(ctxt);
3385
	if (timing) {
3386
	    endTimer("Compiling the schemas");
3387
	}
3388
    } else if ((schema != NULL)
3389
#ifdef LIBXML_READER_ENABLED
3390
		&& (stream == 0)
3391
#endif
3392
	) {
3393
	xmlSchemaParserCtxtPtr ctxt;
3394
3395
	if (timing) {
3396
	    startTimer();
3397
	}
3398
	ctxt = xmlSchemaNewParserCtxt(schema);
3399
	xmlSchemaSetParserErrors(ctxt,
3400
		(xmlSchemaValidityErrorFunc) fprintf,
3401
		(xmlSchemaValidityWarningFunc) fprintf,
3402
		stderr);
3403
	wxschemas = xmlSchemaParse(ctxt);
3404
	if (wxschemas == NULL) {
3405
	    xmlGenericError(xmlGenericErrorContext,
3406
		    "WXS schema %s failed to compile\n", schema);
3407
            progresult = XMLLINT_ERR_SCHEMACOMP;
3408
	    schema = NULL;
3409
	}
3410
	xmlSchemaFreeParserCtxt(ctxt);
3411
	if (timing) {
3412
	    endTimer("Compiling the schemas");
3413
	}
3414
    }
3415
#endif /* LIBXML_SCHEMAS_ENABLED */
3416
#ifdef LIBXML_PATTERN_ENABLED
3417
    if ((pattern != NULL)
3418
#ifdef LIBXML_READER_ENABLED
3419
        && (walker == 0)
3420
#endif
3421
	) {
3422
        patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
3423
	if (patternc == NULL) {
3424
	    xmlGenericError(xmlGenericErrorContext,
3425
		    "Pattern %s failed to compile\n", pattern);
3426
            progresult = XMLLINT_ERR_SCHEMAPAT;
3427
	    pattern = NULL;
3428
	}
3429
    }
3430
#endif /* LIBXML_PATTERN_ENABLED */
3431
    for (i = 1; i < argc ; i++) {
3432
	if ((!strcmp(argv[i], "-encode")) ||
3433
	         (!strcmp(argv[i], "--encode"))) {
3434
	    i++;
3435
	    continue;
3436
        } else if ((!strcmp(argv[i], "-o")) ||
3437
                   (!strcmp(argv[i], "-output")) ||
3438
                   (!strcmp(argv[i], "--output"))) {
3439
            i++;
3440
	    continue;
3441
        }
3442
#ifdef LIBXML_VALID_ENABLED
3443
	if ((!strcmp(argv[i], "-dtdvalid")) ||
3444
	         (!strcmp(argv[i], "--dtdvalid"))) {
3445
	    i++;
3446
	    continue;
3447
        } 
3448
	if ((!strcmp(argv[i], "-path")) ||
3449
                   (!strcmp(argv[i], "--path"))) {
3450
            i++;
3451
	    continue;
3452
        }
3453
	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3454
	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3455
	    i++;
3456
	    continue;
3457
        }
3458
#endif /* LIBXML_VALID_ENABLED */
3459
	if ((!strcmp(argv[i], "-relaxng")) ||
3460
	         (!strcmp(argv[i], "--relaxng"))) {
3461
	    i++;
3462
	    continue;
3463
        }
3464
	if ((!strcmp(argv[i], "-maxmem")) ||
3465
	         (!strcmp(argv[i], "--maxmem"))) {
3466
	    i++;
3467
	    continue;
3468
        }
3469
	if ((!strcmp(argv[i], "-schema")) ||
3470
	         (!strcmp(argv[i], "--schema"))) {
3471
	    i++;
3472
	    continue;
3473
        }
3474
	if ((!strcmp(argv[i], "-schematron")) ||
3475
	         (!strcmp(argv[i], "--schematron"))) {
3476
	    i++;
3477
	    continue;
3478
        }
3479
#ifdef LIBXML_PATTERN_ENABLED
3480
        if ((!strcmp(argv[i], "-pattern")) ||
3481
	    (!strcmp(argv[i], "--pattern"))) {
3482
	    i++;
3483
	    continue;
3484
	}
3485
#endif
3486
	if ((timing) && (repeat))
3487
	    startTimer();
3488
	/* Remember file names.  "-" means stdin.  <sven@zen.org> */
3489
	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
3490
	    if (repeat) {
3491
		xmlParserCtxtPtr ctxt = NULL;
3492
3493
		for (acount = 0;acount < repeat;acount++) {
3494
#ifdef LIBXML_READER_ENABLED
3495
		    if (stream != 0) {
3496
			streamFile(argv[i]);
3497
		    } else {
3498
#endif /* LIBXML_READER_ENABLED */
3499
                        if (sax) {
3500
			    testSAX(argv[i]);
3501
			} else {
3502
			    if (ctxt == NULL)
3503
				ctxt = xmlNewParserCtxt();
3504
			    parseAndPrintFile(argv[i], ctxt);
3505
			}
3506
#ifdef LIBXML_READER_ENABLED
3507
		    }
3508
#endif /* LIBXML_READER_ENABLED */
3509
		}
3510
		if (ctxt != NULL)
3511
		    xmlFreeParserCtxt(ctxt);
3512
	    } else {
3513
		nbregister = 0;
3514
3515
#ifdef LIBXML_READER_ENABLED
3516
		if (stream != 0)
3517
		    streamFile(argv[i]);
3518
		else
3519
#endif /* LIBXML_READER_ENABLED */
3520
                if (sax) {
3521
		    testSAX(argv[i]);
3522
		} else {
3523
		    parseAndPrintFile(argv[i], NULL);
3524
		}
3525
3526
                if ((chkregister) && (nbregister != 0)) {
3527
		    fprintf(stderr, "Registration count off: %d\n", nbregister);
3528
		    progresult = XMLLINT_ERR_RDREGIS;
3529
		}
3530
	    }
3531
	    files ++;
3532
	    if ((timing) && (repeat)) {
3533
		endTimer("%d iterations", repeat);
3534
	    }
3535
	}
3536
    }
3537
    if (generate) 
3538
	parseAndPrintFile(NULL, NULL);
3539
    if ((htmlout) && (!nowrap)) {
3540
	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
3541
    }
3542
    if ((files == 0) && (!generate) && (version == 0)) {
3543
	usage(argv[0]);
3544
    }
3545
#ifdef LIBXML_SCHEMATRON_ENABLED
3546
    if (wxschematron != NULL)
3547
	xmlSchematronFree(wxschematron);
3548
#endif
3549
#ifdef LIBXML_SCHEMAS_ENABLED
3550
    if (relaxngschemas != NULL)
3551
	xmlRelaxNGFree(relaxngschemas);
3552
    if (wxschemas != NULL)
3553
	xmlSchemaFree(wxschemas);
3554
    xmlRelaxNGCleanupTypes();
3555
#endif
3556
#ifdef LIBXML_PATTERN_ENABLED
3557
    if (patternc != NULL)
3558
        xmlFreePattern(patternc);
3559
#endif
3560
    xmlCleanupParser();
3561
    xmlMemoryDump();
3562
3563
    return(progresult);
3564
}