blob: 01fbed0a16527a737ec79e5be1560dc15b165721 [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 Veillard3c5ed912002-01-08 10:36:16 +000014#if defined (_WIN32) && !defined(__CYGWIN__)
Daniel Veillard2d90de42001-04-16 17:46:18 +000015#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 Veillard1df3dfc2001-12-18 11:14:16 +0000123static const char *output = NULL;
124
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000125
Daniel Veillard01db67c2001-12-18 07:09:59 +0000126/*
127 * Internal timing routines to remove the necessity to have unix-specific
128 * function calls
129 */
130
131#if defined(HAVE_GETTIMEOFDAY)
132static struct timeval begin, end;
133
134/*
135 * startTimer: call where you want to start timing
136 */
137static void
138startTimer(void)
139{
140 gettimeofday(&begin, NULL);
141}
142
143/*
144 * endTimer: call where you want to stop timing and to print out a
145 * message about the timing performed; format is a printf
146 * type argument
147 */
148static void
149endTimer(const char *format, ...)
150{
151 long msec;
152 va_list ap;
153
154 gettimeofday(&end, NULL);
155 msec = end.tv_sec - begin.tv_sec;
156 msec *= 1000;
157 msec += (end.tv_usec - begin.tv_usec) / 1000;
158
159#ifndef HAVE_STDARG_H
160#error "endTimer required stdarg functions"
161#endif
162 va_start(ap, format);
163 vfprintf(stderr, format, ap);
164 va_end(ap);
165
166 fprintf(stderr, " took %ld ms\n", msec);
167}
168#elif defined(HAVE_TIME_H)
169
170/*
171 * No gettimeofday function, so we have to make do with calling clock.
172 * This is obviously less accurate, but there's little we can do about
173 * that.
174 */
175
176static clock_t begin, end;
177static void
178startTimer(void)
179{
180 begin = clock();
181}
182static void
183endTimer(const char *fmt, ...)
184{
185 long msec;
186 va_list ap;
187
188 end = clock();
189 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
190
191#ifndef HAVE_STDARG_H
192#error "endTimer required stdarg functions"
193#endif
194 va_start(ap, fmt);
195 vfprintf(stderr, fmt, ap);
196 va_end(ap);
197 fprintf(stderr, " took %ld ms\n", msec);
198}
199#else
200
201/*
202 * We don't have a gettimeofday or time.h, so we just don't do timing
203 */
204static void
205startTimer(void)
206{
207 /*
208 * Do nothing
209 */
210}
211static void
212endTimer(char *format, ...)
213{
214 /*
215 * We cannot do anything because we don't have a timing function
216 */
217#ifdef HAVE_STDARG_H
218 va_start(ap, format);
219 vfprintf(stderr, format, ap);
220 va_end(ap);
221 fprintf(stderr, " was not timed\n", msec);
222#else
223 /* We don't have gettimeofday, time or stdarg.h, what crazy world is
224 * this ?!
225 */
226#endif
227}
228#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000229/************************************************************************
230 * *
231 * HTML ouput *
232 * *
233 ************************************************************************/
234char buffer[50000];
235
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000236static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000237xmlHTMLEncodeSend(void) {
238 char *result;
239
240 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
241 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000242 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000243 xmlFree(result);
244 }
245 buffer[0] = 0;
246}
247
248/**
249 * xmlHTMLPrintFileInfo:
250 * @input: an xmlParserInputPtr input
251 *
252 * Displays the associated file and line informations for the current input
253 */
254
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000255static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000256xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000257 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000258 if (input != NULL) {
259 if (input->filename) {
260 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
261 input->line);
262 } else {
263 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
264 }
265 }
266 xmlHTMLEncodeSend();
267}
268
269/**
270 * xmlHTMLPrintFileContext:
271 * @input: an xmlParserInputPtr input
272 *
273 * Displays current context within the input content for error tracking
274 */
275
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000276static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000277xmlHTMLPrintFileContext(xmlParserInputPtr input) {
278 const xmlChar *cur, *base;
279 int n;
280
281 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000282 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000283 cur = input->cur;
284 base = input->base;
285 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
286 cur--;
287 }
288 n = 0;
289 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
290 cur--;
291 if ((*cur == '\n') || (*cur == '\r')) cur++;
292 base = cur;
293 n = 0;
294 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
295 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
296 n++;
297 }
298 sprintf(&buffer[strlen(buffer)], "\n");
299 cur = input->cur;
300 while ((*cur == '\n') || (*cur == '\r'))
301 cur--;
302 n = 0;
303 while ((cur != base) && (n++ < 80)) {
304 sprintf(&buffer[strlen(buffer)], " ");
305 base++;
306 }
307 sprintf(&buffer[strlen(buffer)],"^\n");
308 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000309 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000310}
311
312/**
313 * xmlHTMLError:
314 * @ctx: an XML parser context
315 * @msg: the message to display/transmit
316 * @...: extra parameters for the message display
317 *
318 * Display and format an error messages, gives file, line, position and
319 * extra parameters.
320 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000321static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000322xmlHTMLError(void *ctx, const char *msg, ...)
323{
324 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
325 xmlParserInputPtr input;
326 xmlParserInputPtr cur = NULL;
327 va_list args;
328
329 buffer[0] = 0;
330 input = ctxt->input;
331 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
332 cur = input;
333 input = ctxt->inputTab[ctxt->inputNr - 2];
334 }
335
336 xmlHTMLPrintFileInfo(input);
337
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000338 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000339 va_start(args, msg);
340 vsprintf(&buffer[strlen(buffer)], msg, args);
341 va_end(args);
342 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000343 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000344
345 xmlHTMLPrintFileContext(input);
346 xmlHTMLEncodeSend();
347}
348
349/**
350 * xmlHTMLWarning:
351 * @ctx: an XML parser context
352 * @msg: the message to display/transmit
353 * @...: extra parameters for the message display
354 *
355 * Display and format a warning messages, gives file, line, position and
356 * extra parameters.
357 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000358static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000359xmlHTMLWarning(void *ctx, const char *msg, ...)
360{
361 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
362 xmlParserInputPtr input;
363 xmlParserInputPtr cur = NULL;
364 va_list args;
365
366 buffer[0] = 0;
367 input = ctxt->input;
368 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
369 cur = input;
370 input = ctxt->inputTab[ctxt->inputNr - 2];
371 }
372
373
374 xmlHTMLPrintFileInfo(input);
375
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000376 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000377 va_start(args, msg);
378 vsprintf(&buffer[strlen(buffer)], msg, args);
379 va_end(args);
380 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000381 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000382
383 xmlHTMLPrintFileContext(input);
384 xmlHTMLEncodeSend();
385}
386
387/**
388 * xmlHTMLValidityError:
389 * @ctx: an XML parser context
390 * @msg: the message to display/transmit
391 * @...: extra parameters for the message display
392 *
393 * Display and format an validity error messages, gives file,
394 * line, position and extra parameters.
395 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000396static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000397xmlHTMLValidityError(void *ctx, const char *msg, ...)
398{
399 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
400 xmlParserInputPtr input;
401 va_list args;
402
403 buffer[0] = 0;
404 input = ctxt->input;
405 if ((input->filename == NULL) && (ctxt->inputNr > 1))
406 input = ctxt->inputTab[ctxt->inputNr - 2];
407
408 xmlHTMLPrintFileInfo(input);
409
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000410 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000411 va_start(args, msg);
412 vsprintf(&buffer[strlen(buffer)], msg, args);
413 va_end(args);
414 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000415 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000416
417 xmlHTMLPrintFileContext(input);
418 xmlHTMLEncodeSend();
419}
420
421/**
422 * xmlHTMLValidityWarning:
423 * @ctx: an XML parser context
424 * @msg: the message to display/transmit
425 * @...: extra parameters for the message display
426 *
427 * Display and format a validity warning messages, gives file, line,
428 * position and extra parameters.
429 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000430static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000431xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
432{
433 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
434 xmlParserInputPtr input;
435 va_list args;
436
437 buffer[0] = 0;
438 input = ctxt->input;
439 if ((input->filename == NULL) && (ctxt->inputNr > 1))
440 input = ctxt->inputTab[ctxt->inputNr - 2];
441
442 xmlHTMLPrintFileInfo(input);
443
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000444 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000445 va_start(args, msg);
446 vsprintf(&buffer[strlen(buffer)], msg, args);
447 va_end(args);
448 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000449 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000450
451 xmlHTMLPrintFileContext(input);
452 xmlHTMLEncodeSend();
453}
454
455/************************************************************************
456 * *
457 * Shell Interface *
458 * *
459 ************************************************************************/
460/**
461 * xmlShellReadline:
462 * @prompt: the prompt value
463 *
464 * Read a string
465 *
466 * Returns a pointer to it or NULL on EOF the caller is expected to
467 * free the returned string.
468 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000469static char *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000470xmlShellReadline(char *prompt) {
471#ifdef HAVE_LIBREADLINE
472 char *line_read;
473
474 /* Get a line from the user. */
475 line_read = readline (prompt);
476
477 /* If the line has any text in it, save it on the history. */
478 if (line_read && *line_read)
479 add_history (line_read);
480
481 return (line_read);
482#else
483 char line_read[501];
Daniel Veillard29e43992001-12-13 22:21:58 +0000484 char *ret;
485 int len;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000486
487 if (prompt != NULL)
488 fprintf(stdout, "%s", prompt);
489 if (!fgets(line_read, 500, stdin))
490 return(NULL);
491 line_read[500] = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000492 len = strlen(line_read);
493 ret = (char *) malloc(len + 1);
494 if (ret != NULL) {
495 memcpy (ret, line_read, len + 1);
496 }
497 return(ret);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000498#endif
499}
500
501/************************************************************************
502 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000503 * I/O Interfaces *
504 * *
505 ************************************************************************/
506
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000507static int myRead(FILE *f, char * buf, int len) {
508 return(fread(buf, 1, len, f));
Daniel Veillard5e873c42000-04-12 13:27:38 +0000509}
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000510static void myClose(FILE *f) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000511 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000512 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000513 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000514}
515
516/************************************************************************
517 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000518 * Test processing *
519 * *
520 ************************************************************************/
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000521static void parseAndPrintFile(char *filename) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000522 xmlDocPtr doc = NULL, tmp;
523
Daniel Veillard48b2f892001-02-25 16:11:03 +0000524 if ((timing) && (!repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +0000525 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000526
527
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000528 if (filename == NULL) {
529 if (generate) {
530 xmlNodePtr n;
531
532 doc = xmlNewDoc(BAD_CAST "1.0");
533 n = xmlNewNode(NULL, BAD_CAST "info");
534 xmlNodeSetContent(n, BAD_CAST "abc");
535 xmlDocSetRootElement(doc, n);
536 }
537 }
Daniel Veillard89cad532001-10-22 09:46:13 +0000538#ifdef LIBXML_DOCB_ENABLED
539 /*
540 * build an SGML tree from a string;
541 */
542 else if ((sgml) && (push)) {
543 FILE *f;
544
545 f = fopen(filename, "r");
546 if (f != NULL) {
547 int res, size = 3;
548 char chars[4096];
549 docbParserCtxtPtr ctxt;
550
551 /* if (repeat) */
552 size = 4096;
553 res = fread(chars, 1, 4, f);
554 if (res > 0) {
555 ctxt = docbCreatePushParserCtxt(NULL, NULL,
556 chars, res, filename, 0);
557 while ((res = fread(chars, 1, size, f)) > 0) {
558 docbParseChunk(ctxt, chars, res, 0);
559 }
560 docbParseChunk(ctxt, chars, 0, 1);
561 doc = ctxt->myDoc;
562 docbFreeParserCtxt(ctxt);
563 }
564 fclose(f);
565 }
566 } else if (sgml) {
567 doc = docbParseFile(filename, NULL);
568 }
569#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000570#ifdef LIBXML_HTML_ENABLED
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000571 else if (html) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000572 doc = htmlParseFile(filename, NULL);
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000573 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000574#endif /* LIBXML_HTML_ENABLED */
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000575 else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000576 /*
577 * build an XML tree from a string;
578 */
579 if (push) {
580 FILE *f;
581
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000582 /* '-' Usually means stdin -<sven@zen.org> */
583 if ((filename[0] == '-') && (filename[1] == 0)) {
584 f = stdin;
585 } else {
586 f = fopen(filename, "r");
587 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000588 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000589 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000590 int res, size = 3;
591 char chars[1024];
592 xmlParserCtxtPtr ctxt;
593
594 if (repeat)
595 size = 1024;
596 res = fread(chars, 1, 4, f);
597 if (res > 0) {
598 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
599 chars, res, filename);
600 while ((res = fread(chars, 1, size, f)) > 0) {
601 xmlParseChunk(ctxt, chars, res, 0);
602 }
603 xmlParseChunk(ctxt, chars, 0, 1);
604 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000605 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000606 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000607 if (!ret) {
608 xmlFreeDoc(doc);
609 doc = NULL;
610 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000611 }
612 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000613 } else if (testIO) {
614 int ret;
615 FILE *f;
616
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000617 /* '-' Usually means stdin -<sven@zen.org> */
618 if ((filename[0] == '-') && (filename[1] == 0)) {
619 f = stdin;
620 } else {
621 f = fopen(filename, "r");
622 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000623 if (f != NULL) {
624 xmlParserCtxtPtr ctxt;
625
626 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
627 (xmlInputReadCallback) myRead,
628 (xmlInputCloseCallback) myClose,
629 f, XML_CHAR_ENCODING_NONE);
630 xmlParseDocument(ctxt);
631
632 ret = ctxt->wellFormed;
633 doc = ctxt->myDoc;
634 xmlFreeParserCtxt(ctxt);
635 if (!ret) {
636 xmlFreeDoc(doc);
637 doc = NULL;
638 }
639 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000640 } else if (recovery) {
641 doc = xmlRecoverFile(filename);
642 } else if (htmlout) {
643 int ret;
644 xmlParserCtxtPtr ctxt;
645 xmlSAXHandler silent, *old;
646
647 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000648
649 if (ctxt == NULL) {
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000650 /* If xmlCreateFileParserCtxt() return NULL something
Daniel Veillard88a172f2000-08-04 18:23:10 +0000651 strange happened so we don't want to do anything. Do
652 we want to print an error message here?
653 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000654 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000655 } else {
656 memcpy(&silent, ctxt->sax, sizeof(silent));
657 old = ctxt->sax;
658 silent.error = xmlHTMLError;
659 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000660 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000661 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000662 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000663 silent.fatalError = xmlHTMLError;
664 ctxt->sax = &silent;
665 ctxt->vctxt.error = xmlHTMLValidityError;
666 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000667 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000668 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000669 ctxt->vctxt.warning = NULL;
670
Daniel Veillard88a172f2000-08-04 18:23:10 +0000671 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000672
Daniel Veillard88a172f2000-08-04 18:23:10 +0000673 ret = ctxt->wellFormed;
674 doc = ctxt->myDoc;
675 ctxt->sax = old;
676 xmlFreeParserCtxt(ctxt);
677 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000678 xmlFreeDoc(doc);
679 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000680 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000681 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000682#ifdef HAVE_SYS_MMAN_H
683 } else if (memory) {
684 int fd;
685 struct stat info;
686 const char *base;
687 if (stat(filename, &info) < 0)
688 return;
689 if ((fd = open(filename, O_RDONLY)) < 0)
690 return;
691 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000692 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000693 return;
694
695 doc = xmlParseMemory((char *) base, info.st_size);
696 munmap((char *) base, info.st_size);
697#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000698 } else
699 doc = xmlParseFile(filename);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000700 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000701
Daniel Veillard88a172f2000-08-04 18:23:10 +0000702 /*
703 * If we don't have a document we might as well give up. Do we
704 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000705 if (doc == NULL) {
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000706 progresult = 1;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000707 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000708 }
709
Daniel Veillard48b2f892001-02-25 16:11:03 +0000710 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000711 endTimer("Parsing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000712 }
713
Daniel Veillard29e43992001-12-13 22:21:58 +0000714 /*
715 * Remove DOCTYPE nodes
716 */
717 if (dropdtd) {
718 xmlDtdPtr dtd;
719
720 dtd = xmlGetIntSubset(doc);
721 if (dtd != NULL) {
722 xmlUnlinkNode((xmlNodePtr)dtd);
723 xmlFreeDtd(dtd);
724 }
725 }
726
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000727#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard48b2f892001-02-25 16:11:03 +0000728 if (xinclude) {
729 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000730 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000731 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000732 xmlXIncludeProcess(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000733 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000734 endTimer("Xinclude processing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000735 }
736 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000737#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000738
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000739#ifdef LIBXML_DEBUG_ENABLED
740 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000741 * shell interaction
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000742 */
743 if (shell)
744 xmlShell(doc, filename, xmlShellReadline, stdout);
745#endif
746
747 /*
748 * test intermediate copy if needed.
749 */
750 if (copy) {
751 tmp = doc;
752 doc = xmlCopyDoc(doc, 1);
753 xmlFreeDoc(tmp);
754 }
755
756 if ((insert) && (!html)) {
757 const xmlChar* list[256];
758 int nb, i;
759 xmlNodePtr node;
760
761 if (doc->children != NULL) {
762 node = doc->children;
763 while ((node != NULL) && (node->last == NULL)) node = node->next;
764 if (node != NULL) {
765 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
766 if (nb < 0) {
767 printf("could not get valid list of elements\n");
768 } else if (nb == 0) {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000769 printf("No element can be inserted under root\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000770 } else {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000771 printf("%d element types can be inserted under root:\n",
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000772 nb);
773 for (i = 0;i < nb;i++) {
774 printf("%s\n", list[i]);
775 }
776 }
777 }
778 }
779 }else if (noout == 0) {
780 /*
781 * print it.
782 */
783#ifdef LIBXML_DEBUG_ENABLED
784 if (!debug) {
785#endif
Daniel Veillard48b2f892001-02-25 16:11:03 +0000786 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000787 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000788 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000789#ifdef HAVE_SYS_MMAN_H
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000790 if (memory) {
791 xmlChar *result;
792 int len;
793
794 if (encoding != NULL) {
Daniel Veillardd536f702001-11-08 17:32:47 +0000795 if ( format ) {
796 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
797 } else {
798 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
799 }
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000800 } else {
Daniel Veillard90493a92001-08-14 14:12:47 +0000801 if (format)
802 xmlDocDumpFormatMemory(doc, &result, &len, 1);
803 else
804 xmlDocDumpMemory(doc, &result, &len);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000805 }
806 if (result == NULL) {
807 fprintf(stderr, "Failed to save\n");
808 } else {
809 write(1, result, len);
810 xmlFree(result);
811 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000812 } else
813#endif /* HAVE_SYS_MMAN_H */
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000814 if (compress) {
815 xmlSaveFile(output ? output : "-", doc);
816 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000817 else if (encoding != NULL) {
818 if ( format ) {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000819 xmlSaveFormatFileEnc(output ? output : "-", doc, encoding, 1);
820 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000821 else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000822 xmlSaveFileEnc(output ? output : "-", doc, encoding);
Daniel Veillardd536f702001-11-08 17:32:47 +0000823 }
824 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000825 else if (format) {
826 xmlSaveFormatFile(output ? output : "-", doc, 1);
827 }
828 else {
829 FILE *out;
830 if (output == NULL)
831 out = stdout;
832 else {
833 out = fopen(output,"wb");
834 }
835 xmlDocDump(out, doc);
836
837 if (output)
838 fclose(out);
839 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000840 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000841 endTimer("Saving");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000842 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000843#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000844 } else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000845 FILE *out;
846 if (output == NULL)
847 out = stdout;
848 else {
849 out = fopen(output,"wb");
850 }
851 xmlDebugDumpDocument(out, doc);
852
853 if (output)
854 fclose(out);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000855 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000856#endif
857 }
858
859 /*
860 * A posteriori validation test
861 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000862 if (dtdvalid != NULL) {
863 xmlDtdPtr dtd;
864
Daniel Veillard48b2f892001-02-25 16:11:03 +0000865 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000866 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000867 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000868 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000869 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000870 endTimer("Parsing DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000871 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000872 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000873 xmlGenericError(xmlGenericErrorContext,
874 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000875 progresult = 2;
Daniel Veillardcd429612000-10-11 15:57:05 +0000876 } else {
877 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000878 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000879 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000880 }
Daniel Veillard01db67c2001-12-18 07:09:59 +0000881 cvp.userData = (void *) stderr;
882 cvp.error = (xmlValidityErrorFunc) fprintf;
883 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000884 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000885 xmlGenericError(xmlGenericErrorContext,
886 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000887 filename, dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000888 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000889 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000890 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000891 endTimer("Validating against DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000892 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000893 xmlFreeDtd(dtd);
894 }
895 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000896 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000897 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000898 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000899 }
Daniel Veillardb7664f42001-08-19 13:00:43 +0000900 cvp.userData = (void *) stderr;
901 cvp.error = (xmlValidityErrorFunc) fprintf;
902 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000903 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000904 xmlGenericError(xmlGenericErrorContext,
905 "Document %s does not validate\n", filename);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000906 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000907 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000908 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000909 endTimer("Validating");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000910 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000911 }
912
913#ifdef LIBXML_DEBUG_ENABLED
914 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000915 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000916#endif
917
918 /*
919 * free it.
920 */
Daniel Veillard48b2f892001-02-25 16:11:03 +0000921 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000922 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000923 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000924 xmlFreeDoc(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000925 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000926 endTimer("Freeing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000927 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000928}
929
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000930/************************************************************************
931 * *
932 * Usage and Main *
933 * *
934 ************************************************************************/
935
936static void usage(const char *name) {
937 printf("Usage : %s [options] XMLfiles ...\n", name);
938 printf("\tParse the XML files and output the result of the parsing\n");
939 printf("\t--version : display the version of the XML library used\n");
940#ifdef LIBXML_DEBUG_ENABLED
941 printf("\t--debug : dump a debug tree of the in-memory document\n");
942 printf("\t--shell : run a navigating shell\n");
943 printf("\t--debugent : debug the entities defined in the document\n");
944#endif
945 printf("\t--copy : used to test the internal copy implementation\n");
946 printf("\t--recover : output what was parsable on broken XML documents\n");
947 printf("\t--noent : substitute entity references by their value\n");
948 printf("\t--noout : don't output the result tree\n");
949 printf("\t--htmlout : output results as HTML\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000950 printf("\t--nowrap : do not put HTML doc wrapper\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000951 printf("\t--valid : validate the document in addition to std well-formed check\n");
952 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
953 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
954 printf("\t--timing : print some timings\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000955 printf("\t--output file or -o file: save to a given file\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000956 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
957 printf("\t--insert : ad-hoc test for valid insertions\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000958#ifdef HAVE_ZLIB_H
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000959 printf("\t--compress : turn on gzip compression of output\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000960#endif
Daniel Veillard89cad532001-10-22 09:46:13 +0000961#ifdef LIBXML_DOCB_ENABLED
962 printf("\t--sgml : use the DocBook SGML parser\n");
963#endif
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000964#ifdef LIBXML_HTML_ENABLED
965 printf("\t--html : use the HTML parser\n");
966#endif
967 printf("\t--push : use the push mode of the parser\n");
968#ifdef HAVE_SYS_MMAN_H
969 printf("\t--memory : parse from memory\n");
970#endif
971 printf("\t--nowarning : do not emit warnings from parser/validator\n");
972 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard90493a92001-08-14 14:12:47 +0000973 printf("\t--format : reformat/reindent the input\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000974 printf("\t--testIO : test user I/O support\n");
975 printf("\t--encode encoding : output in the given encoding\n");
976#ifdef LIBXML_CATALOG_ENABLED
Daniel Veillardbd9b0e82001-11-26 10:32:08 +0000977 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
978 printf("\t otherwise XML Catalogs starting from \n");
979 printf("\t file:///etc/xml/catalog are activated by default\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000980 printf("\t--nocatalogs: deactivate all catalogs\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000981#endif
982 printf("\t--auto : generate a small doc on the fly\n");
983#ifdef LIBXML_XINCLUDE_ENABLED
984 printf("\t--xinclude : do XInclude processing\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000985#endif
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000986 printf("\t--loaddtd : fetch external DTD\n");
Daniel Veillard48da9102001-08-07 01:10:10 +0000987 printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
Daniel Veillard29e43992001-12-13 22:21:58 +0000988 printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
Daniel Veillarda42f25f2002-01-25 14:15:40 +0000989 printf("\nLibxml project home page: http://xmlsoft.org/\n");
990 printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000991}
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000992int
993main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000994 int i, count;
995 int files = 0;
Daniel Veillard845cce42002-01-09 11:51:37 +0000996 int version = 0;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000997
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000998 if (argc <= 1) {
999 usage(argv[0]);
1000 return(1);
1001 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001002 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001003 for (i = 1; i < argc ; i++) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001004 if (!strcmp(argv[i], "-"))
1005 break;
1006
1007 if (argv[i][0] != '-')
1008 continue;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001009#ifdef LIBXML_DEBUG_ENABLED
1010 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
1011 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001012 else if ((!strcmp(argv[i], "-shell")) ||
1013 (!strcmp(argv[i], "--shell"))) {
1014 shell++;
1015 noout = 1;
1016 } else
1017#endif
1018 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
1019 copy++;
1020 else if ((!strcmp(argv[i], "-recover")) ||
1021 (!strcmp(argv[i], "--recover")))
1022 recovery++;
1023 else if ((!strcmp(argv[i], "-noent")) ||
1024 (!strcmp(argv[i], "--noent")))
1025 noent++;
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001026 else if ((!strcmp(argv[i], "-version")) ||
Daniel Veillard845cce42002-01-09 11:51:37 +00001027 (!strcmp(argv[i], "--version"))) {
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001028 fprintf(stderr, "xmllint: using libxml version %s\n",
1029 xmlParserVersion);
Daniel Veillard845cce42002-01-09 11:51:37 +00001030 version = 1;
1031 } else if ((!strcmp(argv[i], "-noout")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001032 (!strcmp(argv[i], "--noout")))
1033 noout++;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001034 else if ((!strcmp(argv[i], "-o")) ||
1035 (!strcmp(argv[i], "-output")) ||
1036 (!strcmp(argv[i], "--output"))) {
1037 i++;
1038 output = argv[i++];
1039 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001040 else if ((!strcmp(argv[i], "-htmlout")) ||
1041 (!strcmp(argv[i], "--htmlout")))
1042 htmlout++;
Daniel Veillard89cad532001-10-22 09:46:13 +00001043#ifdef LIBXML_DOCB_ENABLED
1044 else if ((!strcmp(argv[i], "-sgml")) ||
1045 (!strcmp(argv[i], "--sgml"))) {
1046 sgml++;
1047 }
1048#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001049#ifdef LIBXML_HTML_ENABLED
1050 else if ((!strcmp(argv[i], "-html")) ||
1051 (!strcmp(argv[i], "--html"))) {
1052 html++;
1053 }
1054#endif /* LIBXML_HTML_ENABLED */
1055 else if ((!strcmp(argv[i], "-nowrap")) ||
1056 (!strcmp(argv[i], "--nowrap")))
1057 nowrap++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001058 else if ((!strcmp(argv[i], "-loaddtd")) ||
1059 (!strcmp(argv[i], "--loaddtd")))
1060 loaddtd++;
Daniel Veillard48da9102001-08-07 01:10:10 +00001061 else if ((!strcmp(argv[i], "-dtdattr")) ||
1062 (!strcmp(argv[i], "--dtdattr"))) {
1063 loaddtd++;
1064 dtdattrs++;
1065 } else if ((!strcmp(argv[i], "-valid")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001066 (!strcmp(argv[i], "--valid")))
1067 valid++;
1068 else if ((!strcmp(argv[i], "-postvalid")) ||
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001069 (!strcmp(argv[i], "--postvalid"))) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001070 postvalid++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001071 loaddtd++;
1072 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
Daniel Veillardcd429612000-10-11 15:57:05 +00001073 (!strcmp(argv[i], "--dtdvalid"))) {
1074 i++;
1075 dtdvalid = argv[i];
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001076 loaddtd++;
Daniel Veillardcd429612000-10-11 15:57:05 +00001077 }
Daniel Veillard29e43992001-12-13 22:21:58 +00001078 else if ((!strcmp(argv[i], "-dropdtd")) ||
1079 (!strcmp(argv[i], "--dropdtd")))
1080 dropdtd++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001081 else if ((!strcmp(argv[i], "-insert")) ||
1082 (!strcmp(argv[i], "--insert")))
1083 insert++;
Daniel Veillard48b2f892001-02-25 16:11:03 +00001084 else if ((!strcmp(argv[i], "-timing")) ||
1085 (!strcmp(argv[i], "--timing")))
1086 timing++;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001087 else if ((!strcmp(argv[i], "-auto")) ||
1088 (!strcmp(argv[i], "--auto")))
1089 generate++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001090 else if ((!strcmp(argv[i], "-repeat")) ||
1091 (!strcmp(argv[i], "--repeat")))
1092 repeat++;
1093 else if ((!strcmp(argv[i], "-push")) ||
1094 (!strcmp(argv[i], "--push")))
1095 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +00001096#ifdef HAVE_SYS_MMAN_H
1097 else if ((!strcmp(argv[i], "-memory")) ||
1098 (!strcmp(argv[i], "--memory")))
1099 memory++;
1100#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +00001101 else if ((!strcmp(argv[i], "-testIO")) ||
1102 (!strcmp(argv[i], "--testIO")))
1103 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +00001104#ifdef LIBXML_XINCLUDE_ENABLED
1105 else if ((!strcmp(argv[i], "-xinclude")) ||
1106 (!strcmp(argv[i], "--xinclude")))
1107 xinclude++;
1108#endif
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001109#ifdef HAVE_ZLIB_H
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001110 else if ((!strcmp(argv[i], "-compress")) ||
1111 (!strcmp(argv[i], "--compress"))) {
1112 compress++;
1113 xmlSetCompressMode(9);
1114 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001115#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001116 else if ((!strcmp(argv[i], "-nowarning")) ||
1117 (!strcmp(argv[i], "--nowarning"))) {
1118 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001119 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001120 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001121 else if ((!strcmp(argv[i], "-pedantic")) ||
1122 (!strcmp(argv[i], "--pedantic"))) {
1123 xmlGetWarningsDefaultValue = 1;
1124 xmlPedanticParserDefault(1);
1125 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001126#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001127 else if ((!strcmp(argv[i], "-debugent")) ||
1128 (!strcmp(argv[i], "--debugent"))) {
1129 debugent++;
1130 xmlParserDebugEntities = 1;
1131 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001132#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00001133#ifdef LIBXML_CATALOG_ENABLED
1134 else if ((!strcmp(argv[i], "-catalogs")) ||
1135 (!strcmp(argv[i], "--catalogs"))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001136 catalogs++;
1137 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1138 (!strcmp(argv[i], "--nocatalogs"))) {
1139 nocatalogs++;
Daniel Veillard81418e32001-05-22 15:08:55 +00001140 }
1141#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001142 else if ((!strcmp(argv[i], "-encode")) ||
1143 (!strcmp(argv[i], "--encode"))) {
1144 i++;
1145 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001146 /*
1147 * OK it's for testing purposes
1148 */
1149 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +00001150 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001151 else if ((!strcmp(argv[i], "-noblanks")) ||
1152 (!strcmp(argv[i], "--noblanks"))) {
1153 noblanks++;
1154 xmlKeepBlanksDefault(0);
Daniel Veillard90493a92001-08-14 14:12:47 +00001155 }
1156 else if ((!strcmp(argv[i], "-format")) ||
1157 (!strcmp(argv[i], "--format"))) {
1158 noblanks++;
1159 format++;
1160 xmlKeepBlanksDefault(0);
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001161 } else {
1162 fprintf(stderr, "Unknown option %s\n", argv[i]);
1163 usage(argv[0]);
1164 return(1);
1165 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001166 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001167
1168#ifdef LIBXML_CATALOG_ENABLED
1169 if (nocatalogs == 0) {
1170 if (catalogs) {
1171 const char *catal;
1172
1173 catal = getenv("SGML_CATALOG_FILES");
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00001174 if (catal != NULL) {
1175 xmlLoadCatalogs(catal);
1176 } else {
1177 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1178 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001179 }
1180 }
1181#endif
Daniel Veillardd9bad132001-07-23 19:39:43 +00001182 xmlLineNumbersDefault(1);
Daniel Veillard48da9102001-08-07 01:10:10 +00001183 if (loaddtd != 0)
1184 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1185 if (dtdattrs)
1186 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001187 if (noent != 0) xmlSubstituteEntitiesDefault(1);
1188 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1189 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001190 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001191 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001192 xmlGenericError(xmlGenericErrorContext,
1193 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1194 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001195 "<html><head><title>%s output</title></head>\n",
1196 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001197 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001198 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1199 argv[0]);
1200 }
1201 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +00001202 if ((!strcmp(argv[i], "-encode")) ||
1203 (!strcmp(argv[i], "--encode"))) {
1204 i++;
1205 continue;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001206 } else if ((!strcmp(argv[i], "-o")) ||
1207 (!strcmp(argv[i], "-output")) ||
1208 (!strcmp(argv[i], "--output"))) {
1209 i++;
1210 continue;
Daniel Veillardbe803962000-06-28 23:40:59 +00001211 }
Daniel Veillardcd429612000-10-11 15:57:05 +00001212 if ((!strcmp(argv[i], "-dtdvalid")) ||
1213 (!strcmp(argv[i], "--dtdvalid"))) {
1214 i++;
1215 continue;
1216 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001217 if ((timing) && (repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +00001218 startTimer();
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001219 /* Remember file names. "-" means stdin. <sven@zen.org> */
Daniel Veillard4a6845d2001-01-03 13:32:39 +00001220 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001221 if (repeat) {
1222 for (count = 0;count < 100 * repeat;count++)
1223 parseAndPrintFile(argv[i]);
1224 } else
1225 parseAndPrintFile(argv[i]);
1226 files ++;
Daniel Veillarda7866932001-12-04 13:14:44 +00001227 if ((timing) && (repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +00001228 endTimer("100 iterations");
Daniel Veillarda7866932001-12-04 13:14:44 +00001229 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001230 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001231 }
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001232 if (generate)
1233 parseAndPrintFile(NULL);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001234 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001235 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001236 }
Daniel Veillard845cce42002-01-09 11:51:37 +00001237 if ((files == 0) && (!generate) && (version == 0)) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001238 usage(argv[0]);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001239 }
1240 xmlCleanupParser();
1241 xmlMemoryDump();
1242
Daniel Veillardf7cd4812001-02-23 18:44:52 +00001243 return(progresult);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001244}
Daniel Veillard88a172f2000-08-04 18:23:10 +00001245