xmlwf.c revision 1.1.1.5.6.1 1 1.1.1.5.6.1 martin /*
2 1.1.1.5.6.1 martin __ __ _
3 1.1.1.5.6.1 martin ___\ \/ /_ __ __ _| |_
4 1.1.1.5.6.1 martin / _ \\ /| '_ \ / _` | __|
5 1.1.1.5.6.1 martin | __// \| |_) | (_| | |_
6 1.1.1.5.6.1 martin \___/_/\_\ .__/ \__,_|\__|
7 1.1.1.5.6.1 martin |_| XML parser
8 1.1.1.5.6.1 martin
9 1.1.1.5.6.1 martin Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 1.1.1.5.6.1 martin Copyright (c) 2000-2017 Expat development team
11 1.1.1.5.6.1 martin Licensed under the MIT license:
12 1.1.1.5.6.1 martin
13 1.1.1.5.6.1 martin Permission is hereby granted, free of charge, to any person obtaining
14 1.1.1.5.6.1 martin a copy of this software and associated documentation files (the
15 1.1.1.5.6.1 martin "Software"), to deal in the Software without restriction, including
16 1.1.1.5.6.1 martin without limitation the rights to use, copy, modify, merge, publish,
17 1.1.1.5.6.1 martin distribute, sublicense, and/or sell copies of the Software, and to permit
18 1.1.1.5.6.1 martin persons to whom the Software is furnished to do so, subject to the
19 1.1.1.5.6.1 martin following conditions:
20 1.1.1.5.6.1 martin
21 1.1.1.5.6.1 martin The above copyright notice and this permission notice shall be included
22 1.1.1.5.6.1 martin in all copies or substantial portions of the Software.
23 1.1.1.5.6.1 martin
24 1.1.1.5.6.1 martin THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 1.1.1.5.6.1 martin EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 1.1.1.5.6.1 martin MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 1.1.1.5.6.1 martin NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 1.1.1.5.6.1 martin DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 1.1.1.5.6.1 martin OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 1.1.1.5.6.1 martin USE OR OTHER DEALINGS IN THE SOFTWARE.
31 1.1 tron */
32 1.1 tron
33 1.1.1.5.6.1 martin #include <assert.h>
34 1.1 tron #include <stdio.h>
35 1.1 tron #include <stdlib.h>
36 1.1 tron #include <stddef.h>
37 1.1 tron #include <string.h>
38 1.1 tron
39 1.1 tron #include "expat.h"
40 1.1 tron #include "codepage.h"
41 1.1.1.5.6.1 martin #include "internal.h" /* for UNUSED_P only */
42 1.1 tron #include "xmlfile.h"
43 1.1 tron #include "xmltchar.h"
44 1.1 tron
45 1.1 tron #ifdef _MSC_VER
46 1.1.1.5.6.1 martin # include <crtdbg.h>
47 1.1 tron #endif
48 1.1 tron
49 1.1.1.5.6.1 martin #ifdef XML_UNICODE
50 1.1.1.5.6.1 martin # include <wchar.h>
51 1.1.1.5.6.1 martin #endif
52 1.1.1.5.6.1 martin
53 1.1.1.5.6.1 martin /* Structures for handler user data */
54 1.1.1.5.6.1 martin typedef struct NotationList {
55 1.1.1.5.6.1 martin struct NotationList *next;
56 1.1.1.5.6.1 martin const XML_Char *notationName;
57 1.1.1.5.6.1 martin const XML_Char *systemId;
58 1.1.1.5.6.1 martin const XML_Char *publicId;
59 1.1.1.5.6.1 martin } NotationList;
60 1.1.1.5.6.1 martin
61 1.1.1.5.6.1 martin typedef struct xmlwfUserData {
62 1.1.1.5.6.1 martin FILE *fp;
63 1.1.1.5.6.1 martin NotationList *notationListHead;
64 1.1.1.5.6.1 martin const XML_Char *currentDoctypeName;
65 1.1.1.5.6.1 martin } XmlwfUserData;
66 1.1.1.5.6.1 martin
67 1.1 tron /* This ensures proper sorting. */
68 1.1 tron
69 1.1 tron #define NSSEP T('\001')
70 1.1 tron
71 1.1 tron static void XMLCALL
72 1.1.1.5.6.1 martin characterData(void *userData, const XML_Char *s, int len) {
73 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
74 1.1 tron for (; len > 0; --len, ++s) {
75 1.1 tron switch (*s) {
76 1.1 tron case T('&'):
77 1.1 tron fputts(T("&"), fp);
78 1.1 tron break;
79 1.1 tron case T('<'):
80 1.1 tron fputts(T("<"), fp);
81 1.1 tron break;
82 1.1 tron case T('>'):
83 1.1 tron fputts(T(">"), fp);
84 1.1 tron break;
85 1.1 tron #ifdef W3C14N
86 1.1 tron case 13:
87 1.1 tron fputts(T("
"), fp);
88 1.1 tron break;
89 1.1 tron #else
90 1.1 tron case T('"'):
91 1.1 tron fputts(T("""), fp);
92 1.1 tron break;
93 1.1 tron case 9:
94 1.1 tron case 10:
95 1.1 tron case 13:
96 1.1 tron ftprintf(fp, T("&#%d;"), *s);
97 1.1 tron break;
98 1.1 tron #endif
99 1.1 tron default:
100 1.1 tron puttc(*s, fp);
101 1.1 tron break;
102 1.1 tron }
103 1.1 tron }
104 1.1 tron }
105 1.1 tron
106 1.1 tron static void
107 1.1.1.5.6.1 martin attributeValue(FILE *fp, const XML_Char *s) {
108 1.1 tron puttc(T('='), fp);
109 1.1 tron puttc(T('"'), fp);
110 1.1.1.5.6.1 martin assert(s);
111 1.1 tron for (;;) {
112 1.1 tron switch (*s) {
113 1.1 tron case 0:
114 1.1 tron case NSSEP:
115 1.1 tron puttc(T('"'), fp);
116 1.1 tron return;
117 1.1 tron case T('&'):
118 1.1 tron fputts(T("&"), fp);
119 1.1 tron break;
120 1.1 tron case T('<'):
121 1.1 tron fputts(T("<"), fp);
122 1.1 tron break;
123 1.1 tron case T('"'):
124 1.1 tron fputts(T("""), fp);
125 1.1 tron break;
126 1.1 tron #ifdef W3C14N
127 1.1 tron case 9:
128 1.1 tron fputts(T("	"), fp);
129 1.1 tron break;
130 1.1 tron case 10:
131 1.1 tron fputts(T("
"), fp);
132 1.1 tron break;
133 1.1 tron case 13:
134 1.1 tron fputts(T("
"), fp);
135 1.1 tron break;
136 1.1 tron #else
137 1.1 tron case T('>'):
138 1.1 tron fputts(T(">"), fp);
139 1.1 tron break;
140 1.1 tron case 9:
141 1.1 tron case 10:
142 1.1 tron case 13:
143 1.1 tron ftprintf(fp, T("&#%d;"), *s);
144 1.1 tron break;
145 1.1 tron #endif
146 1.1 tron default:
147 1.1 tron puttc(*s, fp);
148 1.1 tron break;
149 1.1 tron }
150 1.1 tron s++;
151 1.1 tron }
152 1.1 tron }
153 1.1 tron
154 1.1 tron /* Lexicographically comparing UTF-8 encoded attribute values,
155 1.1 tron is equivalent to lexicographically comparing based on the character number. */
156 1.1 tron
157 1.1 tron static int
158 1.1.1.5.6.1 martin attcmp(const void *att1, const void *att2) {
159 1.1 tron return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
160 1.1 tron }
161 1.1 tron
162 1.1 tron static void XMLCALL
163 1.1.1.5.6.1 martin startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
164 1.1 tron int nAtts;
165 1.1 tron const XML_Char **p;
166 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
167 1.1 tron puttc(T('<'), fp);
168 1.1 tron fputts(name, fp);
169 1.1 tron
170 1.1 tron p = atts;
171 1.1 tron while (*p)
172 1.1 tron ++p;
173 1.1 tron nAtts = (int)((p - atts) >> 1);
174 1.1 tron if (nAtts > 1)
175 1.1 tron qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
176 1.1 tron while (*atts) {
177 1.1 tron puttc(T(' '), fp);
178 1.1 tron fputts(*atts++, fp);
179 1.1 tron attributeValue(fp, *atts);
180 1.1 tron atts++;
181 1.1 tron }
182 1.1 tron puttc(T('>'), fp);
183 1.1 tron }
184 1.1 tron
185 1.1 tron static void XMLCALL
186 1.1.1.5.6.1 martin endElement(void *userData, const XML_Char *name) {
187 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
188 1.1 tron puttc(T('<'), fp);
189 1.1 tron puttc(T('/'), fp);
190 1.1 tron fputts(name, fp);
191 1.1 tron puttc(T('>'), fp);
192 1.1 tron }
193 1.1 tron
194 1.1 tron static int
195 1.1.1.5.6.1 martin nsattcmp(const void *p1, const void *p2) {
196 1.1 tron const XML_Char *att1 = *(const XML_Char **)p1;
197 1.1 tron const XML_Char *att2 = *(const XML_Char **)p2;
198 1.1 tron int sep1 = (tcsrchr(att1, NSSEP) != 0);
199 1.1 tron int sep2 = (tcsrchr(att1, NSSEP) != 0);
200 1.1 tron if (sep1 != sep2)
201 1.1 tron return sep1 - sep2;
202 1.1 tron return tcscmp(att1, att2);
203 1.1 tron }
204 1.1 tron
205 1.1 tron static void XMLCALL
206 1.1.1.5.6.1 martin startElementNS(void *userData, const XML_Char *name, const XML_Char **atts) {
207 1.1 tron int nAtts;
208 1.1 tron int nsi;
209 1.1 tron const XML_Char **p;
210 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
211 1.1 tron const XML_Char *sep;
212 1.1 tron puttc(T('<'), fp);
213 1.1 tron
214 1.1 tron sep = tcsrchr(name, NSSEP);
215 1.1 tron if (sep) {
216 1.1 tron fputts(T("n1:"), fp);
217 1.1 tron fputts(sep + 1, fp);
218 1.1 tron fputts(T(" xmlns:n1"), fp);
219 1.1 tron attributeValue(fp, name);
220 1.1 tron nsi = 2;
221 1.1.1.5.6.1 martin } else {
222 1.1 tron fputts(name, fp);
223 1.1 tron nsi = 1;
224 1.1 tron }
225 1.1 tron
226 1.1 tron p = atts;
227 1.1 tron while (*p)
228 1.1 tron ++p;
229 1.1 tron nAtts = (int)((p - atts) >> 1);
230 1.1 tron if (nAtts > 1)
231 1.1 tron qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
232 1.1 tron while (*atts) {
233 1.1 tron name = *atts++;
234 1.1 tron sep = tcsrchr(name, NSSEP);
235 1.1 tron puttc(T(' '), fp);
236 1.1 tron if (sep) {
237 1.1 tron ftprintf(fp, T("n%d:"), nsi);
238 1.1 tron fputts(sep + 1, fp);
239 1.1.1.5.6.1 martin } else
240 1.1 tron fputts(name, fp);
241 1.1 tron attributeValue(fp, *atts);
242 1.1 tron if (sep) {
243 1.1 tron ftprintf(fp, T(" xmlns:n%d"), nsi++);
244 1.1 tron attributeValue(fp, name);
245 1.1 tron }
246 1.1 tron atts++;
247 1.1 tron }
248 1.1 tron puttc(T('>'), fp);
249 1.1 tron }
250 1.1 tron
251 1.1 tron static void XMLCALL
252 1.1.1.5.6.1 martin endElementNS(void *userData, const XML_Char *name) {
253 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
254 1.1 tron const XML_Char *sep;
255 1.1 tron puttc(T('<'), fp);
256 1.1 tron puttc(T('/'), fp);
257 1.1 tron sep = tcsrchr(name, NSSEP);
258 1.1 tron if (sep) {
259 1.1 tron fputts(T("n1:"), fp);
260 1.1 tron fputts(sep + 1, fp);
261 1.1.1.5.6.1 martin } else
262 1.1 tron fputts(name, fp);
263 1.1 tron puttc(T('>'), fp);
264 1.1 tron }
265 1.1 tron
266 1.1 tron #ifndef W3C14N
267 1.1 tron
268 1.1 tron static void XMLCALL
269 1.1 tron processingInstruction(void *userData, const XML_Char *target,
270 1.1.1.5.6.1 martin const XML_Char *data) {
271 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)userData)->fp;
272 1.1 tron puttc(T('<'), fp);
273 1.1 tron puttc(T('?'), fp);
274 1.1 tron fputts(target, fp);
275 1.1 tron puttc(T(' '), fp);
276 1.1 tron fputts(data, fp);
277 1.1 tron puttc(T('?'), fp);
278 1.1 tron puttc(T('>'), fp);
279 1.1 tron }
280 1.1 tron
281 1.1.1.5.6.1 martin static XML_Char *
282 1.1.1.5.6.1 martin xcsdup(const XML_Char *s) {
283 1.1.1.5.6.1 martin XML_Char *result;
284 1.1.1.5.6.1 martin int count = 0;
285 1.1.1.5.6.1 martin int numBytes;
286 1.1.1.5.6.1 martin
287 1.1.1.5.6.1 martin /* Get the length of the string, including terminator */
288 1.1.1.5.6.1 martin while (s[count++] != 0) {
289 1.1.1.5.6.1 martin /* Do nothing */
290 1.1.1.5.6.1 martin }
291 1.1.1.5.6.1 martin numBytes = count * sizeof(XML_Char);
292 1.1.1.5.6.1 martin result = malloc(numBytes);
293 1.1.1.5.6.1 martin if (result == NULL)
294 1.1.1.5.6.1 martin return NULL;
295 1.1.1.5.6.1 martin memcpy(result, s, numBytes);
296 1.1.1.5.6.1 martin return result;
297 1.1.1.5.6.1 martin }
298 1.1.1.5.6.1 martin
299 1.1.1.5.6.1 martin static void XMLCALL
300 1.1.1.5.6.1 martin startDoctypeDecl(void *userData, const XML_Char *doctypeName,
301 1.1.1.5.6.1 martin const XML_Char *sysid, const XML_Char *publid,
302 1.1.1.5.6.1 martin int has_internal_subset) {
303 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)userData;
304 1.1.1.5.6.1 martin UNUSED_P(sysid);
305 1.1.1.5.6.1 martin UNUSED_P(publid);
306 1.1.1.5.6.1 martin UNUSED_P(has_internal_subset);
307 1.1.1.5.6.1 martin data->currentDoctypeName = xcsdup(doctypeName);
308 1.1.1.5.6.1 martin }
309 1.1.1.5.6.1 martin
310 1.1.1.5.6.1 martin static void
311 1.1.1.5.6.1 martin freeNotations(XmlwfUserData *data) {
312 1.1.1.5.6.1 martin NotationList *notationListHead = data->notationListHead;
313 1.1.1.5.6.1 martin
314 1.1.1.5.6.1 martin while (notationListHead != NULL) {
315 1.1.1.5.6.1 martin NotationList *next = notationListHead->next;
316 1.1.1.5.6.1 martin free((void *)notationListHead->notationName);
317 1.1.1.5.6.1 martin free((void *)notationListHead->systemId);
318 1.1.1.5.6.1 martin free((void *)notationListHead->publicId);
319 1.1.1.5.6.1 martin free(notationListHead);
320 1.1.1.5.6.1 martin notationListHead = next;
321 1.1.1.5.6.1 martin }
322 1.1.1.5.6.1 martin data->notationListHead = NULL;
323 1.1.1.5.6.1 martin }
324 1.1.1.5.6.1 martin
325 1.1.1.5.6.1 martin static int
326 1.1.1.5.6.1 martin xcscmp(const XML_Char *xs, const XML_Char *xt) {
327 1.1.1.5.6.1 martin while (*xs != 0 && *xt != 0) {
328 1.1.1.5.6.1 martin if (*xs < *xt)
329 1.1.1.5.6.1 martin return -1;
330 1.1.1.5.6.1 martin if (*xs > *xt)
331 1.1.1.5.6.1 martin return 1;
332 1.1.1.5.6.1 martin xs++;
333 1.1.1.5.6.1 martin xt++;
334 1.1.1.5.6.1 martin }
335 1.1.1.5.6.1 martin if (*xs < *xt)
336 1.1.1.5.6.1 martin return -1;
337 1.1.1.5.6.1 martin if (*xs > *xt)
338 1.1.1.5.6.1 martin return 1;
339 1.1.1.5.6.1 martin return 0;
340 1.1.1.5.6.1 martin }
341 1.1.1.5.6.1 martin
342 1.1.1.5.6.1 martin static int
343 1.1.1.5.6.1 martin notationCmp(const void *a, const void *b) {
344 1.1.1.5.6.1 martin const NotationList *const n1 = *(NotationList **)a;
345 1.1.1.5.6.1 martin const NotationList *const n2 = *(NotationList **)b;
346 1.1.1.5.6.1 martin
347 1.1.1.5.6.1 martin return xcscmp(n1->notationName, n2->notationName);
348 1.1.1.5.6.1 martin }
349 1.1.1.5.6.1 martin
350 1.1.1.5.6.1 martin static void XMLCALL
351 1.1.1.5.6.1 martin endDoctypeDecl(void *userData) {
352 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)userData;
353 1.1.1.5.6.1 martin NotationList **notations;
354 1.1.1.5.6.1 martin int notationCount = 0;
355 1.1.1.5.6.1 martin NotationList *p;
356 1.1.1.5.6.1 martin int i;
357 1.1.1.5.6.1 martin
358 1.1.1.5.6.1 martin /* How many notations do we have? */
359 1.1.1.5.6.1 martin for (p = data->notationListHead; p != NULL; p = p->next)
360 1.1.1.5.6.1 martin notationCount++;
361 1.1.1.5.6.1 martin if (notationCount == 0) {
362 1.1.1.5.6.1 martin /* Nothing to report */
363 1.1.1.5.6.1 martin free((void *)data->currentDoctypeName);
364 1.1.1.5.6.1 martin data->currentDoctypeName = NULL;
365 1.1.1.5.6.1 martin return;
366 1.1.1.5.6.1 martin }
367 1.1.1.5.6.1 martin
368 1.1.1.5.6.1 martin notations = malloc(notationCount * sizeof(NotationList *));
369 1.1.1.5.6.1 martin if (notations == NULL) {
370 1.1.1.5.6.1 martin fprintf(stderr, "Unable to sort notations");
371 1.1.1.5.6.1 martin freeNotations(data);
372 1.1.1.5.6.1 martin return;
373 1.1.1.5.6.1 martin }
374 1.1.1.5.6.1 martin
375 1.1.1.5.6.1 martin for (p = data->notationListHead, i = 0; i < notationCount; p = p->next, i++) {
376 1.1.1.5.6.1 martin notations[i] = p;
377 1.1.1.5.6.1 martin }
378 1.1.1.5.6.1 martin qsort(notations, notationCount, sizeof(NotationList *), notationCmp);
379 1.1.1.5.6.1 martin
380 1.1.1.5.6.1 martin /* Output the DOCTYPE header */
381 1.1.1.5.6.1 martin fputts(T("<!DOCTYPE "), data->fp);
382 1.1.1.5.6.1 martin fputts(data->currentDoctypeName, data->fp);
383 1.1.1.5.6.1 martin fputts(T(" [\n"), data->fp);
384 1.1.1.5.6.1 martin
385 1.1.1.5.6.1 martin /* Now the NOTATIONs */
386 1.1.1.5.6.1 martin for (i = 0; i < notationCount; i++) {
387 1.1.1.5.6.1 martin fputts(T("<!NOTATION "), data->fp);
388 1.1.1.5.6.1 martin fputts(notations[i]->notationName, data->fp);
389 1.1.1.5.6.1 martin if (notations[i]->publicId != NULL) {
390 1.1.1.5.6.1 martin fputts(T(" PUBLIC '"), data->fp);
391 1.1.1.5.6.1 martin fputts(notations[i]->publicId, data->fp);
392 1.1.1.5.6.1 martin puttc(T('\''), data->fp);
393 1.1.1.5.6.1 martin if (notations[i]->systemId != NULL) {
394 1.1.1.5.6.1 martin puttc(T(' '), data->fp);
395 1.1.1.5.6.1 martin puttc(T('\''), data->fp);
396 1.1.1.5.6.1 martin fputts(notations[i]->systemId, data->fp);
397 1.1.1.5.6.1 martin puttc(T('\''), data->fp);
398 1.1.1.5.6.1 martin }
399 1.1.1.5.6.1 martin } else if (notations[i]->systemId != NULL) {
400 1.1.1.5.6.1 martin fputts(T(" SYSTEM '"), data->fp);
401 1.1.1.5.6.1 martin fputts(notations[i]->systemId, data->fp);
402 1.1.1.5.6.1 martin puttc(T('\''), data->fp);
403 1.1.1.5.6.1 martin }
404 1.1.1.5.6.1 martin puttc(T('>'), data->fp);
405 1.1.1.5.6.1 martin puttc(T('\n'), data->fp);
406 1.1.1.5.6.1 martin }
407 1.1.1.5.6.1 martin
408 1.1.1.5.6.1 martin /* Finally end the DOCTYPE */
409 1.1.1.5.6.1 martin fputts(T("]>\n"), data->fp);
410 1.1.1.5.6.1 martin
411 1.1.1.5.6.1 martin free(notations);
412 1.1.1.5.6.1 martin freeNotations(data);
413 1.1.1.5.6.1 martin free((void *)data->currentDoctypeName);
414 1.1.1.5.6.1 martin data->currentDoctypeName = NULL;
415 1.1.1.5.6.1 martin }
416 1.1.1.5.6.1 martin
417 1.1.1.5.6.1 martin static void XMLCALL
418 1.1.1.5.6.1 martin notationDecl(void *userData, const XML_Char *notationName, const XML_Char *base,
419 1.1.1.5.6.1 martin const XML_Char *systemId, const XML_Char *publicId) {
420 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)userData;
421 1.1.1.5.6.1 martin NotationList *entry = malloc(sizeof(NotationList));
422 1.1.1.5.6.1 martin const char *errorMessage = "Unable to store NOTATION for output\n";
423 1.1.1.5.6.1 martin
424 1.1.1.5.6.1 martin UNUSED_P(base);
425 1.1.1.5.6.1 martin if (entry == NULL) {
426 1.1.1.5.6.1 martin fputs(errorMessage, stderr);
427 1.1.1.5.6.1 martin return; /* Nothing we can really do about this */
428 1.1.1.5.6.1 martin }
429 1.1.1.5.6.1 martin entry->notationName = xcsdup(notationName);
430 1.1.1.5.6.1 martin if (entry->notationName == NULL) {
431 1.1.1.5.6.1 martin fputs(errorMessage, stderr);
432 1.1.1.5.6.1 martin free(entry);
433 1.1.1.5.6.1 martin return;
434 1.1.1.5.6.1 martin }
435 1.1.1.5.6.1 martin if (systemId != NULL) {
436 1.1.1.5.6.1 martin entry->systemId = xcsdup(systemId);
437 1.1.1.5.6.1 martin if (entry->systemId == NULL) {
438 1.1.1.5.6.1 martin fputs(errorMessage, stderr);
439 1.1.1.5.6.1 martin free((void *)entry->notationName);
440 1.1.1.5.6.1 martin free(entry);
441 1.1.1.5.6.1 martin return;
442 1.1.1.5.6.1 martin }
443 1.1.1.5.6.1 martin } else {
444 1.1.1.5.6.1 martin entry->systemId = NULL;
445 1.1.1.5.6.1 martin }
446 1.1.1.5.6.1 martin if (publicId != NULL) {
447 1.1.1.5.6.1 martin entry->publicId = xcsdup(publicId);
448 1.1.1.5.6.1 martin if (entry->publicId == NULL) {
449 1.1.1.5.6.1 martin fputs(errorMessage, stderr);
450 1.1.1.5.6.1 martin free((void *)entry->systemId); /* Safe if it's NULL */
451 1.1.1.5.6.1 martin free((void *)entry->notationName);
452 1.1.1.5.6.1 martin free(entry);
453 1.1.1.5.6.1 martin return;
454 1.1.1.5.6.1 martin }
455 1.1.1.5.6.1 martin } else {
456 1.1.1.5.6.1 martin entry->publicId = NULL;
457 1.1.1.5.6.1 martin }
458 1.1.1.5.6.1 martin
459 1.1.1.5.6.1 martin entry->next = data->notationListHead;
460 1.1.1.5.6.1 martin data->notationListHead = entry;
461 1.1.1.5.6.1 martin }
462 1.1.1.5.6.1 martin
463 1.1 tron #endif /* not W3C14N */
464 1.1 tron
465 1.1 tron static void XMLCALL
466 1.1.1.5.6.1 martin defaultCharacterData(void *userData, const XML_Char *s, int len) {
467 1.1.1.5.6.1 martin UNUSED_P(s);
468 1.1.1.5.6.1 martin UNUSED_P(len);
469 1.1.1.5.6.1 martin XML_DefaultCurrent((XML_Parser)userData);
470 1.1 tron }
471 1.1 tron
472 1.1 tron static void XMLCALL
473 1.1.1.5.6.1 martin defaultStartElement(void *userData, const XML_Char *name,
474 1.1.1.5.6.1 martin const XML_Char **atts) {
475 1.1.1.5.6.1 martin UNUSED_P(name);
476 1.1.1.5.6.1 martin UNUSED_P(atts);
477 1.1.1.5.6.1 martin XML_DefaultCurrent((XML_Parser)userData);
478 1.1 tron }
479 1.1 tron
480 1.1 tron static void XMLCALL
481 1.1.1.5.6.1 martin defaultEndElement(void *userData, const XML_Char *name) {
482 1.1.1.5.6.1 martin UNUSED_P(name);
483 1.1.1.5.6.1 martin XML_DefaultCurrent((XML_Parser)userData);
484 1.1 tron }
485 1.1 tron
486 1.1 tron static void XMLCALL
487 1.1.1.5.6.1 martin defaultProcessingInstruction(void *userData, const XML_Char *target,
488 1.1.1.5.6.1 martin const XML_Char *data) {
489 1.1.1.5.6.1 martin UNUSED_P(target);
490 1.1.1.5.6.1 martin UNUSED_P(data);
491 1.1.1.5.6.1 martin XML_DefaultCurrent((XML_Parser)userData);
492 1.1 tron }
493 1.1 tron
494 1.1 tron static void XMLCALL
495 1.1.1.5.6.1 martin nopCharacterData(void *userData, const XML_Char *s, int len) {
496 1.1.1.5.6.1 martin UNUSED_P(userData);
497 1.1.1.5.6.1 martin UNUSED_P(s);
498 1.1.1.5.6.1 martin UNUSED_P(len);
499 1.1 tron }
500 1.1 tron
501 1.1 tron static void XMLCALL
502 1.1.1.5.6.1 martin nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
503 1.1.1.5.6.1 martin UNUSED_P(userData);
504 1.1.1.5.6.1 martin UNUSED_P(name);
505 1.1.1.5.6.1 martin UNUSED_P(atts);
506 1.1 tron }
507 1.1 tron
508 1.1 tron static void XMLCALL
509 1.1.1.5.6.1 martin nopEndElement(void *userData, const XML_Char *name) {
510 1.1.1.5.6.1 martin UNUSED_P(userData);
511 1.1.1.5.6.1 martin UNUSED_P(name);
512 1.1 tron }
513 1.1 tron
514 1.1 tron static void XMLCALL
515 1.1.1.5.6.1 martin nopProcessingInstruction(void *userData, const XML_Char *target,
516 1.1.1.5.6.1 martin const XML_Char *data) {
517 1.1.1.5.6.1 martin UNUSED_P(userData);
518 1.1.1.5.6.1 martin UNUSED_P(target);
519 1.1.1.5.6.1 martin UNUSED_P(data);
520 1.1 tron }
521 1.1 tron
522 1.1 tron static void XMLCALL
523 1.1.1.5.6.1 martin markup(void *userData, const XML_Char *s, int len) {
524 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp;
525 1.1 tron for (; len > 0; --len, ++s)
526 1.1 tron puttc(*s, fp);
527 1.1 tron }
528 1.1 tron
529 1.1 tron static void
530 1.1.1.5.6.1 martin metaLocation(XML_Parser parser) {
531 1.1 tron const XML_Char *uri = XML_GetBase(parser);
532 1.1.1.5.6.1 martin FILE *fp = ((XmlwfUserData *)XML_GetUserData(parser))->fp;
533 1.1 tron if (uri)
534 1.1.1.5.6.1 martin ftprintf(fp, T(" uri=\"%s\""), uri);
535 1.1.1.5.6.1 martin ftprintf(fp,
536 1.1.1.5.6.1 martin T(" byte=\"%") T(XML_FMT_INT_MOD) T("d\"") T(" nbytes=\"%d\"")
537 1.1.1.5.6.1 martin T(" line=\"%") T(XML_FMT_INT_MOD) T("u\"") T(" col=\"%")
538 1.1.1.5.6.1 martin T(XML_FMT_INT_MOD) T("u\""),
539 1.1.1.5.6.1 martin XML_GetCurrentByteIndex(parser), XML_GetCurrentByteCount(parser),
540 1.1 tron XML_GetCurrentLineNumber(parser),
541 1.1 tron XML_GetCurrentColumnNumber(parser));
542 1.1 tron }
543 1.1 tron
544 1.1 tron static void
545 1.1.1.5.6.1 martin metaStartDocument(void *userData) {
546 1.1.1.5.6.1 martin fputts(T("<document>\n"),
547 1.1.1.5.6.1 martin ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp);
548 1.1 tron }
549 1.1 tron
550 1.1 tron static void
551 1.1.1.5.6.1 martin metaEndDocument(void *userData) {
552 1.1.1.5.6.1 martin fputts(T("</document>\n"),
553 1.1.1.5.6.1 martin ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp);
554 1.1 tron }
555 1.1 tron
556 1.1 tron static void XMLCALL
557 1.1.1.5.6.1 martin metaStartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
558 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
559 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
560 1.1.1.5.6.1 martin FILE *fp = data->fp;
561 1.1 tron const XML_Char **specifiedAttsEnd
562 1.1.1.5.6.1 martin = atts + XML_GetSpecifiedAttributeCount(parser);
563 1.1 tron const XML_Char **idAttPtr;
564 1.1 tron int idAttIndex = XML_GetIdAttributeIndex(parser);
565 1.1 tron if (idAttIndex < 0)
566 1.1 tron idAttPtr = 0;
567 1.1 tron else
568 1.1 tron idAttPtr = atts + idAttIndex;
569 1.1.1.5.6.1 martin
570 1.1 tron ftprintf(fp, T("<starttag name=\"%s\""), name);
571 1.1 tron metaLocation(parser);
572 1.1 tron if (*atts) {
573 1.1 tron fputts(T(">\n"), fp);
574 1.1 tron do {
575 1.1 tron ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
576 1.1.1.5.6.1 martin characterData(data, atts[1], (int)tcslen(atts[1]));
577 1.1 tron if (atts >= specifiedAttsEnd)
578 1.1 tron fputts(T("\" defaulted=\"yes\"/>\n"), fp);
579 1.1 tron else if (atts == idAttPtr)
580 1.1 tron fputts(T("\" id=\"yes\"/>\n"), fp);
581 1.1 tron else
582 1.1 tron fputts(T("\"/>\n"), fp);
583 1.1 tron } while (*(atts += 2));
584 1.1 tron fputts(T("</starttag>\n"), fp);
585 1.1.1.5.6.1 martin } else
586 1.1 tron fputts(T("/>\n"), fp);
587 1.1 tron }
588 1.1 tron
589 1.1 tron static void XMLCALL
590 1.1.1.5.6.1 martin metaEndElement(void *userData, const XML_Char *name) {
591 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
592 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
593 1.1.1.5.6.1 martin FILE *fp = data->fp;
594 1.1 tron ftprintf(fp, T("<endtag name=\"%s\""), name);
595 1.1 tron metaLocation(parser);
596 1.1 tron fputts(T("/>\n"), fp);
597 1.1 tron }
598 1.1 tron
599 1.1 tron static void XMLCALL
600 1.1 tron metaProcessingInstruction(void *userData, const XML_Char *target,
601 1.1.1.5.6.1 martin const XML_Char *data) {
602 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
603 1.1.1.5.6.1 martin XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
604 1.1.1.5.6.1 martin FILE *fp = usrData->fp;
605 1.1 tron ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
606 1.1.1.5.6.1 martin characterData(usrData, data, (int)tcslen(data));
607 1.1 tron puttc(T('"'), fp);
608 1.1 tron metaLocation(parser);
609 1.1 tron fputts(T("/>\n"), fp);
610 1.1 tron }
611 1.1 tron
612 1.1 tron static void XMLCALL
613 1.1.1.5.6.1 martin metaComment(void *userData, const XML_Char *data) {
614 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
615 1.1.1.5.6.1 martin XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
616 1.1.1.5.6.1 martin FILE *fp = usrData->fp;
617 1.1 tron fputts(T("<comment data=\""), fp);
618 1.1.1.5.6.1 martin characterData(usrData, data, (int)tcslen(data));
619 1.1 tron puttc(T('"'), fp);
620 1.1 tron metaLocation(parser);
621 1.1 tron fputts(T("/>\n"), fp);
622 1.1 tron }
623 1.1 tron
624 1.1 tron static void XMLCALL
625 1.1.1.5.6.1 martin metaStartCdataSection(void *userData) {
626 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
627 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
628 1.1.1.5.6.1 martin FILE *fp = data->fp;
629 1.1 tron fputts(T("<startcdata"), fp);
630 1.1 tron metaLocation(parser);
631 1.1 tron fputts(T("/>\n"), fp);
632 1.1 tron }
633 1.1 tron
634 1.1 tron static void XMLCALL
635 1.1.1.5.6.1 martin metaEndCdataSection(void *userData) {
636 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
637 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
638 1.1.1.5.6.1 martin FILE *fp = data->fp;
639 1.1 tron fputts(T("<endcdata"), fp);
640 1.1 tron metaLocation(parser);
641 1.1 tron fputts(T("/>\n"), fp);
642 1.1 tron }
643 1.1 tron
644 1.1 tron static void XMLCALL
645 1.1.1.5.6.1 martin metaCharacterData(void *userData, const XML_Char *s, int len) {
646 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
647 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
648 1.1.1.5.6.1 martin FILE *fp = data->fp;
649 1.1 tron fputts(T("<chars str=\""), fp);
650 1.1.1.5.6.1 martin characterData(data, s, len);
651 1.1 tron puttc(T('"'), fp);
652 1.1 tron metaLocation(parser);
653 1.1 tron fputts(T("/>\n"), fp);
654 1.1 tron }
655 1.1 tron
656 1.1 tron static void XMLCALL
657 1.1.1.5.6.1 martin metaStartDoctypeDecl(void *userData, const XML_Char *doctypeName,
658 1.1.1.5.6.1 martin const XML_Char *sysid, const XML_Char *pubid,
659 1.1.1.5.6.1 martin int has_internal_subset) {
660 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
661 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
662 1.1.1.5.6.1 martin FILE *fp = data->fp;
663 1.1.1.5.6.1 martin UNUSED_P(sysid);
664 1.1.1.5.6.1 martin UNUSED_P(pubid);
665 1.1.1.5.6.1 martin UNUSED_P(has_internal_subset);
666 1.1 tron ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
667 1.1 tron metaLocation(parser);
668 1.1 tron fputts(T("/>\n"), fp);
669 1.1 tron }
670 1.1 tron
671 1.1 tron static void XMLCALL
672 1.1.1.5.6.1 martin metaEndDoctypeDecl(void *userData) {
673 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
674 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
675 1.1.1.5.6.1 martin FILE *fp = data->fp;
676 1.1 tron fputts(T("<enddoctype"), fp);
677 1.1 tron metaLocation(parser);
678 1.1 tron fputts(T("/>\n"), fp);
679 1.1 tron }
680 1.1 tron
681 1.1 tron static void XMLCALL
682 1.1.1.5.6.1 martin metaNotationDecl(void *userData, const XML_Char *notationName,
683 1.1.1.5.6.1 martin const XML_Char *base, const XML_Char *systemId,
684 1.1.1.5.6.1 martin const XML_Char *publicId) {
685 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
686 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
687 1.1.1.5.6.1 martin FILE *fp = data->fp;
688 1.1.1.5.6.1 martin UNUSED_P(base);
689 1.1 tron ftprintf(fp, T("<notation name=\"%s\""), notationName);
690 1.1 tron if (publicId)
691 1.1 tron ftprintf(fp, T(" public=\"%s\""), publicId);
692 1.1 tron if (systemId) {
693 1.1 tron fputts(T(" system=\""), fp);
694 1.1.1.5.6.1 martin characterData(data, systemId, (int)tcslen(systemId));
695 1.1 tron puttc(T('"'), fp);
696 1.1 tron }
697 1.1 tron metaLocation(parser);
698 1.1 tron fputts(T("/>\n"), fp);
699 1.1 tron }
700 1.1 tron
701 1.1 tron static void XMLCALL
702 1.1.1.5.6.1 martin metaEntityDecl(void *userData, const XML_Char *entityName, int is_param,
703 1.1.1.5.6.1 martin const XML_Char *value, int value_length, const XML_Char *base,
704 1.1.1.5.6.1 martin const XML_Char *systemId, const XML_Char *publicId,
705 1.1.1.5.6.1 martin const XML_Char *notationName) {
706 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
707 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
708 1.1.1.5.6.1 martin FILE *fp = data->fp;
709 1.1 tron
710 1.1.1.5.6.1 martin UNUSED_P(is_param);
711 1.1.1.5.6.1 martin UNUSED_P(base);
712 1.1 tron if (value) {
713 1.1 tron ftprintf(fp, T("<entity name=\"%s\""), entityName);
714 1.1 tron metaLocation(parser);
715 1.1 tron puttc(T('>'), fp);
716 1.1.1.5.6.1 martin characterData(data, value, value_length);
717 1.1 tron fputts(T("</entity/>\n"), fp);
718 1.1.1.5.6.1 martin } else if (notationName) {
719 1.1 tron ftprintf(fp, T("<entity name=\"%s\""), entityName);
720 1.1 tron if (publicId)
721 1.1 tron ftprintf(fp, T(" public=\"%s\""), publicId);
722 1.1 tron fputts(T(" system=\""), fp);
723 1.1.1.5.6.1 martin characterData(data, systemId, (int)tcslen(systemId));
724 1.1 tron puttc(T('"'), fp);
725 1.1 tron ftprintf(fp, T(" notation=\"%s\""), notationName);
726 1.1 tron metaLocation(parser);
727 1.1 tron fputts(T("/>\n"), fp);
728 1.1.1.5.6.1 martin } else {
729 1.1 tron ftprintf(fp, T("<entity name=\"%s\""), entityName);
730 1.1 tron if (publicId)
731 1.1 tron ftprintf(fp, T(" public=\"%s\""), publicId);
732 1.1 tron fputts(T(" system=\""), fp);
733 1.1.1.5.6.1 martin characterData(data, systemId, (int)tcslen(systemId));
734 1.1 tron puttc(T('"'), fp);
735 1.1 tron metaLocation(parser);
736 1.1 tron fputts(T("/>\n"), fp);
737 1.1 tron }
738 1.1 tron }
739 1.1 tron
740 1.1 tron static void XMLCALL
741 1.1.1.5.6.1 martin metaStartNamespaceDecl(void *userData, const XML_Char *prefix,
742 1.1.1.5.6.1 martin const XML_Char *uri) {
743 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
744 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
745 1.1.1.5.6.1 martin FILE *fp = data->fp;
746 1.1 tron fputts(T("<startns"), fp);
747 1.1 tron if (prefix)
748 1.1 tron ftprintf(fp, T(" prefix=\"%s\""), prefix);
749 1.1 tron if (uri) {
750 1.1 tron fputts(T(" ns=\""), fp);
751 1.1.1.5.6.1 martin characterData(data, uri, (int)tcslen(uri));
752 1.1 tron fputts(T("\"/>\n"), fp);
753 1.1.1.5.6.1 martin } else
754 1.1 tron fputts(T("/>\n"), fp);
755 1.1 tron }
756 1.1 tron
757 1.1 tron static void XMLCALL
758 1.1.1.5.6.1 martin metaEndNamespaceDecl(void *userData, const XML_Char *prefix) {
759 1.1.1.5.6.1 martin XML_Parser parser = (XML_Parser)userData;
760 1.1.1.5.6.1 martin XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
761 1.1.1.5.6.1 martin FILE *fp = data->fp;
762 1.1.1.5.6.1 martin if (! prefix)
763 1.1 tron fputts(T("<endns/>\n"), fp);
764 1.1 tron else
765 1.1 tron ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
766 1.1 tron }
767 1.1 tron
768 1.1 tron static int XMLCALL
769 1.1.1.5.6.1 martin unknownEncodingConvert(void *data, const char *p) {
770 1.1 tron return codepageConvert(*(int *)data, p);
771 1.1 tron }
772 1.1 tron
773 1.1 tron static int XMLCALL
774 1.1.1.5.6.1 martin unknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info) {
775 1.1 tron int cp;
776 1.1 tron static const XML_Char prefixL[] = T("windows-");
777 1.1 tron static const XML_Char prefixU[] = T("WINDOWS-");
778 1.1 tron int i;
779 1.1 tron
780 1.1.1.5.6.1 martin UNUSED_P(userData);
781 1.1 tron for (i = 0; prefixU[i]; i++)
782 1.1 tron if (name[i] != prefixU[i] && name[i] != prefixL[i])
783 1.1 tron return 0;
784 1.1.1.5.6.1 martin
785 1.1 tron cp = 0;
786 1.1 tron for (; name[i]; i++) {
787 1.1 tron static const XML_Char digits[] = T("0123456789");
788 1.1 tron const XML_Char *s = tcschr(digits, name[i]);
789 1.1.1.5.6.1 martin if (! s)
790 1.1 tron return 0;
791 1.1 tron cp *= 10;
792 1.1 tron cp += (int)(s - digits);
793 1.1 tron if (cp >= 0x10000)
794 1.1 tron return 0;
795 1.1 tron }
796 1.1.1.5.6.1 martin if (! codepageMap(cp, info->map))
797 1.1 tron return 0;
798 1.1 tron info->convert = unknownEncodingConvert;
799 1.1 tron /* We could just cast the code page integer to a void *,
800 1.1 tron and avoid the use of release. */
801 1.1 tron info->release = free;
802 1.1 tron info->data = malloc(sizeof(int));
803 1.1.1.5.6.1 martin if (! info->data)
804 1.1 tron return 0;
805 1.1 tron *(int *)info->data = cp;
806 1.1 tron return 1;
807 1.1 tron }
808 1.1 tron
809 1.1 tron static int XMLCALL
810 1.1.1.5.6.1 martin notStandalone(void *userData) {
811 1.1.1.5.6.1 martin UNUSED_P(userData);
812 1.1 tron return 0;
813 1.1 tron }
814 1.1 tron
815 1.1 tron static void
816 1.1.1.5.6.1 martin showVersion(XML_Char *prog) {
817 1.1 tron XML_Char *s = prog;
818 1.1 tron XML_Char ch;
819 1.1 tron const XML_Feature *features = XML_GetFeatureList();
820 1.1 tron while ((ch = *s) != 0) {
821 1.1 tron if (ch == '/'
822 1.1.1.5 christos #if defined(_WIN32)
823 1.1 tron || ch == '\\'
824 1.1 tron #endif
825 1.1.1.5.6.1 martin )
826 1.1 tron prog = s + 1;
827 1.1 tron ++s;
828 1.1 tron }
829 1.1 tron ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
830 1.1 tron if (features != NULL && features[0].feature != XML_FEATURE_END) {
831 1.1 tron int i = 1;
832 1.1 tron ftprintf(stdout, T("%s"), features[0].name);
833 1.1 tron if (features[0].value)
834 1.1 tron ftprintf(stdout, T("=%ld"), features[0].value);
835 1.1 tron while (features[i].feature != XML_FEATURE_END) {
836 1.1 tron ftprintf(stdout, T(", %s"), features[i].name);
837 1.1 tron if (features[i].value)
838 1.1 tron ftprintf(stdout, T("=%ld"), features[i].value);
839 1.1 tron ++i;
840 1.1 tron }
841 1.1 tron ftprintf(stdout, T("\n"));
842 1.1 tron }
843 1.1 tron }
844 1.1 tron
845 1.1 tron static void
846 1.1.1.5.6.1 martin usage(const XML_Char *prog, int rc) {
847 1.1.1.5.6.1 martin ftprintf(
848 1.1.1.5.6.1 martin stderr,
849 1.1.1.5.6.1 martin /* Generated with:
850 1.1.1.5.6.1 martin * $ xmlwf/xmlwf_helpgen.sh
851 1.1.1.5.6.1 martin */
852 1.1.1.5.6.1 martin /* clang-format off */
853 1.1.1.5.6.1 martin T("usage: %s [-s] [-n] [-p] [-x] [-e ENCODING] [-w] [-r] [-d DIRECTORY]\n")
854 1.1.1.5.6.1 martin T(" [-c | -m | -t] [-N]\n")
855 1.1.1.5.6.1 martin T(" [FILE [FILE ...]]\n")
856 1.1.1.5.6.1 martin T("\n")
857 1.1.1.5.6.1 martin T("xmlwf - Determines if an XML document is well-formed\n")
858 1.1.1.5.6.1 martin T("\n")
859 1.1.1.5.6.1 martin T("positional arguments:\n")
860 1.1.1.5.6.1 martin T(" FILE files to process (default: STDIN)\n")
861 1.1.1.5.6.1 martin T("\n")
862 1.1.1.5.6.1 martin T("input control arguments:\n")
863 1.1.1.5.6.1 martin T(" -s print an error if the document is not [s]tandalone\n")
864 1.1.1.5.6.1 martin T(" -n enable [n]amespace processing\n")
865 1.1.1.5.6.1 martin T(" -p enable processing external DTDs and [p]arameter entities\n")
866 1.1.1.5.6.1 martin T(" -x enable processing of e[x]ternal entities\n")
867 1.1.1.5.6.1 martin T(" -e ENCODING override any in-document [e]ncoding declaration\n")
868 1.1.1.5.6.1 martin T(" -w enable support for [W]indows code pages\n")
869 1.1.1.5.6.1 martin T(" -r disable memory-mapping and use normal file [r]ead IO calls instead\n")
870 1.1.1.5.6.1 martin T("\n")
871 1.1.1.5.6.1 martin T("output control arguments:\n")
872 1.1.1.5.6.1 martin T(" -d DIRECTORY output [d]estination directory\n")
873 1.1.1.5.6.1 martin T(" -c write a [c]opy of input XML, not canonical XML\n")
874 1.1.1.5.6.1 martin T(" -m write [m]eta XML, not canonical XML\n")
875 1.1.1.5.6.1 martin T(" -t write no XML output for [t]iming of plain parsing\n")
876 1.1.1.5.6.1 martin T(" -N enable adding doctype and [n]otation declarations\n")
877 1.1.1.5.6.1 martin T("\n")
878 1.1.1.5.6.1 martin T("info arguments:\n")
879 1.1.1.5.6.1 martin T(" -h show this [h]elp message and exit\n")
880 1.1.1.5.6.1 martin T(" -v show program's [v]ersion number and exit\n")
881 1.1.1.5.6.1 martin T("\n")
882 1.1.1.5.6.1 martin T("libexpat is software libre, licensed under the MIT license.\n")
883 1.1.1.5.6.1 martin T("Please report bugs at https://github.com/libexpat/libexpat/issues. Thank you!\n")
884 1.1.1.5.6.1 martin , /* clang-format on */
885 1.1.1.5.6.1 martin prog);
886 1.1 tron exit(rc);
887 1.1 tron }
888 1.1 tron
889 1.1.1.5.6.1 martin #if defined(__MINGW32__) && defined(XML_UNICODE)
890 1.1.1.5.6.1 martin /* Silence warning about missing prototype */
891 1.1.1.5.6.1 martin int wmain(int argc, XML_Char **argv);
892 1.1.1.5.6.1 martin #endif
893 1.1.1.5.6.1 martin
894 1.1 tron int
895 1.1.1.5.6.1 martin tmain(int argc, XML_Char **argv) {
896 1.1 tron int i, j;
897 1.1 tron const XML_Char *outputDir = NULL;
898 1.1 tron const XML_Char *encoding = NULL;
899 1.1 tron unsigned processFlags = XML_MAP_FILE;
900 1.1 tron int windowsCodePages = 0;
901 1.1 tron int outputType = 0;
902 1.1 tron int useNamespaces = 0;
903 1.1 tron int requireStandalone = 0;
904 1.1.1.5.6.1 martin int requiresNotations = 0;
905 1.1.1.5.6.1 martin enum XML_ParamEntityParsing paramEntityParsing
906 1.1.1.5.6.1 martin = XML_PARAM_ENTITY_PARSING_NEVER;
907 1.1 tron int useStdin = 0;
908 1.1.1.5.6.1 martin XmlwfUserData userData = {NULL, NULL, NULL};
909 1.1 tron
910 1.1 tron #ifdef _MSC_VER
911 1.1.1.5.6.1 martin _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
912 1.1 tron #endif
913 1.1 tron
914 1.1 tron i = 1;
915 1.1 tron j = 0;
916 1.1 tron while (i < argc) {
917 1.1 tron if (j == 0) {
918 1.1 tron if (argv[i][0] != T('-'))
919 1.1 tron break;
920 1.1 tron if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
921 1.1 tron i++;
922 1.1 tron break;
923 1.1 tron }
924 1.1 tron j++;
925 1.1 tron }
926 1.1 tron switch (argv[i][j]) {
927 1.1 tron case T('r'):
928 1.1 tron processFlags &= ~XML_MAP_FILE;
929 1.1 tron j++;
930 1.1 tron break;
931 1.1 tron case T('s'):
932 1.1 tron requireStandalone = 1;
933 1.1 tron j++;
934 1.1 tron break;
935 1.1 tron case T('n'):
936 1.1 tron useNamespaces = 1;
937 1.1 tron j++;
938 1.1 tron break;
939 1.1 tron case T('p'):
940 1.1 tron paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
941 1.1 tron /* fall through */
942 1.1 tron case T('x'):
943 1.1 tron processFlags |= XML_EXTERNAL_ENTITIES;
944 1.1 tron j++;
945 1.1 tron break;
946 1.1 tron case T('w'):
947 1.1 tron windowsCodePages = 1;
948 1.1 tron j++;
949 1.1 tron break;
950 1.1 tron case T('m'):
951 1.1 tron outputType = 'm';
952 1.1 tron j++;
953 1.1 tron break;
954 1.1 tron case T('c'):
955 1.1 tron outputType = 'c';
956 1.1 tron useNamespaces = 0;
957 1.1 tron j++;
958 1.1 tron break;
959 1.1 tron case T('t'):
960 1.1 tron outputType = 't';
961 1.1 tron j++;
962 1.1 tron break;
963 1.1.1.5.6.1 martin case T('N'):
964 1.1.1.5.6.1 martin requiresNotations = 1;
965 1.1.1.5.6.1 martin j++;
966 1.1.1.5.6.1 martin break;
967 1.1 tron case T('d'):
968 1.1 tron if (argv[i][j + 1] == T('\0')) {
969 1.1 tron if (++i == argc)
970 1.1 tron usage(argv[0], 2);
971 1.1 tron outputDir = argv[i];
972 1.1.1.5.6.1 martin } else
973 1.1 tron outputDir = argv[i] + j + 1;
974 1.1 tron i++;
975 1.1 tron j = 0;
976 1.1 tron break;
977 1.1 tron case T('e'):
978 1.1 tron if (argv[i][j + 1] == T('\0')) {
979 1.1 tron if (++i == argc)
980 1.1 tron usage(argv[0], 2);
981 1.1 tron encoding = argv[i];
982 1.1.1.5.6.1 martin } else
983 1.1 tron encoding = argv[i] + j + 1;
984 1.1 tron i++;
985 1.1 tron j = 0;
986 1.1 tron break;
987 1.1 tron case T('h'):
988 1.1 tron usage(argv[0], 0);
989 1.1 tron return 0;
990 1.1 tron case T('v'):
991 1.1 tron showVersion(argv[0]);
992 1.1 tron return 0;
993 1.1 tron case T('\0'):
994 1.1 tron if (j > 1) {
995 1.1 tron i++;
996 1.1 tron j = 0;
997 1.1 tron break;
998 1.1 tron }
999 1.1 tron /* fall through */
1000 1.1 tron default:
1001 1.1 tron usage(argv[0], 2);
1002 1.1 tron }
1003 1.1 tron }
1004 1.1 tron if (i == argc) {
1005 1.1 tron useStdin = 1;
1006 1.1 tron processFlags &= ~XML_MAP_FILE;
1007 1.1 tron i--;
1008 1.1 tron }
1009 1.1 tron for (; i < argc; i++) {
1010 1.1 tron XML_Char *outName = 0;
1011 1.1 tron int result;
1012 1.1 tron XML_Parser parser;
1013 1.1 tron if (useNamespaces)
1014 1.1 tron parser = XML_ParserCreateNS(encoding, NSSEP);
1015 1.1 tron else
1016 1.1 tron parser = XML_ParserCreate(encoding);
1017 1.1.1.4 spz
1018 1.1.1.4 spz if (! parser) {
1019 1.1.1.5.6.1 martin tperror(T("Could not instantiate parser"));
1020 1.1.1.4 spz exit(1);
1021 1.1.1.4 spz }
1022 1.1.1.4 spz
1023 1.1 tron if (requireStandalone)
1024 1.1 tron XML_SetNotStandaloneHandler(parser, notStandalone);
1025 1.1 tron XML_SetParamEntityParsing(parser, paramEntityParsing);
1026 1.1 tron if (outputType == 't') {
1027 1.1 tron /* This is for doing timings; this gives a more realistic estimate of
1028 1.1 tron the parsing time. */
1029 1.1 tron outputDir = 0;
1030 1.1 tron XML_SetElementHandler(parser, nopStartElement, nopEndElement);
1031 1.1 tron XML_SetCharacterDataHandler(parser, nopCharacterData);
1032 1.1 tron XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
1033 1.1.1.5.6.1 martin } else if (outputDir) {
1034 1.1.1.5.6.1 martin const XML_Char *delim = T("/");
1035 1.1 tron const XML_Char *file = useStdin ? T("STDIN") : argv[i];
1036 1.1.1.5.6.1 martin if (! useStdin) {
1037 1.1 tron /* Jump after last (back)slash */
1038 1.1.1.5.6.1 martin const XML_Char *lastDelim = tcsrchr(file, delim[0]);
1039 1.1 tron if (lastDelim)
1040 1.1 tron file = lastDelim + 1;
1041 1.1.1.5 christos #if defined(_WIN32)
1042 1.1 tron else {
1043 1.1.1.5.6.1 martin const XML_Char *winDelim = T("\\");
1044 1.1 tron lastDelim = tcsrchr(file, winDelim[0]);
1045 1.1 tron if (lastDelim) {
1046 1.1 tron file = lastDelim + 1;
1047 1.1 tron delim = winDelim;
1048 1.1 tron }
1049 1.1 tron }
1050 1.1 tron #endif
1051 1.1 tron }
1052 1.1 tron outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
1053 1.1.1.5.6.1 martin * sizeof(XML_Char));
1054 1.1 tron tcscpy(outName, outputDir);
1055 1.1 tron tcscat(outName, delim);
1056 1.1 tron tcscat(outName, file);
1057 1.1.1.5.6.1 martin userData.fp = tfopen(outName, T("wb"));
1058 1.1.1.5.6.1 martin if (! userData.fp) {
1059 1.1 tron tperror(outName);
1060 1.1 tron exit(1);
1061 1.1 tron }
1062 1.1.1.5.6.1 martin setvbuf(userData.fp, NULL, _IOFBF, 16384);
1063 1.1 tron #ifdef XML_UNICODE
1064 1.1.1.5.6.1 martin puttc(0xFEFF, userData.fp);
1065 1.1 tron #endif
1066 1.1.1.5.6.1 martin XML_SetUserData(parser, &userData);
1067 1.1 tron switch (outputType) {
1068 1.1 tron case 'm':
1069 1.1 tron XML_UseParserAsHandlerArg(parser);
1070 1.1 tron XML_SetElementHandler(parser, metaStartElement, metaEndElement);
1071 1.1 tron XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
1072 1.1 tron XML_SetCommentHandler(parser, metaComment);
1073 1.1 tron XML_SetCdataSectionHandler(parser, metaStartCdataSection,
1074 1.1 tron metaEndCdataSection);
1075 1.1 tron XML_SetCharacterDataHandler(parser, metaCharacterData);
1076 1.1 tron XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
1077 1.1 tron metaEndDoctypeDecl);
1078 1.1 tron XML_SetEntityDeclHandler(parser, metaEntityDecl);
1079 1.1 tron XML_SetNotationDeclHandler(parser, metaNotationDecl);
1080 1.1 tron XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
1081 1.1 tron metaEndNamespaceDecl);
1082 1.1 tron metaStartDocument(parser);
1083 1.1 tron break;
1084 1.1 tron case 'c':
1085 1.1 tron XML_UseParserAsHandlerArg(parser);
1086 1.1 tron XML_SetDefaultHandler(parser, markup);
1087 1.1 tron XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
1088 1.1 tron XML_SetCharacterDataHandler(parser, defaultCharacterData);
1089 1.1 tron XML_SetProcessingInstructionHandler(parser,
1090 1.1 tron defaultProcessingInstruction);
1091 1.1 tron break;
1092 1.1 tron default:
1093 1.1 tron if (useNamespaces)
1094 1.1 tron XML_SetElementHandler(parser, startElementNS, endElementNS);
1095 1.1 tron else
1096 1.1 tron XML_SetElementHandler(parser, startElement, endElement);
1097 1.1 tron XML_SetCharacterDataHandler(parser, characterData);
1098 1.1 tron #ifndef W3C14N
1099 1.1 tron XML_SetProcessingInstructionHandler(parser, processingInstruction);
1100 1.1.1.5.6.1 martin if (requiresNotations) {
1101 1.1.1.5.6.1 martin XML_SetDoctypeDeclHandler(parser, startDoctypeDecl, endDoctypeDecl);
1102 1.1.1.5.6.1 martin XML_SetNotationDeclHandler(parser, notationDecl);
1103 1.1.1.5.6.1 martin }
1104 1.1 tron #endif /* not W3C14N */
1105 1.1 tron break;
1106 1.1 tron }
1107 1.1 tron }
1108 1.1 tron if (windowsCodePages)
1109 1.1 tron XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
1110 1.1 tron result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
1111 1.1 tron if (outputDir) {
1112 1.1 tron if (outputType == 'm')
1113 1.1 tron metaEndDocument(parser);
1114 1.1.1.5.6.1 martin fclose(userData.fp);
1115 1.1.1.5.6.1 martin if (! result) {
1116 1.1 tron tremove(outName);
1117 1.1.1.2 spz }
1118 1.1 tron free(outName);
1119 1.1 tron }
1120 1.1 tron XML_ParserFree(parser);
1121 1.1.1.5.6.1 martin if (! result) {
1122 1.1.1.5.6.1 martin exit(2);
1123 1.1.1.5.6.1 martin }
1124 1.1 tron }
1125 1.1 tron return 0;
1126 1.1 tron }
1127