xmlwf.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
  2. See the file COPYING for copying permission.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stddef.h>
  7. #include <string.h>
  8. #include "expat.h"
  9. #include "codepage.h"
  10. #include "internal.h" /* for UNUSED_P only */
  11. #include "xmlfile.h"
  12. #include "xmltchar.h"
  13. #ifdef _MSC_VER
  14. #include <crtdbg.h>
  15. #endif
  16. /* This ensures proper sorting. */
  17. #define NSSEP T('\001')
  18. static void XMLCALL
  19. characterData(void *userData, const XML_Char *s, int len)
  20. {
  21. FILE *fp = (FILE *)userData;
  22. for (; len > 0; --len, ++s) {
  23. switch (*s) {
  24. case T('&'):
  25. fputts(T("&amp;"), fp);
  26. break;
  27. case T('<'):
  28. fputts(T("&lt;"), fp);
  29. break;
  30. case T('>'):
  31. fputts(T("&gt;"), fp);
  32. break;
  33. #ifdef W3C14N
  34. case 13:
  35. fputts(T("&#xD;"), fp);
  36. break;
  37. #else
  38. case T('"'):
  39. fputts(T("&quot;"), fp);
  40. break;
  41. case 9:
  42. case 10:
  43. case 13:
  44. ftprintf(fp, T("&#%d;"), *s);
  45. break;
  46. #endif
  47. default:
  48. puttc(*s, fp);
  49. break;
  50. }
  51. }
  52. }
  53. static void
  54. attributeValue(FILE *fp, const XML_Char *s)
  55. {
  56. puttc(T('='), fp);
  57. puttc(T('"'), fp);
  58. for (;;) {
  59. switch (*s) {
  60. case 0:
  61. case NSSEP:
  62. puttc(T('"'), fp);
  63. return;
  64. case T('&'):
  65. fputts(T("&amp;"), fp);
  66. break;
  67. case T('<'):
  68. fputts(T("&lt;"), fp);
  69. break;
  70. case T('"'):
  71. fputts(T("&quot;"), fp);
  72. break;
  73. #ifdef W3C14N
  74. case 9:
  75. fputts(T("&#x9;"), fp);
  76. break;
  77. case 10:
  78. fputts(T("&#xA;"), fp);
  79. break;
  80. case 13:
  81. fputts(T("&#xD;"), fp);
  82. break;
  83. #else
  84. case T('>'):
  85. fputts(T("&gt;"), fp);
  86. break;
  87. case 9:
  88. case 10:
  89. case 13:
  90. ftprintf(fp, T("&#%d;"), *s);
  91. break;
  92. #endif
  93. default:
  94. puttc(*s, fp);
  95. break;
  96. }
  97. s++;
  98. }
  99. }
  100. /* Lexicographically comparing UTF-8 encoded attribute values,
  101. is equivalent to lexicographically comparing based on the character number. */
  102. static int
  103. attcmp(const void *att1, const void *att2)
  104. {
  105. return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
  106. }
  107. static void XMLCALL
  108. startElement(void *userData, const XML_Char *name, const XML_Char **atts)
  109. {
  110. int nAtts;
  111. const XML_Char **p;
  112. FILE *fp = (FILE *)userData;
  113. puttc(T('<'), fp);
  114. fputts(name, fp);
  115. p = atts;
  116. while (*p)
  117. ++p;
  118. nAtts = (int)((p - atts) >> 1);
  119. if (nAtts > 1)
  120. qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
  121. while (*atts) {
  122. puttc(T(' '), fp);
  123. fputts(*atts++, fp);
  124. attributeValue(fp, *atts);
  125. atts++;
  126. }
  127. puttc(T('>'), fp);
  128. }
  129. static void XMLCALL
  130. endElement(void *userData, const XML_Char *name)
  131. {
  132. FILE *fp = (FILE *)userData;
  133. puttc(T('<'), fp);
  134. puttc(T('/'), fp);
  135. fputts(name, fp);
  136. puttc(T('>'), fp);
  137. }
  138. static int
  139. nsattcmp(const void *p1, const void *p2)
  140. {
  141. const XML_Char *att1 = *(const XML_Char **)p1;
  142. const XML_Char *att2 = *(const XML_Char **)p2;
  143. int sep1 = (tcsrchr(att1, NSSEP) != 0);
  144. int sep2 = (tcsrchr(att1, NSSEP) != 0);
  145. if (sep1 != sep2)
  146. return sep1 - sep2;
  147. return tcscmp(att1, att2);
  148. }
  149. static void XMLCALL
  150. startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
  151. {
  152. int nAtts;
  153. int nsi;
  154. const XML_Char **p;
  155. FILE *fp = (FILE *)userData;
  156. const XML_Char *sep;
  157. puttc(T('<'), fp);
  158. sep = tcsrchr(name, NSSEP);
  159. if (sep) {
  160. fputts(T("n1:"), fp);
  161. fputts(sep + 1, fp);
  162. fputts(T(" xmlns:n1"), fp);
  163. attributeValue(fp, name);
  164. nsi = 2;
  165. }
  166. else {
  167. fputts(name, fp);
  168. nsi = 1;
  169. }
  170. p = atts;
  171. while (*p)
  172. ++p;
  173. nAtts = (int)((p - atts) >> 1);
  174. if (nAtts > 1)
  175. qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
  176. while (*atts) {
  177. name = *atts++;
  178. sep = tcsrchr(name, NSSEP);
  179. puttc(T(' '), fp);
  180. if (sep) {
  181. ftprintf(fp, T("n%d:"), nsi);
  182. fputts(sep + 1, fp);
  183. }
  184. else
  185. fputts(name, fp);
  186. attributeValue(fp, *atts);
  187. if (sep) {
  188. ftprintf(fp, T(" xmlns:n%d"), nsi++);
  189. attributeValue(fp, name);
  190. }
  191. atts++;
  192. }
  193. puttc(T('>'), fp);
  194. }
  195. static void XMLCALL
  196. endElementNS(void *userData, const XML_Char *name)
  197. {
  198. FILE *fp = (FILE *)userData;
  199. const XML_Char *sep;
  200. puttc(T('<'), fp);
  201. puttc(T('/'), fp);
  202. sep = tcsrchr(name, NSSEP);
  203. if (sep) {
  204. fputts(T("n1:"), fp);
  205. fputts(sep + 1, fp);
  206. }
  207. else
  208. fputts(name, fp);
  209. puttc(T('>'), fp);
  210. }
  211. #ifndef W3C14N
  212. static void XMLCALL
  213. processingInstruction(void *userData, const XML_Char *target,
  214. const XML_Char *data)
  215. {
  216. FILE *fp = (FILE *)userData;
  217. puttc(T('<'), fp);
  218. puttc(T('?'), fp);
  219. fputts(target, fp);
  220. puttc(T(' '), fp);
  221. fputts(data, fp);
  222. puttc(T('?'), fp);
  223. puttc(T('>'), fp);
  224. }
  225. #endif /* not W3C14N */
  226. static void XMLCALL
  227. defaultCharacterData(void *userData, const XML_Char *UNUSED_P(s), int UNUSED_P(len))
  228. {
  229. XML_DefaultCurrent((XML_Parser) userData);
  230. }
  231. static void XMLCALL
  232. defaultStartElement(void *userData, const XML_Char *UNUSED_P(name),
  233. const XML_Char **UNUSED_P(atts))
  234. {
  235. XML_DefaultCurrent((XML_Parser) userData);
  236. }
  237. static void XMLCALL
  238. defaultEndElement(void *userData, const XML_Char *UNUSED_P(name))
  239. {
  240. XML_DefaultCurrent((XML_Parser) userData);
  241. }
  242. static void XMLCALL
  243. defaultProcessingInstruction(void *userData, const XML_Char *UNUSED_P(target),
  244. const XML_Char *UNUSED_P(data))
  245. {
  246. XML_DefaultCurrent((XML_Parser) userData);
  247. }
  248. static void XMLCALL
  249. nopCharacterData(void *UNUSED_P(userData), const XML_Char *UNUSED_P(s), int UNUSED_P(len))
  250. {
  251. }
  252. static void XMLCALL
  253. nopStartElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts))
  254. {
  255. }
  256. static void XMLCALL
  257. nopEndElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name))
  258. {
  259. }
  260. static void XMLCALL
  261. nopProcessingInstruction(void *UNUSED_P(userData), const XML_Char *UNUSED_P(target),
  262. const XML_Char *UNUSED_P(data))
  263. {
  264. }
  265. static void XMLCALL
  266. markup(void *userData, const XML_Char *s, int len)
  267. {
  268. FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData);
  269. for (; len > 0; --len, ++s)
  270. puttc(*s, fp);
  271. }
  272. static void
  273. metaLocation(XML_Parser parser)
  274. {
  275. const XML_Char *uri = XML_GetBase(parser);
  276. if (uri)
  277. ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri);
  278. ftprintf((FILE *)XML_GetUserData(parser),
  279. T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \
  280. line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""),
  281. XML_GetCurrentByteIndex(parser),
  282. XML_GetCurrentByteCount(parser),
  283. XML_GetCurrentLineNumber(parser),
  284. XML_GetCurrentColumnNumber(parser));
  285. }
  286. static void
  287. metaStartDocument(void *userData)
  288. {
  289. fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
  290. }
  291. static void
  292. metaEndDocument(void *userData)
  293. {
  294. fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
  295. }
  296. static void XMLCALL
  297. metaStartElement(void *userData, const XML_Char *name,
  298. const XML_Char **atts)
  299. {
  300. XML_Parser parser = (XML_Parser) userData;
  301. FILE *fp = (FILE *)XML_GetUserData(parser);
  302. const XML_Char **specifiedAttsEnd
  303. = atts + XML_GetSpecifiedAttributeCount(parser);
  304. const XML_Char **idAttPtr;
  305. int idAttIndex = XML_GetIdAttributeIndex(parser);
  306. if (idAttIndex < 0)
  307. idAttPtr = 0;
  308. else
  309. idAttPtr = atts + idAttIndex;
  310. ftprintf(fp, T("<starttag name=\"%s\""), name);
  311. metaLocation(parser);
  312. if (*atts) {
  313. fputts(T(">\n"), fp);
  314. do {
  315. ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
  316. characterData(fp, atts[1], (int)tcslen(atts[1]));
  317. if (atts >= specifiedAttsEnd)
  318. fputts(T("\" defaulted=\"yes\"/>\n"), fp);
  319. else if (atts == idAttPtr)
  320. fputts(T("\" id=\"yes\"/>\n"), fp);
  321. else
  322. fputts(T("\"/>\n"), fp);
  323. } while (*(atts += 2));
  324. fputts(T("</starttag>\n"), fp);
  325. }
  326. else
  327. fputts(T("/>\n"), fp);
  328. }
  329. static void XMLCALL
  330. metaEndElement(void *userData, const XML_Char *name)
  331. {
  332. XML_Parser parser = (XML_Parser) userData;
  333. FILE *fp = (FILE *)XML_GetUserData(parser);
  334. ftprintf(fp, T("<endtag name=\"%s\""), name);
  335. metaLocation(parser);
  336. fputts(T("/>\n"), fp);
  337. }
  338. static void XMLCALL
  339. metaProcessingInstruction(void *userData, const XML_Char *target,
  340. const XML_Char *data)
  341. {
  342. XML_Parser parser = (XML_Parser) userData;
  343. FILE *fp = (FILE *)XML_GetUserData(parser);
  344. ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
  345. characterData(fp, data, (int)tcslen(data));
  346. puttc(T('"'), fp);
  347. metaLocation(parser);
  348. fputts(T("/>\n"), fp);
  349. }
  350. static void XMLCALL
  351. metaComment(void *userData, const XML_Char *data)
  352. {
  353. XML_Parser parser = (XML_Parser) userData;
  354. FILE *fp = (FILE *)XML_GetUserData(parser);
  355. fputts(T("<comment data=\""), fp);
  356. characterData(fp, data, (int)tcslen(data));
  357. puttc(T('"'), fp);
  358. metaLocation(parser);
  359. fputts(T("/>\n"), fp);
  360. }
  361. static void XMLCALL
  362. metaStartCdataSection(void *userData)
  363. {
  364. XML_Parser parser = (XML_Parser) userData;
  365. FILE *fp = (FILE *)XML_GetUserData(parser);
  366. fputts(T("<startcdata"), fp);
  367. metaLocation(parser);
  368. fputts(T("/>\n"), fp);
  369. }
  370. static void XMLCALL
  371. metaEndCdataSection(void *userData)
  372. {
  373. XML_Parser parser = (XML_Parser) userData;
  374. FILE *fp = (FILE *)XML_GetUserData(parser);
  375. fputts(T("<endcdata"), fp);
  376. metaLocation(parser);
  377. fputts(T("/>\n"), fp);
  378. }
  379. static void XMLCALL
  380. metaCharacterData(void *userData, const XML_Char *s, int len)
  381. {
  382. XML_Parser parser = (XML_Parser) userData;
  383. FILE *fp = (FILE *)XML_GetUserData(parser);
  384. fputts(T("<chars str=\""), fp);
  385. characterData(fp, s, len);
  386. puttc(T('"'), fp);
  387. metaLocation(parser);
  388. fputts(T("/>\n"), fp);
  389. }
  390. static void XMLCALL
  391. metaStartDoctypeDecl(void *userData,
  392. const XML_Char *doctypeName,
  393. const XML_Char *UNUSED_P(sysid),
  394. const XML_Char *UNUSED_P(pubid),
  395. int UNUSED_P(has_internal_subset))
  396. {
  397. XML_Parser parser = (XML_Parser) userData;
  398. FILE *fp = (FILE *)XML_GetUserData(parser);
  399. ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
  400. metaLocation(parser);
  401. fputts(T("/>\n"), fp);
  402. }
  403. static void XMLCALL
  404. metaEndDoctypeDecl(void *userData)
  405. {
  406. XML_Parser parser = (XML_Parser) userData;
  407. FILE *fp = (FILE *)XML_GetUserData(parser);
  408. fputts(T("<enddoctype"), fp);
  409. metaLocation(parser);
  410. fputts(T("/>\n"), fp);
  411. }
  412. static void XMLCALL
  413. metaNotationDecl(void *userData,
  414. const XML_Char *notationName,
  415. const XML_Char *UNUSED_P(base),
  416. const XML_Char *systemId,
  417. const XML_Char *publicId)
  418. {
  419. XML_Parser parser = (XML_Parser) userData;
  420. FILE *fp = (FILE *)XML_GetUserData(parser);
  421. ftprintf(fp, T("<notation name=\"%s\""), notationName);
  422. if (publicId)
  423. ftprintf(fp, T(" public=\"%s\""), publicId);
  424. if (systemId) {
  425. fputts(T(" system=\""), fp);
  426. characterData(fp, systemId, (int)tcslen(systemId));
  427. puttc(T('"'), fp);
  428. }
  429. metaLocation(parser);
  430. fputts(T("/>\n"), fp);
  431. }
  432. static void XMLCALL
  433. metaEntityDecl(void *userData,
  434. const XML_Char *entityName,
  435. int UNUSED_P(is_param),
  436. const XML_Char *value,
  437. int value_length,
  438. const XML_Char *UNUSED_P(base),
  439. const XML_Char *systemId,
  440. const XML_Char *publicId,
  441. const XML_Char *notationName)
  442. {
  443. XML_Parser parser = (XML_Parser) userData;
  444. FILE *fp = (FILE *)XML_GetUserData(parser);
  445. if (value) {
  446. ftprintf(fp, T("<entity name=\"%s\""), entityName);
  447. metaLocation(parser);
  448. puttc(T('>'), fp);
  449. characterData(fp, value, value_length);
  450. fputts(T("</entity/>\n"), fp);
  451. }
  452. else if (notationName) {
  453. ftprintf(fp, T("<entity name=\"%s\""), entityName);
  454. if (publicId)
  455. ftprintf(fp, T(" public=\"%s\""), publicId);
  456. fputts(T(" system=\""), fp);
  457. characterData(fp, systemId, (int)tcslen(systemId));
  458. puttc(T('"'), fp);
  459. ftprintf(fp, T(" notation=\"%s\""), notationName);
  460. metaLocation(parser);
  461. fputts(T("/>\n"), fp);
  462. }
  463. else {
  464. ftprintf(fp, T("<entity name=\"%s\""), entityName);
  465. if (publicId)
  466. ftprintf(fp, T(" public=\"%s\""), publicId);
  467. fputts(T(" system=\""), fp);
  468. characterData(fp, systemId, (int)tcslen(systemId));
  469. puttc(T('"'), fp);
  470. metaLocation(parser);
  471. fputts(T("/>\n"), fp);
  472. }
  473. }
  474. static void XMLCALL
  475. metaStartNamespaceDecl(void *userData,
  476. const XML_Char *prefix,
  477. const XML_Char *uri)
  478. {
  479. XML_Parser parser = (XML_Parser) userData;
  480. FILE *fp = (FILE *)XML_GetUserData(parser);
  481. fputts(T("<startns"), fp);
  482. if (prefix)
  483. ftprintf(fp, T(" prefix=\"%s\""), prefix);
  484. if (uri) {
  485. fputts(T(" ns=\""), fp);
  486. characterData(fp, uri, (int)tcslen(uri));
  487. fputts(T("\"/>\n"), fp);
  488. }
  489. else
  490. fputts(T("/>\n"), fp);
  491. }
  492. static void XMLCALL
  493. metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
  494. {
  495. XML_Parser parser = (XML_Parser) userData;
  496. FILE *fp = (FILE *)XML_GetUserData(parser);
  497. if (!prefix)
  498. fputts(T("<endns/>\n"), fp);
  499. else
  500. ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
  501. }
  502. static int XMLCALL
  503. unknownEncodingConvert(void *data, const char *p)
  504. {
  505. return codepageConvert(*(int *)data, p);
  506. }
  507. static int XMLCALL
  508. unknownEncoding(void *UNUSED_P(userData), const XML_Char *name, XML_Encoding *info)
  509. {
  510. int cp;
  511. static const XML_Char prefixL[] = T("windows-");
  512. static const XML_Char prefixU[] = T("WINDOWS-");
  513. int i;
  514. for (i = 0; prefixU[i]; i++)
  515. if (name[i] != prefixU[i] && name[i] != prefixL[i])
  516. return 0;
  517. cp = 0;
  518. for (; name[i]; i++) {
  519. static const XML_Char digits[] = T("0123456789");
  520. const XML_Char *s = tcschr(digits, name[i]);
  521. if (!s)
  522. return 0;
  523. cp *= 10;
  524. cp += (int)(s - digits);
  525. if (cp >= 0x10000)
  526. return 0;
  527. }
  528. if (!codepageMap(cp, info->map))
  529. return 0;
  530. info->convert = unknownEncodingConvert;
  531. /* We could just cast the code page integer to a void *,
  532. and avoid the use of release. */
  533. info->release = free;
  534. info->data = malloc(sizeof(int));
  535. if (!info->data)
  536. return 0;
  537. *(int *)info->data = cp;
  538. return 1;
  539. }
  540. static int XMLCALL
  541. notStandalone(void *UNUSED_P(userData))
  542. {
  543. return 0;
  544. }
  545. static void
  546. showVersion(XML_Char *prog)
  547. {
  548. XML_Char *s = prog;
  549. XML_Char ch;
  550. const XML_Feature *features = XML_GetFeatureList();
  551. while ((ch = *s) != 0) {
  552. if (ch == '/'
  553. #if defined(_WIN32)
  554. || ch == '\\'
  555. #endif
  556. )
  557. prog = s + 1;
  558. ++s;
  559. }
  560. ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
  561. if (features != NULL && features[0].feature != XML_FEATURE_END) {
  562. int i = 1;
  563. ftprintf(stdout, T("%s"), features[0].name);
  564. if (features[0].value)
  565. ftprintf(stdout, T("=%ld"), features[0].value);
  566. while (features[i].feature != XML_FEATURE_END) {
  567. ftprintf(stdout, T(", %s"), features[i].name);
  568. if (features[i].value)
  569. ftprintf(stdout, T("=%ld"), features[i].value);
  570. ++i;
  571. }
  572. ftprintf(stdout, T("\n"));
  573. }
  574. }
  575. static void
  576. usage(const XML_Char *prog, int rc)
  577. {
  578. ftprintf(stderr,
  579. T("usage: %s [-s] [-n] [-p] [-x] [-e encoding] [-w] [-d output-dir] [-c] [-m] [-r] [-t] [file ...]\n"), prog);
  580. exit(rc);
  581. }
  582. int
  583. tmain(int argc, XML_Char **argv)
  584. {
  585. int i, j;
  586. const XML_Char *outputDir = NULL;
  587. const XML_Char *encoding = NULL;
  588. unsigned processFlags = XML_MAP_FILE;
  589. int windowsCodePages = 0;
  590. int outputType = 0;
  591. int useNamespaces = 0;
  592. int requireStandalone = 0;
  593. enum XML_ParamEntityParsing paramEntityParsing =
  594. XML_PARAM_ENTITY_PARSING_NEVER;
  595. int useStdin = 0;
  596. #ifdef _MSC_VER
  597. _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
  598. #endif
  599. i = 1;
  600. j = 0;
  601. while (i < argc) {
  602. if (j == 0) {
  603. if (argv[i][0] != T('-'))
  604. break;
  605. if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
  606. i++;
  607. break;
  608. }
  609. j++;
  610. }
  611. switch (argv[i][j]) {
  612. case T('r'):
  613. processFlags &= ~XML_MAP_FILE;
  614. j++;
  615. break;
  616. case T('s'):
  617. requireStandalone = 1;
  618. j++;
  619. break;
  620. case T('n'):
  621. useNamespaces = 1;
  622. j++;
  623. break;
  624. case T('p'):
  625. paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
  626. /* fall through */
  627. case T('x'):
  628. processFlags |= XML_EXTERNAL_ENTITIES;
  629. j++;
  630. break;
  631. case T('w'):
  632. windowsCodePages = 1;
  633. j++;
  634. break;
  635. case T('m'):
  636. outputType = 'm';
  637. j++;
  638. break;
  639. case T('c'):
  640. outputType = 'c';
  641. useNamespaces = 0;
  642. j++;
  643. break;
  644. case T('t'):
  645. outputType = 't';
  646. j++;
  647. break;
  648. case T('d'):
  649. if (argv[i][j + 1] == T('\0')) {
  650. if (++i == argc)
  651. usage(argv[0], 2);
  652. outputDir = argv[i];
  653. }
  654. else
  655. outputDir = argv[i] + j + 1;
  656. i++;
  657. j = 0;
  658. break;
  659. case T('e'):
  660. if (argv[i][j + 1] == T('\0')) {
  661. if (++i == argc)
  662. usage(argv[0], 2);
  663. encoding = argv[i];
  664. }
  665. else
  666. encoding = argv[i] + j + 1;
  667. i++;
  668. j = 0;
  669. break;
  670. case T('h'):
  671. usage(argv[0], 0);
  672. return 0;
  673. case T('v'):
  674. showVersion(argv[0]);
  675. return 0;
  676. case T('\0'):
  677. if (j > 1) {
  678. i++;
  679. j = 0;
  680. break;
  681. }
  682. /* fall through */
  683. default:
  684. usage(argv[0], 2);
  685. }
  686. }
  687. if (i == argc) {
  688. useStdin = 1;
  689. processFlags &= ~XML_MAP_FILE;
  690. i--;
  691. }
  692. for (; i < argc; i++) {
  693. FILE *fp = 0;
  694. XML_Char *outName = 0;
  695. int result;
  696. XML_Parser parser;
  697. if (useNamespaces)
  698. parser = XML_ParserCreateNS(encoding, NSSEP);
  699. else
  700. parser = XML_ParserCreate(encoding);
  701. if (! parser) {
  702. tperror("Could not instantiate parser");
  703. exit(1);
  704. }
  705. if (requireStandalone)
  706. XML_SetNotStandaloneHandler(parser, notStandalone);
  707. XML_SetParamEntityParsing(parser, paramEntityParsing);
  708. if (outputType == 't') {
  709. /* This is for doing timings; this gives a more realistic estimate of
  710. the parsing time. */
  711. outputDir = 0;
  712. XML_SetElementHandler(parser, nopStartElement, nopEndElement);
  713. XML_SetCharacterDataHandler(parser, nopCharacterData);
  714. XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
  715. }
  716. else if (outputDir) {
  717. const XML_Char * delim = T("/");
  718. const XML_Char *file = useStdin ? T("STDIN") : argv[i];
  719. if (!useStdin) {
  720. /* Jump after last (back)slash */
  721. const XML_Char * lastDelim = tcsrchr(file, delim[0]);
  722. if (lastDelim)
  723. file = lastDelim + 1;
  724. #if defined(_WIN32)
  725. else {
  726. const XML_Char * winDelim = T("\\");
  727. lastDelim = tcsrchr(file, winDelim[0]);
  728. if (lastDelim) {
  729. file = lastDelim + 1;
  730. delim = winDelim;
  731. }
  732. }
  733. #endif
  734. }
  735. outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
  736. * sizeof(XML_Char));
  737. tcscpy(outName, outputDir);
  738. tcscat(outName, delim);
  739. tcscat(outName, file);
  740. fp = tfopen(outName, T("wb"));
  741. if (!fp) {
  742. tperror(outName);
  743. exit(1);
  744. }
  745. setvbuf(fp, NULL, _IOFBF, 16384);
  746. #ifdef XML_UNICODE
  747. puttc(0xFEFF, fp);
  748. #endif
  749. XML_SetUserData(parser, fp);
  750. switch (outputType) {
  751. case 'm':
  752. XML_UseParserAsHandlerArg(parser);
  753. XML_SetElementHandler(parser, metaStartElement, metaEndElement);
  754. XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
  755. XML_SetCommentHandler(parser, metaComment);
  756. XML_SetCdataSectionHandler(parser, metaStartCdataSection,
  757. metaEndCdataSection);
  758. XML_SetCharacterDataHandler(parser, metaCharacterData);
  759. XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
  760. metaEndDoctypeDecl);
  761. XML_SetEntityDeclHandler(parser, metaEntityDecl);
  762. XML_SetNotationDeclHandler(parser, metaNotationDecl);
  763. XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
  764. metaEndNamespaceDecl);
  765. metaStartDocument(parser);
  766. break;
  767. case 'c':
  768. XML_UseParserAsHandlerArg(parser);
  769. XML_SetDefaultHandler(parser, markup);
  770. XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
  771. XML_SetCharacterDataHandler(parser, defaultCharacterData);
  772. XML_SetProcessingInstructionHandler(parser,
  773. defaultProcessingInstruction);
  774. break;
  775. default:
  776. if (useNamespaces)
  777. XML_SetElementHandler(parser, startElementNS, endElementNS);
  778. else
  779. XML_SetElementHandler(parser, startElement, endElement);
  780. XML_SetCharacterDataHandler(parser, characterData);
  781. #ifndef W3C14N
  782. XML_SetProcessingInstructionHandler(parser, processingInstruction);
  783. #endif /* not W3C14N */
  784. break;
  785. }
  786. }
  787. if (windowsCodePages)
  788. XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
  789. result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
  790. if (outputDir) {
  791. if (outputType == 'm')
  792. metaEndDocument(parser);
  793. fclose(fp);
  794. if (!result) {
  795. tremove(outName);
  796. exit(2);
  797. }
  798. free(outName);
  799. }
  800. XML_ParserFree(parser);
  801. }
  802. return 0;
  803. }