Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xml2/error.c
4389 views
1
/*
2
* error.c: module displaying/handling XML parser errors
3
*
4
* See Copyright for the status of this software.
5
*
6
* Daniel Veillard <[email protected]>
7
*/
8
9
#define IN_LIBXML
10
#include "libxml.h"
11
12
#include <string.h>
13
#include <stdarg.h>
14
#include <libxml/parser.h>
15
#include <libxml/xmlerror.h>
16
#include <libxml/xmlmemory.h>
17
18
#include "private/error.h"
19
20
#define XML_MAX_ERRORS 100
21
22
#define XML_GET_VAR_STR(msg, str) { \
23
int size, prev_size = -1; \
24
int chars; \
25
char *larger; \
26
va_list ap; \
27
\
28
str = (char *) xmlMalloc(150); \
29
if (str != NULL) { \
30
\
31
size = 150; \
32
\
33
while (size < 64000) { \
34
va_start(ap, msg); \
35
chars = vsnprintf(str, size, msg, ap); \
36
va_end(ap); \
37
if ((chars > -1) && (chars < size)) { \
38
if (prev_size == chars) { \
39
break; \
40
} else { \
41
prev_size = chars; \
42
} \
43
} \
44
if (chars > -1) \
45
size += chars + 1; \
46
else \
47
size += 100; \
48
if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
49
break; \
50
} \
51
str = larger; \
52
}} \
53
}
54
55
/************************************************************************
56
* *
57
* Handling of out of context errors *
58
* *
59
************************************************************************/
60
61
/**
62
* xmlGenericErrorDefaultFunc:
63
* @ctx: an error context
64
* @msg: the message to display/transmit
65
* @...: extra parameters for the message display
66
*
67
* Default handler for out of context error messages.
68
*/
69
void
70
xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
71
va_list args;
72
73
if (xmlGenericErrorContext == NULL)
74
xmlGenericErrorContext = (void *) stderr;
75
76
va_start(args, msg);
77
vfprintf((FILE *)xmlGenericErrorContext, msg, args);
78
va_end(args);
79
}
80
81
/**
82
* initGenericErrorDefaultFunc:
83
* @handler: the handler
84
*
85
* DEPRECATED: Use xmlSetGenericErrorFunc.
86
*
87
* Set or reset (if NULL) the default handler for generic errors
88
* to the builtin error function.
89
*/
90
void
91
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
92
{
93
if (handler == NULL)
94
xmlGenericError = xmlGenericErrorDefaultFunc;
95
else
96
xmlGenericError = (*handler);
97
}
98
99
/**
100
* xmlSetGenericErrorFunc:
101
* @ctx: the new error handling context
102
* @handler: the new handler function
103
*
104
* Function to reset the handler and the error context for out of
105
* context error messages.
106
* This simply means that @handler will be called for subsequent
107
* error messages while not parsing nor validating. And @ctx will
108
* be passed as first argument to @handler
109
* One can simply force messages to be emitted to another FILE * than
110
* stderr by setting @ctx to this file handle and @handler to NULL.
111
* For multi-threaded applications, this must be set separately for each thread.
112
*/
113
void
114
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
115
xmlGenericErrorContext = ctx;
116
if (handler != NULL)
117
xmlGenericError = handler;
118
else
119
xmlGenericError = xmlGenericErrorDefaultFunc;
120
}
121
122
/**
123
* xmlSetStructuredErrorFunc:
124
* @ctx: the new error handling context
125
* @handler: the new handler function
126
*
127
* Function to reset the handler and the error context for out of
128
* context structured error messages.
129
* This simply means that @handler will be called for subsequent
130
* error messages while not parsing nor validating. And @ctx will
131
* be passed as first argument to @handler
132
* For multi-threaded applications, this must be set separately for each thread.
133
*/
134
void
135
xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
136
xmlStructuredErrorContext = ctx;
137
xmlStructuredError = handler;
138
}
139
140
/************************************************************************
141
* *
142
* Handling of parsing errors *
143
* *
144
************************************************************************/
145
146
/**
147
* xmlParserPrintFileInfo:
148
* @input: an xmlParserInputPtr input
149
*
150
* Displays the associated file and line information for the current input
151
*/
152
153
void
154
xmlParserPrintFileInfo(xmlParserInputPtr input) {
155
if (input != NULL) {
156
if (input->filename)
157
xmlGenericError(xmlGenericErrorContext,
158
"%s:%d: ", input->filename,
159
input->line);
160
else
161
xmlGenericError(xmlGenericErrorContext,
162
"Entity: line %d: ", input->line);
163
}
164
}
165
166
/**
167
* xmlParserPrintFileContextInternal:
168
* @input: an xmlParserInputPtr input
169
*
170
* Displays current context within the input content for error tracking
171
*/
172
173
static void
174
xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
175
xmlGenericErrorFunc channel, void *data ) {
176
const xmlChar *cur, *base, *start;
177
unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
178
xmlChar content[81]; /* space for 80 chars + line terminator */
179
xmlChar *ctnt;
180
181
if ((input == NULL) || (input->cur == NULL))
182
return;
183
184
cur = input->cur;
185
base = input->base;
186
/* skip backwards over any end-of-lines */
187
while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
188
cur--;
189
}
190
n = 0;
191
/* search backwards for beginning-of-line (to max buff size) */
192
while ((n < sizeof(content) - 1) && (cur > base) &&
193
(*cur != '\n') && (*cur != '\r')) {
194
cur--;
195
n++;
196
}
197
if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
198
cur++;
199
} else {
200
/* skip over continuation bytes */
201
while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
202
cur++;
203
}
204
/* calculate the error position in terms of the current position */
205
col = input->cur - cur;
206
/* search forward for end-of-line (to max buff size) */
207
n = 0;
208
start = cur;
209
/* copy selected text to our buffer */
210
while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
211
int len = input->end - cur;
212
int c = xmlGetUTF8Char(cur, &len);
213
214
if ((c < 0) || (n + len > sizeof(content)-1))
215
break;
216
cur += len;
217
n += len;
218
}
219
memcpy(content, start, n);
220
content[n] = 0;
221
/* print out the selected text */
222
channel(data ,"%s\n", content);
223
/* create blank line with problem pointer */
224
n = 0;
225
ctnt = content;
226
/* (leave buffer space for pointer + line terminator) */
227
while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
228
if (*(ctnt) != '\t')
229
*(ctnt) = ' ';
230
ctnt++;
231
}
232
*ctnt++ = '^';
233
*ctnt = 0;
234
channel(data ,"%s\n", content);
235
}
236
237
/**
238
* xmlParserPrintFileContext:
239
* @input: an xmlParserInputPtr input
240
*
241
* Displays current context within the input content for error tracking
242
*/
243
void
244
xmlParserPrintFileContext(xmlParserInputPtr input) {
245
xmlParserPrintFileContextInternal(input, xmlGenericError,
246
xmlGenericErrorContext);
247
}
248
249
/**
250
* xmlReportError:
251
* @err: the error
252
* @ctx: the parser context or NULL
253
* @str: the formatted error message
254
*
255
* Report an error with its context, replace the 4 old error/warning
256
* routines.
257
*/
258
static void
259
xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
260
xmlGenericErrorFunc channel, void *data)
261
{
262
char *file = NULL;
263
int line = 0;
264
int code = -1;
265
int domain;
266
const xmlChar *name = NULL;
267
xmlNodePtr node;
268
xmlErrorLevel level;
269
xmlParserInputPtr input = NULL;
270
xmlParserInputPtr cur = NULL;
271
272
if (err == NULL)
273
return;
274
275
if (channel == NULL) {
276
channel = xmlGenericError;
277
data = xmlGenericErrorContext;
278
}
279
file = err->file;
280
line = err->line;
281
code = err->code;
282
domain = err->domain;
283
level = err->level;
284
node = err->node;
285
286
if (code == XML_ERR_OK)
287
return;
288
289
if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
290
name = node->name;
291
292
/*
293
* Maintain the compatibility with the legacy error handling
294
*/
295
if (ctxt != NULL) {
296
input = ctxt->input;
297
if ((input != NULL) && (input->filename == NULL) &&
298
(ctxt->inputNr > 1)) {
299
cur = input;
300
input = ctxt->inputTab[ctxt->inputNr - 2];
301
}
302
if (input != NULL) {
303
if (input->filename)
304
channel(data, "%s:%d: ", input->filename, input->line);
305
else if ((line != 0) && (domain == XML_FROM_PARSER))
306
channel(data, "Entity: line %d: ", input->line);
307
}
308
} else {
309
if (file != NULL)
310
channel(data, "%s:%d: ", file, line);
311
else if ((line != 0) &&
312
((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
313
(domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
314
(domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
315
channel(data, "Entity: line %d: ", line);
316
}
317
if (name != NULL) {
318
channel(data, "element %s: ", name);
319
}
320
switch (domain) {
321
case XML_FROM_PARSER:
322
channel(data, "parser ");
323
break;
324
case XML_FROM_NAMESPACE:
325
channel(data, "namespace ");
326
break;
327
case XML_FROM_DTD:
328
case XML_FROM_VALID:
329
channel(data, "validity ");
330
break;
331
case XML_FROM_HTML:
332
channel(data, "HTML parser ");
333
break;
334
case XML_FROM_MEMORY:
335
channel(data, "memory ");
336
break;
337
case XML_FROM_OUTPUT:
338
channel(data, "output ");
339
break;
340
case XML_FROM_IO:
341
channel(data, "I/O ");
342
break;
343
case XML_FROM_XINCLUDE:
344
channel(data, "XInclude ");
345
break;
346
case XML_FROM_XPATH:
347
channel(data, "XPath ");
348
break;
349
case XML_FROM_XPOINTER:
350
channel(data, "parser ");
351
break;
352
case XML_FROM_REGEXP:
353
channel(data, "regexp ");
354
break;
355
case XML_FROM_MODULE:
356
channel(data, "module ");
357
break;
358
case XML_FROM_SCHEMASV:
359
channel(data, "Schemas validity ");
360
break;
361
case XML_FROM_SCHEMASP:
362
channel(data, "Schemas parser ");
363
break;
364
case XML_FROM_RELAXNGP:
365
channel(data, "Relax-NG parser ");
366
break;
367
case XML_FROM_RELAXNGV:
368
channel(data, "Relax-NG validity ");
369
break;
370
case XML_FROM_CATALOG:
371
channel(data, "Catalog ");
372
break;
373
case XML_FROM_C14N:
374
channel(data, "C14N ");
375
break;
376
case XML_FROM_XSLT:
377
channel(data, "XSLT ");
378
break;
379
case XML_FROM_I18N:
380
channel(data, "encoding ");
381
break;
382
case XML_FROM_SCHEMATRONV:
383
channel(data, "schematron ");
384
break;
385
case XML_FROM_BUFFER:
386
channel(data, "internal buffer ");
387
break;
388
case XML_FROM_URI:
389
channel(data, "URI ");
390
break;
391
default:
392
break;
393
}
394
switch (level) {
395
case XML_ERR_NONE:
396
channel(data, ": ");
397
break;
398
case XML_ERR_WARNING:
399
channel(data, "warning : ");
400
break;
401
case XML_ERR_ERROR:
402
channel(data, "error : ");
403
break;
404
case XML_ERR_FATAL:
405
channel(data, "error : ");
406
break;
407
}
408
if (str != NULL) {
409
int len;
410
len = xmlStrlen((const xmlChar *)str);
411
if ((len > 0) && (str[len - 1] != '\n'))
412
channel(data, "%s\n", str);
413
else
414
channel(data, "%s", str);
415
} else {
416
channel(data, "%s\n", "out of memory error");
417
}
418
419
if (ctxt != NULL) {
420
xmlParserPrintFileContextInternal(input, channel, data);
421
if (cur != NULL) {
422
if (cur->filename)
423
channel(data, "%s:%d: \n", cur->filename, cur->line);
424
else if ((line != 0) && (domain == XML_FROM_PARSER))
425
channel(data, "Entity: line %d: \n", cur->line);
426
xmlParserPrintFileContextInternal(cur, channel, data);
427
}
428
}
429
if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
430
(err->int1 < 100) &&
431
(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
432
xmlChar buf[150];
433
int i;
434
435
channel(data, "%s\n", err->str1);
436
for (i=0;i < err->int1;i++)
437
buf[i] = ' ';
438
buf[i++] = '^';
439
buf[i] = 0;
440
channel(data, "%s\n", buf);
441
}
442
}
443
444
/**
445
* __xmlRaiseError:
446
* @schannel: the structured callback channel
447
* @channel: the old callback channel
448
* @data: the callback data
449
* @ctx: the parser context or NULL
450
* @ctx: the parser context or NULL
451
* @domain: the domain for the error
452
* @code: the code for the error
453
* @level: the xmlErrorLevel for the error
454
* @file: the file source of the error (or NULL)
455
* @line: the line of the error or 0 if N/A
456
* @str1: extra string info
457
* @str2: extra string info
458
* @str3: extra string info
459
* @int1: extra int info
460
* @col: column number of the error or 0 if N/A
461
* @msg: the message to display/transmit
462
* @...: extra parameters for the message display
463
*
464
* Update the appropriate global or contextual error structure,
465
* then forward the error message down the parser or generic
466
* error callback handler
467
*/
468
void
469
__xmlRaiseError(xmlStructuredErrorFunc schannel,
470
xmlGenericErrorFunc channel, void *data, void *ctx,
471
void *nod, int domain, int code, xmlErrorLevel level,
472
const char *file, int line, const char *str1,
473
const char *str2, const char *str3, int int1, int col,
474
const char *msg, ...)
475
{
476
xmlParserCtxtPtr ctxt = NULL;
477
xmlNodePtr node = (xmlNodePtr) nod;
478
char *str = NULL;
479
xmlParserInputPtr input = NULL;
480
xmlErrorPtr to = &xmlLastError;
481
xmlNodePtr baseptr = NULL;
482
483
if (code == XML_ERR_OK)
484
return;
485
if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
486
return;
487
if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
488
(domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
489
(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
490
ctxt = (xmlParserCtxtPtr) ctx;
491
492
if (ctxt != NULL) {
493
if (level == XML_ERR_WARNING) {
494
if (ctxt->nbWarnings >= XML_MAX_ERRORS)
495
return;
496
ctxt->nbWarnings += 1;
497
} else {
498
if (ctxt->nbErrors >= XML_MAX_ERRORS)
499
return;
500
ctxt->nbErrors += 1;
501
}
502
503
if ((schannel == NULL) && (ctxt->sax != NULL) &&
504
(ctxt->sax->initialized == XML_SAX2_MAGIC) &&
505
(ctxt->sax->serror != NULL)) {
506
schannel = ctxt->sax->serror;
507
data = ctxt->userData;
508
}
509
}
510
}
511
/*
512
* Check if structured error handler set
513
*/
514
if (schannel == NULL) {
515
schannel = xmlStructuredError;
516
/*
517
* if user has defined handler, change data ptr to user's choice
518
*/
519
if (schannel != NULL)
520
data = xmlStructuredErrorContext;
521
}
522
/*
523
* Formatting the message
524
*/
525
if (msg == NULL) {
526
str = (char *) xmlStrdup(BAD_CAST "No error message provided");
527
} else {
528
XML_GET_VAR_STR(msg, str);
529
}
530
531
/*
532
* specific processing if a parser context is provided
533
*/
534
if (ctxt != NULL) {
535
if (file == NULL) {
536
input = ctxt->input;
537
if ((input != NULL) && (input->filename == NULL) &&
538
(ctxt->inputNr > 1)) {
539
input = ctxt->inputTab[ctxt->inputNr - 2];
540
}
541
if (input != NULL) {
542
file = input->filename;
543
line = input->line;
544
col = input->col;
545
}
546
}
547
to = &ctxt->lastError;
548
} else if ((node != NULL) && (file == NULL)) {
549
int i;
550
551
if ((node->doc != NULL) && (node->doc->URL != NULL)) {
552
baseptr = node;
553
/* file = (const char *) node->doc->URL; */
554
}
555
for (i = 0;
556
((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
557
i++)
558
node = node->parent;
559
if ((baseptr == NULL) && (node != NULL) &&
560
(node->doc != NULL) && (node->doc->URL != NULL))
561
baseptr = node;
562
563
if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
564
line = node->line;
565
if ((line == 0) || (line == 65535))
566
line = xmlGetLineNo(node);
567
}
568
569
/*
570
* Save the information about the error
571
*/
572
xmlResetError(to);
573
to->domain = domain;
574
to->code = code;
575
to->message = str;
576
to->level = level;
577
if (file != NULL)
578
to->file = (char *) xmlStrdup((const xmlChar *) file);
579
else if (baseptr != NULL) {
580
#ifdef LIBXML_XINCLUDE_ENABLED
581
/*
582
* We check if the error is within an XInclude section and,
583
* if so, attempt to print out the href of the XInclude instead
584
* of the usual "base" (doc->URL) for the node (bug 152623).
585
*/
586
xmlNodePtr prev = baseptr;
587
char *href = NULL;
588
int inclcount = 0;
589
while (prev != NULL) {
590
if (prev->prev == NULL)
591
prev = prev->parent;
592
else {
593
prev = prev->prev;
594
if (prev->type == XML_XINCLUDE_START) {
595
if (inclcount > 0) {
596
--inclcount;
597
} else {
598
href = (char *) xmlGetProp(prev, BAD_CAST "href");
599
if (href != NULL)
600
break;
601
}
602
} else if (prev->type == XML_XINCLUDE_END)
603
inclcount++;
604
}
605
}
606
if (href != NULL)
607
to->file = href;
608
else
609
#endif
610
to->file = (char *) xmlStrdup(baseptr->doc->URL);
611
if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
612
to->file = (char *) xmlStrdup(node->doc->URL);
613
}
614
}
615
to->line = line;
616
if (str1 != NULL)
617
to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
618
if (str2 != NULL)
619
to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
620
if (str3 != NULL)
621
to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
622
to->int1 = int1;
623
to->int2 = col;
624
to->node = node;
625
to->ctxt = ctx;
626
627
if (to != &xmlLastError)
628
xmlCopyError(to,&xmlLastError);
629
630
if (schannel != NULL) {
631
schannel(data, to);
632
return;
633
}
634
635
/*
636
* Find the callback channel if channel param is NULL
637
*/
638
if ((ctxt != NULL) && (channel == NULL) &&
639
(xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
640
if (level == XML_ERR_WARNING)
641
channel = ctxt->sax->warning;
642
else
643
channel = ctxt->sax->error;
644
data = ctxt->userData;
645
} else if (channel == NULL) {
646
channel = xmlGenericError;
647
if (ctxt != NULL) {
648
data = ctxt;
649
} else {
650
data = xmlGenericErrorContext;
651
}
652
}
653
if (channel == NULL)
654
return;
655
656
if ((channel == xmlParserError) ||
657
(channel == xmlParserWarning) ||
658
(channel == xmlParserValidityError) ||
659
(channel == xmlParserValidityWarning))
660
xmlReportError(to, ctxt, str, NULL, NULL);
661
else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
662
(channel == xmlGenericErrorDefaultFunc))
663
xmlReportError(to, ctxt, str, channel, data);
664
else
665
channel(data, "%s", str);
666
}
667
668
/**
669
* __xmlSimpleError:
670
* @domain: where the error comes from
671
* @code: the error code
672
* @node: the context node
673
* @extra: extra information
674
*
675
* Handle an out of memory condition
676
*/
677
void
678
__xmlSimpleError(int domain, int code, xmlNodePtr node,
679
const char *msg, const char *extra)
680
{
681
682
if (code == XML_ERR_NO_MEMORY) {
683
if (extra)
684
__xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
685
XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
686
NULL, NULL, 0, 0,
687
"Memory allocation failed : %s\n", extra);
688
else
689
__xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
690
XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
691
NULL, NULL, 0, 0, "Memory allocation failed\n");
692
} else {
693
__xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
694
code, XML_ERR_ERROR, NULL, 0, extra,
695
NULL, NULL, 0, 0, msg, extra);
696
}
697
}
698
/**
699
* xmlParserError:
700
* @ctx: an XML parser context
701
* @msg: the message to display/transmit
702
* @...: extra parameters for the message display
703
*
704
* Display and format an error messages, gives file, line, position and
705
* extra parameters.
706
*/
707
void
708
xmlParserError(void *ctx, const char *msg, ...)
709
{
710
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
711
xmlParserInputPtr input = NULL;
712
xmlParserInputPtr cur = NULL;
713
char * str;
714
715
if (ctxt != NULL) {
716
input = ctxt->input;
717
if ((input != NULL) && (input->filename == NULL) &&
718
(ctxt->inputNr > 1)) {
719
cur = input;
720
input = ctxt->inputTab[ctxt->inputNr - 2];
721
}
722
xmlParserPrintFileInfo(input);
723
}
724
725
xmlGenericError(xmlGenericErrorContext, "error: ");
726
XML_GET_VAR_STR(msg, str);
727
xmlGenericError(xmlGenericErrorContext, "%s", str);
728
if (str != NULL)
729
xmlFree(str);
730
731
if (ctxt != NULL) {
732
xmlParserPrintFileContext(input);
733
if (cur != NULL) {
734
xmlParserPrintFileInfo(cur);
735
xmlGenericError(xmlGenericErrorContext, "\n");
736
xmlParserPrintFileContext(cur);
737
}
738
}
739
}
740
741
/**
742
* xmlParserWarning:
743
* @ctx: an XML parser context
744
* @msg: the message to display/transmit
745
* @...: extra parameters for the message display
746
*
747
* Display and format a warning messages, gives file, line, position and
748
* extra parameters.
749
*/
750
void
751
xmlParserWarning(void *ctx, const char *msg, ...)
752
{
753
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
754
xmlParserInputPtr input = NULL;
755
xmlParserInputPtr cur = NULL;
756
char * str;
757
758
if (ctxt != NULL) {
759
input = ctxt->input;
760
if ((input != NULL) && (input->filename == NULL) &&
761
(ctxt->inputNr > 1)) {
762
cur = input;
763
input = ctxt->inputTab[ctxt->inputNr - 2];
764
}
765
xmlParserPrintFileInfo(input);
766
}
767
768
xmlGenericError(xmlGenericErrorContext, "warning: ");
769
XML_GET_VAR_STR(msg, str);
770
xmlGenericError(xmlGenericErrorContext, "%s", str);
771
if (str != NULL)
772
xmlFree(str);
773
774
if (ctxt != NULL) {
775
xmlParserPrintFileContext(input);
776
if (cur != NULL) {
777
xmlParserPrintFileInfo(cur);
778
xmlGenericError(xmlGenericErrorContext, "\n");
779
xmlParserPrintFileContext(cur);
780
}
781
}
782
}
783
784
/************************************************************************
785
* *
786
* Handling of validation errors *
787
* *
788
************************************************************************/
789
790
/**
791
* xmlParserValidityError:
792
* @ctx: an XML parser context
793
* @msg: the message to display/transmit
794
* @...: extra parameters for the message display
795
*
796
* Display and format an validity error messages, gives file,
797
* line, position and extra parameters.
798
*/
799
void
800
xmlParserValidityError(void *ctx, const char *msg, ...)
801
{
802
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
803
xmlParserInputPtr input = NULL;
804
char * str;
805
int len = xmlStrlen((const xmlChar *) msg);
806
static int had_info = 0;
807
808
if ((len > 1) && (msg[len - 2] != ':')) {
809
if (ctxt != NULL) {
810
input = ctxt->input;
811
if ((input->filename == NULL) && (ctxt->inputNr > 1))
812
input = ctxt->inputTab[ctxt->inputNr - 2];
813
814
if (had_info == 0) {
815
xmlParserPrintFileInfo(input);
816
}
817
}
818
xmlGenericError(xmlGenericErrorContext, "validity error: ");
819
had_info = 0;
820
} else {
821
had_info = 1;
822
}
823
824
XML_GET_VAR_STR(msg, str);
825
xmlGenericError(xmlGenericErrorContext, "%s", str);
826
if (str != NULL)
827
xmlFree(str);
828
829
if ((ctxt != NULL) && (input != NULL)) {
830
xmlParserPrintFileContext(input);
831
}
832
}
833
834
/**
835
* xmlParserValidityWarning:
836
* @ctx: an XML parser context
837
* @msg: the message to display/transmit
838
* @...: extra parameters for the message display
839
*
840
* Display and format a validity warning messages, gives file, line,
841
* position and extra parameters.
842
*/
843
void
844
xmlParserValidityWarning(void *ctx, const char *msg, ...)
845
{
846
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
847
xmlParserInputPtr input = NULL;
848
char * str;
849
int len = xmlStrlen((const xmlChar *) msg);
850
851
if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
852
input = ctxt->input;
853
if ((input->filename == NULL) && (ctxt->inputNr > 1))
854
input = ctxt->inputTab[ctxt->inputNr - 2];
855
856
xmlParserPrintFileInfo(input);
857
}
858
859
xmlGenericError(xmlGenericErrorContext, "validity warning: ");
860
XML_GET_VAR_STR(msg, str);
861
xmlGenericError(xmlGenericErrorContext, "%s", str);
862
if (str != NULL)
863
xmlFree(str);
864
865
if (ctxt != NULL) {
866
xmlParserPrintFileContext(input);
867
}
868
}
869
870
871
/************************************************************************
872
* *
873
* Extended Error Handling *
874
* *
875
************************************************************************/
876
877
/**
878
* xmlGetLastError:
879
*
880
* Get the last global error registered. This is per thread if compiled
881
* with thread support.
882
*
883
* Returns a pointer to the error
884
*/
885
const xmlError *
886
xmlGetLastError(void)
887
{
888
if (xmlLastError.code == XML_ERR_OK)
889
return (NULL);
890
return (&xmlLastError);
891
}
892
893
/**
894
* xmlResetError:
895
* @err: pointer to the error.
896
*
897
* Cleanup the error.
898
*/
899
void
900
xmlResetError(xmlErrorPtr err)
901
{
902
if (err == NULL)
903
return;
904
if (err->code == XML_ERR_OK)
905
return;
906
if (err->message != NULL)
907
xmlFree(err->message);
908
if (err->file != NULL)
909
xmlFree(err->file);
910
if (err->str1 != NULL)
911
xmlFree(err->str1);
912
if (err->str2 != NULL)
913
xmlFree(err->str2);
914
if (err->str3 != NULL)
915
xmlFree(err->str3);
916
memset(err, 0, sizeof(xmlError));
917
err->code = XML_ERR_OK;
918
}
919
920
/**
921
* xmlResetLastError:
922
*
923
* Cleanup the last global error registered. For parsing error
924
* this does not change the well-formedness result.
925
*/
926
void
927
xmlResetLastError(void)
928
{
929
if (xmlLastError.code == XML_ERR_OK)
930
return;
931
xmlResetError(&xmlLastError);
932
}
933
934
/**
935
* xmlCtxtGetLastError:
936
* @ctx: an XML parser context
937
*
938
* Get the last parsing error registered.
939
*
940
* Returns NULL if no error occurred or a pointer to the error
941
*/
942
const xmlError *
943
xmlCtxtGetLastError(void *ctx)
944
{
945
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
946
947
if (ctxt == NULL)
948
return (NULL);
949
if (ctxt->lastError.code == XML_ERR_OK)
950
return (NULL);
951
return (&ctxt->lastError);
952
}
953
954
/**
955
* xmlCtxtResetLastError:
956
* @ctx: an XML parser context
957
*
958
* Cleanup the last global error registered. For parsing error
959
* this does not change the well-formedness result.
960
*/
961
void
962
xmlCtxtResetLastError(void *ctx)
963
{
964
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
965
966
if (ctxt == NULL)
967
return;
968
ctxt->errNo = XML_ERR_OK;
969
if (ctxt->lastError.code == XML_ERR_OK)
970
return;
971
xmlResetError(&ctxt->lastError);
972
}
973
974
/**
975
* xmlCopyError:
976
* @from: a source error
977
* @to: a target error
978
*
979
* Save the original error to the new place.
980
*
981
* Returns 0 in case of success and -1 in case of error.
982
*/
983
int
984
xmlCopyError(const xmlError *from, xmlErrorPtr to) {
985
char *message, *file, *str1, *str2, *str3;
986
987
if ((from == NULL) || (to == NULL))
988
return(-1);
989
990
message = (char *) xmlStrdup((xmlChar *) from->message);
991
file = (char *) xmlStrdup ((xmlChar *) from->file);
992
str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
993
str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
994
str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
995
996
if (to->message != NULL)
997
xmlFree(to->message);
998
if (to->file != NULL)
999
xmlFree(to->file);
1000
if (to->str1 != NULL)
1001
xmlFree(to->str1);
1002
if (to->str2 != NULL)
1003
xmlFree(to->str2);
1004
if (to->str3 != NULL)
1005
xmlFree(to->str3);
1006
to->domain = from->domain;
1007
to->code = from->code;
1008
to->level = from->level;
1009
to->line = from->line;
1010
to->node = from->node;
1011
to->int1 = from->int1;
1012
to->int2 = from->int2;
1013
to->node = from->node;
1014
to->ctxt = from->ctxt;
1015
to->message = message;
1016
to->file = file;
1017
to->str1 = str1;
1018
to->str2 = str2;
1019
to->str3 = str3;
1020
1021
return 0;
1022
}
1023
1024