blob: f35187a39b65eb52c59191458d551ca51fcd83a3 [file] [log] [blame]
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001/*
2 * xmllint.c : a small tester program for XML input.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00006 * daniel@veillard.com
Daniel Veillardce8b83b2000-04-05 18:38:42 +00007 */
8
Bjorn Reese70a9da52001-04-21 16:57:29 +00009#include "libxml.h"
Daniel Veillardce8b83b2000-04-05 18:38:42 +000010
Daniel Veillardce8b83b2000-04-05 18:38:42 +000011#include <string.h>
Daniel Veillardce8b83b2000-04-05 18:38:42 +000012#include <stdarg.h>
Daniel Veillard28ae6362001-07-14 16:44:32 +000013
Daniel Veillard2d90de42001-04-16 17:46:18 +000014#ifdef _WIN32
15#ifdef _MSC_VER
16#include <winsock2.h>
17#pragma comment(lib, "ws2_32.lib")
18#define gettimeofday(p1,p2)
Daniel Veillard28ae6362001-07-14 16:44:32 +000019#else /* _MSC_VER */
20#include <sys/time.h>
Daniel Veillard2d90de42001-04-16 17:46:18 +000021#endif /* _MSC_VER */
22#else /* _WIN32 */
Daniel Veillarded472f32001-12-13 08:48:14 +000023#ifdef HAVE_SYS_TIME_H
Daniel Veillard48b2f892001-02-25 16:11:03 +000024#include <sys/time.h>
Daniel Veillarded472f32001-12-13 08:48:14 +000025#endif
Daniel Veillard01db67c2001-12-18 07:09:59 +000026#ifdef HAVE_TIME_H
27#include <time.h>
28#endif
Daniel Veillard2d90de42001-04-16 17:46:18 +000029#endif /* _WIN32 */
Daniel Veillard48b2f892001-02-25 16:11:03 +000030
Daniel Veillardce8b83b2000-04-05 18:38:42 +000031
32#ifdef HAVE_SYS_TYPES_H
33#include <sys/types.h>
34#endif
35#ifdef HAVE_SYS_STAT_H
36#include <sys/stat.h>
37#endif
38#ifdef HAVE_FCNTL_H
39#include <fcntl.h>
40#endif
41#ifdef HAVE_UNISTD_H
42#include <unistd.h>
43#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000044#ifdef HAVE_SYS_MMAN_H
45#include <sys/mman.h>
Daniel Veillard87b95392000-08-12 21:12:04 +000046/* seems needed for Solaris */
47#ifndef MAP_FAILED
48#define MAP_FAILED ((void *) -1)
49#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000050#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000051#ifdef HAVE_STDLIB_H
52#include <stdlib.h>
53#endif
54#ifdef HAVE_LIBREADLINE
55#include <readline/readline.h>
56#ifdef HAVE_LIBHISTORY
57#include <readline/history.h>
58#endif
59#endif
60
61#include <libxml/xmlmemory.h>
62#include <libxml/parser.h>
63#include <libxml/parserInternals.h>
64#include <libxml/HTMLparser.h>
65#include <libxml/HTMLtree.h>
66#include <libxml/tree.h>
67#include <libxml/xpath.h>
68#include <libxml/debugXML.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000069#include <libxml/xmlerror.h>
Daniel Veillard9e8bfae2000-11-06 16:43:11 +000070#ifdef LIBXML_XINCLUDE_ENABLED
71#include <libxml/xinclude.h>
72#endif
Daniel Veillard81418e32001-05-22 15:08:55 +000073#ifdef LIBXML_CATALOG_ENABLED
74#include <libxml/catalog.h>
75#endif
Daniel Veillard89cad532001-10-22 09:46:13 +000076#ifdef LIBXML_DOCB_ENABLED
77#include <libxml/DOCBparser.h>
78#endif
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000079#include <libxml/globals.h>
Daniel Veillardce8b83b2000-04-05 18:38:42 +000080
81#ifdef LIBXML_DEBUG_ENABLED
82static int debug = 0;
83static int shell = 0;
84static int debugent = 0;
85#endif
86static int copy = 0;
87static int recovery = 0;
88static int noent = 0;
89static int noout = 0;
90static int nowrap = 0;
91static int valid = 0;
92static int postvalid = 0;
Daniel Veillardcd429612000-10-11 15:57:05 +000093static char * dtdvalid = NULL;
Daniel Veillardce8b83b2000-04-05 18:38:42 +000094static int repeat = 0;
95static int insert = 0;
96static int compress = 0;
Daniel Veillard89cad532001-10-22 09:46:13 +000097#ifdef LIBXML_DOCB_ENABLED
98static int sgml = 0;
99#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000100static int html = 0;
101static int htmlout = 0;
102static int push = 0;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000103#ifdef HAVE_SYS_MMAN_H
104static int memory = 0;
105#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000106static int noblanks = 0;
Daniel Veillard90493a92001-08-14 14:12:47 +0000107static int format = 0;
Daniel Veillard5e873c42000-04-12 13:27:38 +0000108static int testIO = 0;
Daniel Veillardbe803962000-06-28 23:40:59 +0000109static char *encoding = NULL;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000110#ifdef LIBXML_XINCLUDE_ENABLED
111static int xinclude = 0;
112#endif
Daniel Veillard48da9102001-08-07 01:10:10 +0000113static int dtdattrs = 0;
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000114static int loaddtd = 0;
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000115static int progresult = 0;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000116static int timing = 0;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000117static int generate = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000118static int dropdtd = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000119#ifdef LIBXML_CATALOG_ENABLED
120static int catalogs = 0;
121static int nocatalogs = 0;
122#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000123
Daniel Veillard01db67c2001-12-18 07:09:59 +0000124/*
125 * Internal timing routines to remove the necessity to have unix-specific
126 * function calls
127 */
128
129#if defined(HAVE_GETTIMEOFDAY)
130static struct timeval begin, end;
131
132/*
133 * startTimer: call where you want to start timing
134 */
135static void
136startTimer(void)
137{
138 gettimeofday(&begin, NULL);
139}
140
141/*
142 * endTimer: call where you want to stop timing and to print out a
143 * message about the timing performed; format is a printf
144 * type argument
145 */
146static void
147endTimer(const char *format, ...)
148{
149 long msec;
150 va_list ap;
151
152 gettimeofday(&end, NULL);
153 msec = end.tv_sec - begin.tv_sec;
154 msec *= 1000;
155 msec += (end.tv_usec - begin.tv_usec) / 1000;
156
157#ifndef HAVE_STDARG_H
158#error "endTimer required stdarg functions"
159#endif
160 va_start(ap, format);
161 vfprintf(stderr, format, ap);
162 va_end(ap);
163
164 fprintf(stderr, " took %ld ms\n", msec);
165}
166#elif defined(HAVE_TIME_H)
167
168/*
169 * No gettimeofday function, so we have to make do with calling clock.
170 * This is obviously less accurate, but there's little we can do about
171 * that.
172 */
173
174static clock_t begin, end;
175static void
176startTimer(void)
177{
178 begin = clock();
179}
180static void
181endTimer(const char *fmt, ...)
182{
183 long msec;
184 va_list ap;
185
186 end = clock();
187 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
188
189#ifndef HAVE_STDARG_H
190#error "endTimer required stdarg functions"
191#endif
192 va_start(ap, fmt);
193 vfprintf(stderr, fmt, ap);
194 va_end(ap);
195 fprintf(stderr, " took %ld ms\n", msec);
196}
197#else
198
199/*
200 * We don't have a gettimeofday or time.h, so we just don't do timing
201 */
202static void
203startTimer(void)
204{
205 /*
206 * Do nothing
207 */
208}
209static void
210endTimer(char *format, ...)
211{
212 /*
213 * We cannot do anything because we don't have a timing function
214 */
215#ifdef HAVE_STDARG_H
216 va_start(ap, format);
217 vfprintf(stderr, format, ap);
218 va_end(ap);
219 fprintf(stderr, " was not timed\n", msec);
220#else
221 /* We don't have gettimeofday, time or stdarg.h, what crazy world is
222 * this ?!
223 */
224#endif
225}
226#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000227/************************************************************************
228 * *
229 * HTML ouput *
230 * *
231 ************************************************************************/
232char buffer[50000];
233
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000234static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000235xmlHTMLEncodeSend(void) {
236 char *result;
237
238 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
239 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000240 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000241 xmlFree(result);
242 }
243 buffer[0] = 0;
244}
245
246/**
247 * xmlHTMLPrintFileInfo:
248 * @input: an xmlParserInputPtr input
249 *
250 * Displays the associated file and line informations for the current input
251 */
252
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000253static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000254xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000255 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000256 if (input != NULL) {
257 if (input->filename) {
258 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
259 input->line);
260 } else {
261 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
262 }
263 }
264 xmlHTMLEncodeSend();
265}
266
267/**
268 * xmlHTMLPrintFileContext:
269 * @input: an xmlParserInputPtr input
270 *
271 * Displays current context within the input content for error tracking
272 */
273
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000274static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000275xmlHTMLPrintFileContext(xmlParserInputPtr input) {
276 const xmlChar *cur, *base;
277 int n;
278
279 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000280 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000281 cur = input->cur;
282 base = input->base;
283 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
284 cur--;
285 }
286 n = 0;
287 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
288 cur--;
289 if ((*cur == '\n') || (*cur == '\r')) cur++;
290 base = cur;
291 n = 0;
292 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
293 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
294 n++;
295 }
296 sprintf(&buffer[strlen(buffer)], "\n");
297 cur = input->cur;
298 while ((*cur == '\n') || (*cur == '\r'))
299 cur--;
300 n = 0;
301 while ((cur != base) && (n++ < 80)) {
302 sprintf(&buffer[strlen(buffer)], " ");
303 base++;
304 }
305 sprintf(&buffer[strlen(buffer)],"^\n");
306 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000307 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000308}
309
310/**
311 * xmlHTMLError:
312 * @ctx: an XML parser context
313 * @msg: the message to display/transmit
314 * @...: extra parameters for the message display
315 *
316 * Display and format an error messages, gives file, line, position and
317 * extra parameters.
318 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000319static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000320xmlHTMLError(void *ctx, const char *msg, ...)
321{
322 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
323 xmlParserInputPtr input;
324 xmlParserInputPtr cur = NULL;
325 va_list args;
326
327 buffer[0] = 0;
328 input = ctxt->input;
329 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
330 cur = input;
331 input = ctxt->inputTab[ctxt->inputNr - 2];
332 }
333
334 xmlHTMLPrintFileInfo(input);
335
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000336 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000337 va_start(args, msg);
338 vsprintf(&buffer[strlen(buffer)], msg, args);
339 va_end(args);
340 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000341 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000342
343 xmlHTMLPrintFileContext(input);
344 xmlHTMLEncodeSend();
345}
346
347/**
348 * xmlHTMLWarning:
349 * @ctx: an XML parser context
350 * @msg: the message to display/transmit
351 * @...: extra parameters for the message display
352 *
353 * Display and format a warning messages, gives file, line, position and
354 * extra parameters.
355 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000356static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000357xmlHTMLWarning(void *ctx, const char *msg, ...)
358{
359 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
360 xmlParserInputPtr input;
361 xmlParserInputPtr cur = NULL;
362 va_list args;
363
364 buffer[0] = 0;
365 input = ctxt->input;
366 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
367 cur = input;
368 input = ctxt->inputTab[ctxt->inputNr - 2];
369 }
370
371
372 xmlHTMLPrintFileInfo(input);
373
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000374 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000375 va_start(args, msg);
376 vsprintf(&buffer[strlen(buffer)], msg, args);
377 va_end(args);
378 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000379 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000380
381 xmlHTMLPrintFileContext(input);
382 xmlHTMLEncodeSend();
383}
384
385/**
386 * xmlHTMLValidityError:
387 * @ctx: an XML parser context
388 * @msg: the message to display/transmit
389 * @...: extra parameters for the message display
390 *
391 * Display and format an validity error messages, gives file,
392 * line, position and extra parameters.
393 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000394static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000395xmlHTMLValidityError(void *ctx, const char *msg, ...)
396{
397 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
398 xmlParserInputPtr input;
399 va_list args;
400
401 buffer[0] = 0;
402 input = ctxt->input;
403 if ((input->filename == NULL) && (ctxt->inputNr > 1))
404 input = ctxt->inputTab[ctxt->inputNr - 2];
405
406 xmlHTMLPrintFileInfo(input);
407
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000408 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000409 va_start(args, msg);
410 vsprintf(&buffer[strlen(buffer)], msg, args);
411 va_end(args);
412 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000413 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000414
415 xmlHTMLPrintFileContext(input);
416 xmlHTMLEncodeSend();
417}
418
419/**
420 * xmlHTMLValidityWarning:
421 * @ctx: an XML parser context
422 * @msg: the message to display/transmit
423 * @...: extra parameters for the message display
424 *
425 * Display and format a validity warning messages, gives file, line,
426 * position and extra parameters.
427 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000428static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000429xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
430{
431 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
432 xmlParserInputPtr input;
433 va_list args;
434
435 buffer[0] = 0;
436 input = ctxt->input;
437 if ((input->filename == NULL) && (ctxt->inputNr > 1))
438 input = ctxt->inputTab[ctxt->inputNr - 2];
439
440 xmlHTMLPrintFileInfo(input);
441
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000442 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000443 va_start(args, msg);
444 vsprintf(&buffer[strlen(buffer)], msg, args);
445 va_end(args);
446 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000447 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000448
449 xmlHTMLPrintFileContext(input);
450 xmlHTMLEncodeSend();
451}
452
453/************************************************************************
454 * *
455 * Shell Interface *
456 * *
457 ************************************************************************/
458/**
459 * xmlShellReadline:
460 * @prompt: the prompt value
461 *
462 * Read a string
463 *
464 * Returns a pointer to it or NULL on EOF the caller is expected to
465 * free the returned string.
466 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000467static char *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000468xmlShellReadline(char *prompt) {
469#ifdef HAVE_LIBREADLINE
470 char *line_read;
471
472 /* Get a line from the user. */
473 line_read = readline (prompt);
474
475 /* If the line has any text in it, save it on the history. */
476 if (line_read && *line_read)
477 add_history (line_read);
478
479 return (line_read);
480#else
481 char line_read[501];
Daniel Veillard29e43992001-12-13 22:21:58 +0000482 char *ret;
483 int len;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000484
485 if (prompt != NULL)
486 fprintf(stdout, "%s", prompt);
487 if (!fgets(line_read, 500, stdin))
488 return(NULL);
489 line_read[500] = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000490 len = strlen(line_read);
491 ret = (char *) malloc(len + 1);
492 if (ret != NULL) {
493 memcpy (ret, line_read, len + 1);
494 }
495 return(ret);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000496#endif
497}
498
499/************************************************************************
500 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000501 * I/O Interfaces *
502 * *
503 ************************************************************************/
504
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000505static int myRead(FILE *f, char * buf, int len) {
506 return(fread(buf, 1, len, f));
Daniel Veillard5e873c42000-04-12 13:27:38 +0000507}
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000508static void myClose(FILE *f) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000509 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000510 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000511 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000512}
513
514/************************************************************************
515 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000516 * Test processing *
517 * *
518 ************************************************************************/
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000519static void parseAndPrintFile(char *filename) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000520 xmlDocPtr doc = NULL, tmp;
521
Daniel Veillard48b2f892001-02-25 16:11:03 +0000522 if ((timing) && (!repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +0000523 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000524
525
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000526 if (filename == NULL) {
527 if (generate) {
528 xmlNodePtr n;
529
530 doc = xmlNewDoc(BAD_CAST "1.0");
531 n = xmlNewNode(NULL, BAD_CAST "info");
532 xmlNodeSetContent(n, BAD_CAST "abc");
533 xmlDocSetRootElement(doc, n);
534 }
535 }
Daniel Veillard89cad532001-10-22 09:46:13 +0000536#ifdef LIBXML_DOCB_ENABLED
537 /*
538 * build an SGML tree from a string;
539 */
540 else if ((sgml) && (push)) {
541 FILE *f;
542
543 f = fopen(filename, "r");
544 if (f != NULL) {
545 int res, size = 3;
546 char chars[4096];
547 docbParserCtxtPtr ctxt;
548
549 /* if (repeat) */
550 size = 4096;
551 res = fread(chars, 1, 4, f);
552 if (res > 0) {
553 ctxt = docbCreatePushParserCtxt(NULL, NULL,
554 chars, res, filename, 0);
555 while ((res = fread(chars, 1, size, f)) > 0) {
556 docbParseChunk(ctxt, chars, res, 0);
557 }
558 docbParseChunk(ctxt, chars, 0, 1);
559 doc = ctxt->myDoc;
560 docbFreeParserCtxt(ctxt);
561 }
562 fclose(f);
563 }
564 } else if (sgml) {
565 doc = docbParseFile(filename, NULL);
566 }
567#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000568#ifdef LIBXML_HTML_ENABLED
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000569 else if (html) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000570 doc = htmlParseFile(filename, NULL);
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000571 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000572#endif /* LIBXML_HTML_ENABLED */
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000573 else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000574 /*
575 * build an XML tree from a string;
576 */
577 if (push) {
578 FILE *f;
579
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000580 /* '-' Usually means stdin -<sven@zen.org> */
581 if ((filename[0] == '-') && (filename[1] == 0)) {
582 f = stdin;
583 } else {
584 f = fopen(filename, "r");
585 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000586 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000587 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000588 int res, size = 3;
589 char chars[1024];
590 xmlParserCtxtPtr ctxt;
591
592 if (repeat)
593 size = 1024;
594 res = fread(chars, 1, 4, f);
595 if (res > 0) {
596 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
597 chars, res, filename);
598 while ((res = fread(chars, 1, size, f)) > 0) {
599 xmlParseChunk(ctxt, chars, res, 0);
600 }
601 xmlParseChunk(ctxt, chars, 0, 1);
602 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000603 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000604 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000605 if (!ret) {
606 xmlFreeDoc(doc);
607 doc = NULL;
608 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000609 }
610 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000611 } else if (testIO) {
612 int ret;
613 FILE *f;
614
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000615 /* '-' Usually means stdin -<sven@zen.org> */
616 if ((filename[0] == '-') && (filename[1] == 0)) {
617 f = stdin;
618 } else {
619 f = fopen(filename, "r");
620 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000621 if (f != NULL) {
622 xmlParserCtxtPtr ctxt;
623
624 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
625 (xmlInputReadCallback) myRead,
626 (xmlInputCloseCallback) myClose,
627 f, XML_CHAR_ENCODING_NONE);
628 xmlParseDocument(ctxt);
629
630 ret = ctxt->wellFormed;
631 doc = ctxt->myDoc;
632 xmlFreeParserCtxt(ctxt);
633 if (!ret) {
634 xmlFreeDoc(doc);
635 doc = NULL;
636 }
637 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000638 } else if (recovery) {
639 doc = xmlRecoverFile(filename);
640 } else if (htmlout) {
641 int ret;
642 xmlParserCtxtPtr ctxt;
643 xmlSAXHandler silent, *old;
644
645 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000646
647 if (ctxt == NULL) {
648 /* If xmlCreateFileParseCtxt() return NULL something
649 strange happened so we don't want to do anything. Do
650 we want to print an error message here?
651 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000652 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000653 } else {
654 memcpy(&silent, ctxt->sax, sizeof(silent));
655 old = ctxt->sax;
656 silent.error = xmlHTMLError;
657 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000658 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000659 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000660 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000661 silent.fatalError = xmlHTMLError;
662 ctxt->sax = &silent;
663 ctxt->vctxt.error = xmlHTMLValidityError;
664 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000665 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000666 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000667 ctxt->vctxt.warning = NULL;
668
Daniel Veillard88a172f2000-08-04 18:23:10 +0000669 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000670
Daniel Veillard88a172f2000-08-04 18:23:10 +0000671 ret = ctxt->wellFormed;
672 doc = ctxt->myDoc;
673 ctxt->sax = old;
674 xmlFreeParserCtxt(ctxt);
675 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000676 xmlFreeDoc(doc);
677 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000678 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000679 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000680#ifdef HAVE_SYS_MMAN_H
681 } else if (memory) {
682 int fd;
683 struct stat info;
684 const char *base;
685 if (stat(filename, &info) < 0)
686 return;
687 if ((fd = open(filename, O_RDONLY)) < 0)
688 return;
689 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000690 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000691 return;
692
693 doc = xmlParseMemory((char *) base, info.st_size);
694 munmap((char *) base, info.st_size);
695#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000696 } else
697 doc = xmlParseFile(filename);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000698 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000699
Daniel Veillard88a172f2000-08-04 18:23:10 +0000700 /*
701 * If we don't have a document we might as well give up. Do we
702 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000703 if (doc == NULL) {
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000704 progresult = 1;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000705 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000706 }
707
Daniel Veillard48b2f892001-02-25 16:11:03 +0000708 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000709 endTimer("Parsing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000710 }
711
Daniel Veillard29e43992001-12-13 22:21:58 +0000712 /*
713 * Remove DOCTYPE nodes
714 */
715 if (dropdtd) {
716 xmlDtdPtr dtd;
717
718 dtd = xmlGetIntSubset(doc);
719 if (dtd != NULL) {
720 xmlUnlinkNode((xmlNodePtr)dtd);
721 xmlFreeDtd(dtd);
722 }
723 }
724
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000725#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard48b2f892001-02-25 16:11:03 +0000726 if (xinclude) {
727 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000728 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000729 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000730 xmlXIncludeProcess(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000731 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000732 endTimer("Xinclude processing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000733 }
734 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000735#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000736
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000737#ifdef LIBXML_DEBUG_ENABLED
738 /*
739 * shell interraction
740 */
741 if (shell)
742 xmlShell(doc, filename, xmlShellReadline, stdout);
743#endif
744
745 /*
746 * test intermediate copy if needed.
747 */
748 if (copy) {
749 tmp = doc;
750 doc = xmlCopyDoc(doc, 1);
751 xmlFreeDoc(tmp);
752 }
753
754 if ((insert) && (!html)) {
755 const xmlChar* list[256];
756 int nb, i;
757 xmlNodePtr node;
758
759 if (doc->children != NULL) {
760 node = doc->children;
761 while ((node != NULL) && (node->last == NULL)) node = node->next;
762 if (node != NULL) {
763 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
764 if (nb < 0) {
765 printf("could not get valid list of elements\n");
766 } else if (nb == 0) {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000767 printf("No element can be inserted under root\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000768 } else {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000769 printf("%d element types can be inserted under root:\n",
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000770 nb);
771 for (i = 0;i < nb;i++) {
772 printf("%s\n", list[i]);
773 }
774 }
775 }
776 }
777 }else if (noout == 0) {
778 /*
779 * print it.
780 */
781#ifdef LIBXML_DEBUG_ENABLED
782 if (!debug) {
783#endif
Daniel Veillard48b2f892001-02-25 16:11:03 +0000784 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000785 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000786 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000787#ifdef HAVE_SYS_MMAN_H
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000788 if (memory) {
789 xmlChar *result;
790 int len;
791
792 if (encoding != NULL) {
Daniel Veillardd536f702001-11-08 17:32:47 +0000793 if ( format ) {
794 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
795 } else {
796 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
797 }
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000798 } else {
Daniel Veillard90493a92001-08-14 14:12:47 +0000799 if (format)
800 xmlDocDumpFormatMemory(doc, &result, &len, 1);
801 else
802 xmlDocDumpMemory(doc, &result, &len);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000803 }
804 if (result == NULL) {
805 fprintf(stderr, "Failed to save\n");
806 } else {
807 write(1, result, len);
808 xmlFree(result);
809 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000810 } else
811#endif /* HAVE_SYS_MMAN_H */
812 if (compress)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000813 xmlSaveFile("-", doc);
Daniel Veillardd536f702001-11-08 17:32:47 +0000814 else if (encoding != NULL) {
815 if ( format ) {
816 xmlSaveFormatFileEnc("-", doc, encoding, 1);
817 }
818 else {
819 xmlSaveFileEnc("-", doc, encoding);
820 }
821 }
Daniel Veillard90493a92001-08-14 14:12:47 +0000822 else if (format)
823 xmlSaveFormatFile("-", doc, 1);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000824 else
825 xmlDocDump(stdout, doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000826 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000827 endTimer("Saving");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000828 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000829#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000830 } else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000831 xmlDebugDumpDocument(stdout, doc);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000832 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000833#endif
834 }
835
836 /*
837 * A posteriori validation test
838 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000839 if (dtdvalid != NULL) {
840 xmlDtdPtr dtd;
841
Daniel Veillard48b2f892001-02-25 16:11:03 +0000842 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000843 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000844 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000845 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000846 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000847 endTimer("Parsing DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000848 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000849 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000850 xmlGenericError(xmlGenericErrorContext,
851 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000852 progresult = 2;
Daniel Veillardcd429612000-10-11 15:57:05 +0000853 } else {
854 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000855 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000856 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000857 }
Daniel Veillard01db67c2001-12-18 07:09:59 +0000858 cvp.userData = (void *) stderr;
859 cvp.error = (xmlValidityErrorFunc) fprintf;
860 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000861 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000862 xmlGenericError(xmlGenericErrorContext,
863 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000864 filename, dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000865 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000866 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000867 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000868 endTimer("Validating against DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000869 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000870 xmlFreeDtd(dtd);
871 }
872 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000873 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000874 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000875 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000876 }
Daniel Veillardb7664f42001-08-19 13:00:43 +0000877 cvp.userData = (void *) stderr;
878 cvp.error = (xmlValidityErrorFunc) fprintf;
879 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000880 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000881 xmlGenericError(xmlGenericErrorContext,
882 "Document %s does not validate\n", filename);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000883 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000884 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000885 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000886 endTimer("Validating");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000887 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000888 }
889
890#ifdef LIBXML_DEBUG_ENABLED
891 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000892 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000893#endif
894
895 /*
896 * free it.
897 */
Daniel Veillard48b2f892001-02-25 16:11:03 +0000898 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000899 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000900 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000901 xmlFreeDoc(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000902 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000903 endTimer("Freeing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000904 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000905}
906
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000907/************************************************************************
908 * *
909 * Usage and Main *
910 * *
911 ************************************************************************/
912
913static void usage(const char *name) {
914 printf("Usage : %s [options] XMLfiles ...\n", name);
915 printf("\tParse the XML files and output the result of the parsing\n");
916 printf("\t--version : display the version of the XML library used\n");
917#ifdef LIBXML_DEBUG_ENABLED
918 printf("\t--debug : dump a debug tree of the in-memory document\n");
919 printf("\t--shell : run a navigating shell\n");
920 printf("\t--debugent : debug the entities defined in the document\n");
921#endif
922 printf("\t--copy : used to test the internal copy implementation\n");
923 printf("\t--recover : output what was parsable on broken XML documents\n");
924 printf("\t--noent : substitute entity references by their value\n");
925 printf("\t--noout : don't output the result tree\n");
926 printf("\t--htmlout : output results as HTML\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000927 printf("\t--nowrap : do not put HTML doc wrapper\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000928 printf("\t--valid : validate the document in addition to std well-formed check\n");
929 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
930 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
931 printf("\t--timing : print some timings\n");
932 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
933 printf("\t--insert : ad-hoc test for valid insertions\n");
934 printf("\t--compress : turn on gzip compression of output\n");
Daniel Veillard89cad532001-10-22 09:46:13 +0000935#ifdef LIBXML_DOCB_ENABLED
936 printf("\t--sgml : use the DocBook SGML parser\n");
937#endif
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000938#ifdef LIBXML_HTML_ENABLED
939 printf("\t--html : use the HTML parser\n");
940#endif
941 printf("\t--push : use the push mode of the parser\n");
942#ifdef HAVE_SYS_MMAN_H
943 printf("\t--memory : parse from memory\n");
944#endif
945 printf("\t--nowarning : do not emit warnings from parser/validator\n");
946 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard90493a92001-08-14 14:12:47 +0000947 printf("\t--format : reformat/reindent the input\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000948 printf("\t--testIO : test user I/O support\n");
949 printf("\t--encode encoding : output in the given encoding\n");
950#ifdef LIBXML_CATALOG_ENABLED
Daniel Veillardbd9b0e82001-11-26 10:32:08 +0000951 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
952 printf("\t otherwise XML Catalogs starting from \n");
953 printf("\t file:///etc/xml/catalog are activated by default\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000954 printf("\t--nocatalogs: deactivate all catalogs\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000955#endif
956 printf("\t--auto : generate a small doc on the fly\n");
957#ifdef LIBXML_XINCLUDE_ENABLED
958 printf("\t--xinclude : do XInclude processing\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000959#endif
Daniel Veillard48da9102001-08-07 01:10:10 +0000960 printf("\t--loaddtd : fetch external Dtd\n");
961 printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
Daniel Veillard29e43992001-12-13 22:21:58 +0000962 printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000963}
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000964int
965main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000966 int i, count;
967 int files = 0;
968
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000969 if (argc <= 1) {
970 usage(argv[0]);
971 return(1);
972 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000973 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000974 for (i = 1; i < argc ; i++) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000975 if (!strcmp(argv[i], "-"))
976 break;
977
978 if (argv[i][0] != '-')
979 continue;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000980#ifdef LIBXML_DEBUG_ENABLED
981 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
982 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000983 else if ((!strcmp(argv[i], "-shell")) ||
984 (!strcmp(argv[i], "--shell"))) {
985 shell++;
986 noout = 1;
987 } else
988#endif
989 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
990 copy++;
991 else if ((!strcmp(argv[i], "-recover")) ||
992 (!strcmp(argv[i], "--recover")))
993 recovery++;
994 else if ((!strcmp(argv[i], "-noent")) ||
995 (!strcmp(argv[i], "--noent")))
996 noent++;
Daniel Veillard4ec885a2001-06-17 10:31:07 +0000997 else if ((!strcmp(argv[i], "-version")) ||
998 (!strcmp(argv[i], "--version")))
999 fprintf(stderr, "xmllint: using libxml version %s\n",
1000 xmlParserVersion);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001001 else if ((!strcmp(argv[i], "-noout")) ||
1002 (!strcmp(argv[i], "--noout")))
1003 noout++;
1004 else if ((!strcmp(argv[i], "-htmlout")) ||
1005 (!strcmp(argv[i], "--htmlout")))
1006 htmlout++;
Daniel Veillard89cad532001-10-22 09:46:13 +00001007#ifdef LIBXML_DOCB_ENABLED
1008 else if ((!strcmp(argv[i], "-sgml")) ||
1009 (!strcmp(argv[i], "--sgml"))) {
1010 sgml++;
1011 }
1012#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001013#ifdef LIBXML_HTML_ENABLED
1014 else if ((!strcmp(argv[i], "-html")) ||
1015 (!strcmp(argv[i], "--html"))) {
1016 html++;
1017 }
1018#endif /* LIBXML_HTML_ENABLED */
1019 else if ((!strcmp(argv[i], "-nowrap")) ||
1020 (!strcmp(argv[i], "--nowrap")))
1021 nowrap++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001022 else if ((!strcmp(argv[i], "-loaddtd")) ||
1023 (!strcmp(argv[i], "--loaddtd")))
1024 loaddtd++;
Daniel Veillard48da9102001-08-07 01:10:10 +00001025 else if ((!strcmp(argv[i], "-dtdattr")) ||
1026 (!strcmp(argv[i], "--dtdattr"))) {
1027 loaddtd++;
1028 dtdattrs++;
1029 } else if ((!strcmp(argv[i], "-valid")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001030 (!strcmp(argv[i], "--valid")))
1031 valid++;
1032 else if ((!strcmp(argv[i], "-postvalid")) ||
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001033 (!strcmp(argv[i], "--postvalid"))) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001034 postvalid++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001035 loaddtd++;
1036 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
Daniel Veillardcd429612000-10-11 15:57:05 +00001037 (!strcmp(argv[i], "--dtdvalid"))) {
1038 i++;
1039 dtdvalid = argv[i];
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001040 loaddtd++;
Daniel Veillardcd429612000-10-11 15:57:05 +00001041 }
Daniel Veillard29e43992001-12-13 22:21:58 +00001042 else if ((!strcmp(argv[i], "-dropdtd")) ||
1043 (!strcmp(argv[i], "--dropdtd")))
1044 dropdtd++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001045 else if ((!strcmp(argv[i], "-insert")) ||
1046 (!strcmp(argv[i], "--insert")))
1047 insert++;
Daniel Veillard48b2f892001-02-25 16:11:03 +00001048 else if ((!strcmp(argv[i], "-timing")) ||
1049 (!strcmp(argv[i], "--timing")))
1050 timing++;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001051 else if ((!strcmp(argv[i], "-auto")) ||
1052 (!strcmp(argv[i], "--auto")))
1053 generate++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001054 else if ((!strcmp(argv[i], "-repeat")) ||
1055 (!strcmp(argv[i], "--repeat")))
1056 repeat++;
1057 else if ((!strcmp(argv[i], "-push")) ||
1058 (!strcmp(argv[i], "--push")))
1059 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +00001060#ifdef HAVE_SYS_MMAN_H
1061 else if ((!strcmp(argv[i], "-memory")) ||
1062 (!strcmp(argv[i], "--memory")))
1063 memory++;
1064#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +00001065 else if ((!strcmp(argv[i], "-testIO")) ||
1066 (!strcmp(argv[i], "--testIO")))
1067 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +00001068#ifdef LIBXML_XINCLUDE_ENABLED
1069 else if ((!strcmp(argv[i], "-xinclude")) ||
1070 (!strcmp(argv[i], "--xinclude")))
1071 xinclude++;
1072#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001073 else if ((!strcmp(argv[i], "-compress")) ||
1074 (!strcmp(argv[i], "--compress"))) {
1075 compress++;
1076 xmlSetCompressMode(9);
1077 }
1078 else if ((!strcmp(argv[i], "-nowarning")) ||
1079 (!strcmp(argv[i], "--nowarning"))) {
1080 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001081 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001082 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001083 else if ((!strcmp(argv[i], "-pedantic")) ||
1084 (!strcmp(argv[i], "--pedantic"))) {
1085 xmlGetWarningsDefaultValue = 1;
1086 xmlPedanticParserDefault(1);
1087 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001088#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001089 else if ((!strcmp(argv[i], "-debugent")) ||
1090 (!strcmp(argv[i], "--debugent"))) {
1091 debugent++;
1092 xmlParserDebugEntities = 1;
1093 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001094#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00001095#ifdef LIBXML_CATALOG_ENABLED
1096 else if ((!strcmp(argv[i], "-catalogs")) ||
1097 (!strcmp(argv[i], "--catalogs"))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001098 catalogs++;
1099 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1100 (!strcmp(argv[i], "--nocatalogs"))) {
1101 nocatalogs++;
Daniel Veillard81418e32001-05-22 15:08:55 +00001102 }
1103#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001104 else if ((!strcmp(argv[i], "-encode")) ||
1105 (!strcmp(argv[i], "--encode"))) {
1106 i++;
1107 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001108 /*
1109 * OK it's for testing purposes
1110 */
1111 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +00001112 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001113 else if ((!strcmp(argv[i], "-noblanks")) ||
1114 (!strcmp(argv[i], "--noblanks"))) {
1115 noblanks++;
1116 xmlKeepBlanksDefault(0);
Daniel Veillard90493a92001-08-14 14:12:47 +00001117 }
1118 else if ((!strcmp(argv[i], "-format")) ||
1119 (!strcmp(argv[i], "--format"))) {
1120 noblanks++;
1121 format++;
1122 xmlKeepBlanksDefault(0);
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001123 } else {
1124 fprintf(stderr, "Unknown option %s\n", argv[i]);
1125 usage(argv[0]);
1126 return(1);
1127 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001128 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001129
1130#ifdef LIBXML_CATALOG_ENABLED
1131 if (nocatalogs == 0) {
1132 if (catalogs) {
1133 const char *catal;
1134
1135 catal = getenv("SGML_CATALOG_FILES");
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00001136 if (catal != NULL) {
1137 xmlLoadCatalogs(catal);
1138 } else {
1139 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1140 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001141 }
1142 }
1143#endif
Daniel Veillardd9bad132001-07-23 19:39:43 +00001144 xmlLineNumbersDefault(1);
Daniel Veillard48da9102001-08-07 01:10:10 +00001145 if (loaddtd != 0)
1146 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1147 if (dtdattrs)
1148 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001149 if (noent != 0) xmlSubstituteEntitiesDefault(1);
1150 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1151 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001152 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001153 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001154 xmlGenericError(xmlGenericErrorContext,
1155 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1156 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001157 "<html><head><title>%s output</title></head>\n",
1158 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001159 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001160 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1161 argv[0]);
1162 }
1163 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +00001164 if ((!strcmp(argv[i], "-encode")) ||
1165 (!strcmp(argv[i], "--encode"))) {
1166 i++;
1167 continue;
1168 }
Daniel Veillardcd429612000-10-11 15:57:05 +00001169 if ((!strcmp(argv[i], "-dtdvalid")) ||
1170 (!strcmp(argv[i], "--dtdvalid"))) {
1171 i++;
1172 continue;
1173 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001174 if ((timing) && (repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +00001175 startTimer();
Daniel Veillard4a6845d2001-01-03 13:32:39 +00001176 /* Remember file names. "-" means stding. <sven@zen.org> */
1177 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001178 if (repeat) {
1179 for (count = 0;count < 100 * repeat;count++)
1180 parseAndPrintFile(argv[i]);
1181 } else
1182 parseAndPrintFile(argv[i]);
1183 files ++;
Daniel Veillarda7866932001-12-04 13:14:44 +00001184 if ((timing) && (repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +00001185 endTimer("100 iterations");
Daniel Veillarda7866932001-12-04 13:14:44 +00001186 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001187 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001188 }
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001189 if (generate)
1190 parseAndPrintFile(NULL);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001191 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001192 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001193 }
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001194 if ((files == 0) && (!generate)) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001195 usage(argv[0]);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001196 }
1197 xmlCleanupParser();
1198 xmlMemoryDump();
1199
Daniel Veillardf7cd4812001-02-23 18:44:52 +00001200 return(progresult);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001201}
Daniel Veillard88a172f2000-08-04 18:23:10 +00001202