genx.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328
  1. /*
  2. * Copyright (c) 2007-2013 Code Synthesis Tools CC.
  3. * Copyright (c) 2004 by Tim Bray and Sun Microsystems.
  4. *
  5. * For copying permission, see the accompanying COPYING file.
  6. */
  7. #define GENX_VERSION "cs-1"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <xml/details/genx/genx.h>
  12. #define Boolean int
  13. #define True 1
  14. #define False 0
  15. #define STRLEN_XMLNS_COLON 6
  16. /*******************************
  17. * writer state
  18. */
  19. typedef enum
  20. {
  21. SEQUENCE_NO_DOC,
  22. SEQUENCE_PRE_DOC,
  23. SEQUENCE_POST_DOC,
  24. SEQUENCE_START_TAG,
  25. SEQUENCE_ATTRIBUTES,
  26. SEQUENCE_START_ATTR,
  27. SEQUENCE_CONTENT
  28. } writerSequence;
  29. /*******************************
  30. * generic pointer list
  31. */
  32. typedef struct
  33. {
  34. genxWriter writer;
  35. size_t count;
  36. size_t space;
  37. void * * pointers;
  38. } plist;
  39. /*******************************
  40. * text collector, for attribute values
  41. */
  42. typedef struct
  43. {
  44. utf8 buf;
  45. size_t used;
  46. size_t space;
  47. } collector;
  48. /*******************************
  49. * Structs with opaquely-exposed handles
  50. */
  51. /*
  52. * This one's tricky, to handle stacking namespaces
  53. * 'declaration' is the current attribute which would be used to
  54. * declare the currently-effective prefix
  55. * 'defDeclaration' is a appropriate declaration when this is being
  56. * used with the default prefix as passed to genxDeclareNamespace
  57. * baroque is true if this namespace has been used with more than one
  58. * prefix, or is the default namespace but has been unset
  59. */
  60. struct genxNamespace_rec
  61. {
  62. genxWriter writer;
  63. utf8 name;
  64. size_t declCount;
  65. Boolean baroque;
  66. genxAttribute declaration;
  67. genxAttribute defaultDecl;
  68. };
  69. struct genxElement_rec
  70. {
  71. genxWriter writer;
  72. utf8 type;
  73. genxNamespace ns;
  74. };
  75. typedef enum
  76. {
  77. ATTR_NSDECL,
  78. ATTR_NAKED,
  79. ATTR_PREFIXED
  80. } attrType;
  81. struct genxAttribute_rec
  82. {
  83. genxWriter writer;
  84. utf8 name;
  85. genxNamespace ns;
  86. collector value;
  87. int provided; /* provided for current element? */
  88. attrType atype;
  89. genxAttribute next; /* Attribute order chain if not canonical. */
  90. };
  91. /*******************************
  92. * genx's sandbox
  93. */
  94. struct genxWriter_rec
  95. {
  96. genxSender * sender;
  97. genxStatus status;
  98. writerSequence sequence;
  99. char xmlChars[GENX_CHAR_TABLE_SIZE];
  100. void * userData;
  101. int nextPrefix;
  102. utf8 empty;
  103. Boolean defaultNsDeclared;
  104. genxAttribute xmlnsEquals;
  105. genxElement nowStarting;
  106. genxAttribute nowStartingAttr;
  107. plist namespaces;
  108. plist elements;
  109. plist attributes;
  110. plist prefixes;
  111. plist stack;
  112. struct genxAttribute_rec arec; /* Dummy attribute used for lookup. */
  113. char * etext[100];
  114. genxAlloc alloc;
  115. genxDealloc dealloc;
  116. /* Pretty-printing state */
  117. int ppIndent;
  118. int ppDepth;
  119. Boolean ppSimple;
  120. /* Canonicalization. */
  121. Boolean canonical;
  122. /* Attrbute order when not canonical. */
  123. genxAttribute firstAttribute;
  124. genxAttribute lastAttribute;
  125. };
  126. /*******************************
  127. * Forward declarations
  128. */
  129. static genxAttribute declareAttribute(genxWriter w, genxNamespace ns,
  130. constUtf8 name, constUtf8 valuestr,
  131. genxStatus * statusP);
  132. static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix);
  133. static genxStatus unsetDefaultNamespace(genxWriter w);
  134. static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr);
  135. void genxSetCharProps(char * p);
  136. /*******************************
  137. * End of declarations
  138. */
  139. /*******************************
  140. * private memory utilities
  141. */
  142. static void * allocate(genxWriter w, size_t bytes)
  143. {
  144. if (w->alloc)
  145. return (void *) (*w->alloc)(w->userData, bytes);
  146. else
  147. return (void *) malloc(bytes);
  148. }
  149. static void deallocate(genxWriter w, void * data)
  150. {
  151. if (w->dealloc)
  152. (*w->dealloc)(w->userData, data);
  153. else if (w->alloc == NULL)
  154. free(data);
  155. }
  156. static utf8 copy(genxWriter w, constUtf8 from)
  157. {
  158. utf8 temp;
  159. if ((temp = (utf8) allocate(w, strlen((const char *) from) + 1)) == NULL)
  160. return NULL;
  161. strcpy((char *) temp, (const char *) from);
  162. return temp;
  163. }
  164. static genxStatus initCollector(genxWriter w, collector * c)
  165. {
  166. c->space = 100;
  167. if ((c->buf = (utf8) allocate(w, c->space)) == NULL)
  168. return GENX_ALLOC_FAILED;
  169. c->used = 0;
  170. return GENX_SUCCESS;
  171. }
  172. static genxStatus growCollector(genxWriter w, collector * c, size_t size)
  173. {
  174. utf8 newSpace;
  175. c->space = size * 2;
  176. if ((newSpace = (utf8) allocate(w, c->space)) == NULL)
  177. return GENX_ALLOC_FAILED;
  178. strncpy((char *) newSpace, (const char *) c->buf, c->used);
  179. newSpace[c->used] = 0;
  180. deallocate(w, c->buf);
  181. c->buf = newSpace;
  182. return GENX_SUCCESS;
  183. }
  184. static void startCollect(collector * c)
  185. {
  186. c->used = 0;
  187. }
  188. static void endCollect(collector * c)
  189. {
  190. c->buf[c->used] = 0;
  191. }
  192. static genxStatus collectString(genxWriter w, collector * c, constUtf8 string)
  193. {
  194. size_t sl = strlen((const char *) string);
  195. if (sl >= c->space)
  196. if ((w->status = growCollector(w, c, sl)) != GENX_SUCCESS)
  197. return GENX_ALLOC_FAILED;
  198. strcpy((char *) c->buf, (const char *) string);
  199. return GENX_SUCCESS;
  200. }
  201. #define collectPiece(w,c,d,size) {if (((c)->used+(size))>=(c)->space){if (((w)->status=growCollector(w,c,(c)->used+(size)))!=GENX_SUCCESS) return (w)->status;}strncpy((char *)(c)->buf+(c)->used,d,size);(c)->used+=size;}
  202. /*******************************
  203. * private list utilities
  204. */
  205. static genxStatus initPlist(genxWriter w, plist * pl)
  206. {
  207. pl->writer = w;
  208. pl->count = 0;
  209. pl->space = 10;
  210. pl->pointers = (void * *) allocate(w, pl->space * sizeof(void *));
  211. if (pl->pointers == NULL)
  212. return GENX_ALLOC_FAILED;
  213. return GENX_SUCCESS;
  214. }
  215. /*
  216. * make room in a plist
  217. */
  218. static Boolean checkExpand(plist * pl)
  219. {
  220. void * * newlist;
  221. size_t i;
  222. if (pl->count < pl->space)
  223. return True;
  224. pl->space *= 2;
  225. newlist = (void * *) allocate(pl->writer, pl->space * sizeof(void *));
  226. if (newlist == NULL)
  227. return False;
  228. for (i = 0; i < pl->count; i++)
  229. newlist[i] = pl->pointers[i];
  230. deallocate(pl->writer, pl->pointers);
  231. pl->pointers = newlist;
  232. return True;
  233. }
  234. /*
  235. * stick something on the end of a plist
  236. */
  237. static genxStatus listAppend(plist * pl, void * pointer)
  238. {
  239. if (!checkExpand(pl))
  240. return GENX_ALLOC_FAILED;
  241. pl->pointers[pl->count++] = pointer;
  242. return GENX_SUCCESS;
  243. }
  244. /*
  245. * insert in place, shuffling up
  246. */
  247. static genxStatus listInsert(plist * pl, void * pointer, size_t at)
  248. {
  249. size_t i;
  250. if (!checkExpand(pl))
  251. return GENX_ALLOC_FAILED;
  252. for (i = pl->count; i > at; i--)
  253. pl->pointers[i] = pl->pointers[i - 1];
  254. pl->count++;
  255. pl->pointers[at] = pointer;
  256. return GENX_SUCCESS;
  257. }
  258. /*******************************
  259. * list lookups
  260. */
  261. static genxNamespace findNamespace(plist * pl, constUtf8 uri)
  262. {
  263. size_t i;
  264. genxNamespace * nn = (genxNamespace *) pl->pointers;
  265. for (i = 0; i < pl->count; i++)
  266. if (strcmp((char *) uri, (const char *) nn[i]->name) == 0)
  267. return nn[i];
  268. return NULL;
  269. }
  270. static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 type)
  271. {
  272. size_t i;
  273. genxElement * ee = (genxElement *) pl->pointers;
  274. for (i = 0; i < pl->count; i++)
  275. {
  276. if (xmlns == NULL)
  277. {
  278. if (ee[i]->ns == NULL && strcmp((const char *) type,
  279. (const char *) ee[i]->type) == 0)
  280. return ee[i];
  281. }
  282. else
  283. {
  284. if (ee[i]->ns != NULL &&
  285. strcmp((const char *) xmlns, (const char *) ee[i]->ns->name) == 0 &&
  286. strcmp((const char *) type, (const char *) ee[i]->type) == 0)
  287. return ee[i];
  288. }
  289. }
  290. return NULL;
  291. }
  292. /*
  293. * store & intern a prefix, after giving it the
  294. * "xmlns:" prefix. Don't allow storing the same one twice unless 'force'
  295. * is set.
  296. */
  297. static utf8 storePrefix(genxWriter w, constUtf8 prefix, Boolean force)
  298. {
  299. int high, low;
  300. utf8 * pp = (utf8 *) w->prefixes.pointers;
  301. unsigned char buf[1024];
  302. if (prefix[0] == 0)
  303. prefix = (utf8) "xmlns";
  304. else
  305. {
  306. sprintf((char *) buf, "xmlns:%s", prefix);
  307. prefix = buf;
  308. }
  309. high = (int) w->prefixes.count;
  310. low = -1;
  311. while (high - low > 1)
  312. {
  313. int probe = (high + low) / 2;
  314. if (strcmp((const char *) prefix, (const char *) pp[probe]) < 0)
  315. high = probe;
  316. else
  317. low = probe;
  318. }
  319. /* already there? */
  320. if (low != -1 && strcmp((const char *) prefix, (const char *) pp[low]) == 0)
  321. {
  322. if (force)
  323. return pp[low];
  324. w->status = GENX_DUPLICATE_PREFIX;
  325. return NULL;
  326. }
  327. /* copy & insert */
  328. if ((prefix = copy(w, prefix)) == NULL)
  329. {
  330. w->status = GENX_ALLOC_FAILED;
  331. return NULL;
  332. }
  333. w->status = listInsert(&w->prefixes, (void *) prefix, (size_t) high);
  334. if (w->status != GENX_SUCCESS)
  335. return NULL;
  336. return (utf8) prefix;
  337. }
  338. /*******************************
  339. * UTF8 bit-banging
  340. */
  341. /*
  342. * Retrieve the character pointed at, and advance the pointer; return -1 on
  343. * error
  344. */
  345. int genxNextUnicodeChar(constUtf8 * sp)
  346. {
  347. utf8 s = (utf8) *sp;
  348. int c;
  349. if (*s == 0)
  350. return -1;
  351. if (*s < 0x80)
  352. c = *s++;
  353. /* all this encoding sanity-checking taken from section 3.10 of Unicode 4 */
  354. else if (*s < 0xc2)
  355. goto malformed;
  356. /* 2-byte encodings, first byte c2 .. df */
  357. else if (*s < 0xe0)
  358. {
  359. c = (*s++ & 0x1f) << 6;
  360. /*
  361. * for this common idiom, if ((c & 0xc0) != 0x80) is slightly faster
  362. * on MacOS (PPC)
  363. */
  364. if (*s < 0x80 || *s > 0xbf)
  365. goto malformed;
  366. c |= *s++ & 0x3f;
  367. }
  368. /* 3-byte encodings, first byte e0 .. ef */
  369. else if (*s < 0xf0)
  370. {
  371. int b0 = *s;
  372. c = (*s++ & 0x0f) << 12;
  373. if ((b0 == 0xe0 && (*s < 0xa0 || *s > 0xbf)) ||
  374. (b0 < 0xed && (*s < 0x80 || *s > 0xbf)) ||
  375. (b0 == 0xed && (*s < 0x80 || *s > 0x9f)) ||
  376. (b0 > 0xed && (*s < 0x80 || *s > 0xbf)))
  377. goto malformed;
  378. c |= (*s++ & 0x3f) << 6;
  379. if (*s < 0x80 || *s > 0xbf)
  380. goto malformed;
  381. c |= *s++ & 0x3f;
  382. }
  383. /* 4-byte encodings, first byte f0 .. f4 */
  384. else if (*s < 0xf5)
  385. {
  386. int b0 = *s;
  387. c = (*s++ & 0x07) << 18;
  388. if ((b0 == 0xf0 && (*s < 0x90 || *s > 0xbf)) ||
  389. (b0 < 0xf4 && (*s < 0x80 || *s > 0xbf)) ||
  390. (b0 >= 0xf4 && (*s < 0x80 || *s > 0x8f)))
  391. goto malformed;
  392. c |= (*s++ & 0x3f) << 12;
  393. if (*s < 0x80 || *s > 0xbf)
  394. goto malformed;
  395. c |= (*s++ & 0x3f) << 6;
  396. if (*s < 0x80 || *s > 0xbf)
  397. goto malformed;
  398. c |= *s++ & 0x3f;
  399. }
  400. else
  401. goto malformed;
  402. *sp = s;
  403. return c;
  404. /*
  405. * this is needed by scrubText, which wants to get the pointer moved
  406. * past the problem area.
  407. */
  408. malformed:
  409. if (*s)
  410. ++s;
  411. *sp = s;
  412. return -1;
  413. }
  414. static Boolean isXMLChar(genxWriter w, int c)
  415. {
  416. if (c < 0)
  417. return False;
  418. else if (c < GENX_CHAR_TABLE_SIZE)
  419. return (int) w->xmlChars[c];
  420. else
  421. return (c <= 0x10ffff);
  422. }
  423. static Boolean isLetter(genxWriter w, int c)
  424. {
  425. if (c < 0 || c > 0xffff)
  426. return False;
  427. else
  428. {
  429. #if GENX_CHAR_TABLE_SIZE == 0x10000
  430. return w->xmlChars[c] & GENX_LETTER;
  431. #else
  432. return c < GENX_CHAR_TABLE_SIZE ? (w->xmlChars[c] & GENX_LETTER) : True;
  433. #endif
  434. }
  435. }
  436. static Boolean isNameChar(genxWriter w, int c)
  437. {
  438. if (c < 0 || c > 0xffff)
  439. return False;
  440. else
  441. {
  442. #if GENX_CHAR_TABLE_SIZE == 0x10000
  443. return w->xmlChars[c] & GENX_NAMECHAR;
  444. #else
  445. return c < GENX_CHAR_TABLE_SIZE ? (w->xmlChars[c] & GENX_NAMECHAR) : True;
  446. #endif
  447. }
  448. }
  449. /*******************************
  450. * Constructors, setters/getters
  451. */
  452. /*
  453. * Construct a new genxWriter
  454. */
  455. genxWriter genxNew(genxAlloc alloc, genxDealloc dealloc, void * userData)
  456. {
  457. genxWriter w;
  458. genxNamespace xml;
  459. if (alloc)
  460. w = (genxWriter) (*alloc)(userData, sizeof(struct genxWriter_rec));
  461. else
  462. w = (genxWriter) malloc(sizeof(struct genxWriter_rec));
  463. if (w == NULL)
  464. return NULL;
  465. w->status = GENX_SUCCESS;
  466. w->alloc = alloc;
  467. w->dealloc = dealloc;
  468. w->userData = userData;
  469. w->sequence = SEQUENCE_NO_DOC;
  470. if (initPlist(w, &w->namespaces) != GENX_SUCCESS ||
  471. initPlist(w, &w->elements) != GENX_SUCCESS ||
  472. initPlist(w, &w->attributes) != GENX_SUCCESS ||
  473. initPlist(w, &w->prefixes) != GENX_SUCCESS ||
  474. initPlist(w, &w->stack) != GENX_SUCCESS)
  475. return NULL;
  476. if ((w->status = initCollector(w, &w->arec.value)) != GENX_SUCCESS)
  477. return NULL;
  478. if ((w->empty = copy(w, (utf8) "")) == NULL)
  479. {
  480. w->status = GENX_ALLOC_FAILED;
  481. return NULL;
  482. }
  483. w->xmlnsEquals = declareAttribute(w, NULL, (utf8) "xmlns", NULL, &w->status);
  484. if (w->xmlnsEquals == NULL || w->status != GENX_SUCCESS)
  485. return NULL;
  486. w->defaultNsDeclared = False;
  487. w->nextPrefix = 1;
  488. genxSetCharProps(w->xmlChars);
  489. w->etext[GENX_SUCCESS] = "success";
  490. w->etext[GENX_BAD_UTF8] = "invalid UTF-8";
  491. w->etext[GENX_NON_XML_CHARACTER] = "non-XML character";
  492. w->etext[GENX_BAD_NAME] = "invalid name";
  493. w->etext[GENX_ALLOC_FAILED] = "memory allocation failed";
  494. w->etext[GENX_BAD_NAMESPACE_NAME] = "invalid namespace name";
  495. w->etext[GENX_INTERNAL_ERROR] = "internal error";
  496. w->etext[GENX_DUPLICATE_PREFIX] = "duplicate prefix";
  497. w->etext[GENX_SEQUENCE_ERROR] = "call out of sequence";
  498. w->etext[GENX_NO_START_TAG] = "no start tag for end element call";
  499. w->etext[GENX_IO_ERROR] = "io error";
  500. w->etext[GENX_MISSING_VALUE] = "missing attribute value";
  501. w->etext[GENX_MALFORMED_COMMENT] = "malformed comment body";
  502. w->etext[GENX_MALFORMED_PI] = "?> in PI";
  503. w->etext[GENX_XML_PI_TARGET] = "target of PI matches [xX][mM][lL]";
  504. w->etext[GENX_DUPLICATE_ATTRIBUTE] = "duplicate attribute";
  505. w->etext[GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE] =
  506. "attribute is default namespace";
  507. w->etext[GENX_DUPLICATE_NAMESPACE] =
  508. "namespace declared twice with different prefixes";
  509. w->etext[GENX_BAD_DEFAULT_DECLARATION] =
  510. "default namespace declared on an element which is not in a namespace";
  511. /* the xml: namespace is pre-wired */
  512. xml = genxDeclareNamespace(w, (utf8) "http://www.w3.org/XML/1998/namespace",
  513. (utf8) "xml", &w->status);
  514. if (xml == NULL)
  515. return NULL;
  516. xml->declCount = 1;
  517. xml->declaration = xml->defaultDecl;
  518. w->ppIndent = 0; /* Pretty-printing is disabled by default. */
  519. w->canonical = False; /* No canonicalization by default. */
  520. w->firstAttribute = NULL;
  521. w->lastAttribute = NULL;
  522. return w;
  523. }
  524. genxStatus genxReset (genxWriter w)
  525. {
  526. size_t i;
  527. /* Clean up the stack. */
  528. w->stack.count = 0;
  529. /* Reset namespace declaration counts. The first entry is the pre-wired
  530. xml namespace. */
  531. ((genxNamespace) w->namespaces.pointers[0])->declCount = 1;
  532. for (i = 1; i < w->namespaces.count; i++)
  533. {
  534. ((genxNamespace) w->namespaces.pointers[i])->declCount = 0;
  535. ((genxNamespace) w->namespaces.pointers[i])->baroque = False;
  536. }
  537. /* Clear provided attributes. */
  538. for (i = 0; i < w->attributes.count; i++)
  539. ((genxAttribute) w->attributes.pointers[i])->provided = False;
  540. /* Clear attribute list. */
  541. if (!w->canonical)
  542. {
  543. while (w->firstAttribute != NULL)
  544. {
  545. genxAttribute t = w->firstAttribute->next;
  546. w->firstAttribute->next = NULL;
  547. w->firstAttribute = t;
  548. }
  549. w->lastAttribute = NULL;
  550. }
  551. w->status = GENX_SUCCESS;
  552. w->sequence = SEQUENCE_NO_DOC;
  553. return w->status;
  554. }
  555. /*
  556. * get/set userData
  557. */
  558. void genxSetUserData(genxWriter w, void * userData)
  559. {
  560. w->userData = userData;
  561. }
  562. void * genxGetUserData(genxWriter w)
  563. {
  564. return w->userData;
  565. }
  566. /*
  567. * get/set pretty-printing
  568. */
  569. genxStatus genxSetPrettyPrint(genxWriter w, int ind)
  570. {
  571. if (w->sequence == SEQUENCE_NO_DOC)
  572. w->ppIndent = ind;
  573. else
  574. w->status = GENX_SEQUENCE_ERROR;
  575. return w->status;
  576. }
  577. int genxGetPrettyPrint(genxWriter w)
  578. {
  579. return w->ppIndent;
  580. }
  581. /*
  582. * get/set canonicalization.
  583. */
  584. genxStatus genxSetCanonical(genxWriter w, int flag)
  585. {
  586. if (w->sequence == SEQUENCE_NO_DOC)
  587. w->canonical = flag;
  588. else
  589. w->status = GENX_SEQUENCE_ERROR;
  590. return w->status;
  591. }
  592. int genxGetCanonical(genxWriter w)
  593. {
  594. return w->canonical;
  595. }
  596. /*
  597. * get/set allocator
  598. */
  599. void genxSetAlloc(genxWriter w, genxAlloc alloc)
  600. {
  601. w->alloc = alloc;
  602. }
  603. void genxSetDealloc(genxWriter w, genxDealloc dealloc)
  604. {
  605. w->dealloc = dealloc;
  606. }
  607. genxAlloc genxGetAlloc(genxWriter w)
  608. {
  609. return w->alloc;
  610. }
  611. genxDealloc genxGetDealloc(genxWriter w)
  612. {
  613. return w->dealloc;
  614. }
  615. /*
  616. * Clean up
  617. */
  618. void genxDispose(genxWriter w)
  619. {
  620. size_t i;
  621. genxNamespace * nn = (genxNamespace *) w->namespaces.pointers;
  622. genxElement * ee = (genxElement *) w->elements.pointers;
  623. genxAttribute * aa = (genxAttribute *) w->attributes.pointers;
  624. utf8 * pp = (utf8 *) w->prefixes.pointers;
  625. for (i = 0; i < w->namespaces.count; i++)
  626. {
  627. deallocate(w, nn[i]->name);
  628. deallocate(w, nn[i]);
  629. }
  630. for (i = 0; i < w->elements.count; i++)
  631. {
  632. deallocate(w, ee[i]->type);
  633. deallocate(w, ee[i]);
  634. }
  635. for (i = 0; i < w->attributes.count; i++)
  636. {
  637. deallocate(w, aa[i]->name);
  638. deallocate(w, aa[i]->value.buf);
  639. deallocate(w, aa[i]);
  640. }
  641. for(i = 0; i < w->prefixes.count; i++)
  642. deallocate(w, pp[i]);
  643. deallocate(w, w->namespaces.pointers);
  644. deallocate(w, w->elements.pointers);
  645. deallocate(w, w->attributes.pointers);
  646. deallocate(w, w->prefixes.pointers);
  647. deallocate(w, w->stack.pointers);
  648. deallocate(w, w->arec.value.buf);
  649. deallocate(w, w->empty);
  650. /* how Oscar dealt with Igli */
  651. deallocate(w, w);
  652. }
  653. /*******************************
  654. * External utility routines
  655. */
  656. /*
  657. * scan a buffer and report problems with UTF-8 encoding or non-XML characters
  658. */
  659. genxStatus genxCheckText(genxWriter w, constUtf8 s)
  660. {
  661. while (*s)
  662. {
  663. int c = genxNextUnicodeChar(&s);
  664. if (c == -1)
  665. return GENX_BAD_UTF8;
  666. if (!isXMLChar(w, c))
  667. return GENX_NON_XML_CHARACTER;
  668. }
  669. return GENX_SUCCESS;
  670. }
  671. /*
  672. * Purify some text
  673. */
  674. int genxScrubText(genxWriter w, constUtf8 in, utf8 out)
  675. {
  676. int problems = 0;
  677. constUtf8 last = in;
  678. while (*in)
  679. {
  680. int c = genxNextUnicodeChar(&in);
  681. if (c == -1)
  682. {
  683. problems++;
  684. last = in;
  685. continue;
  686. }
  687. if (!isXMLChar(w, c))
  688. {
  689. problems++;
  690. last = in;
  691. continue;
  692. }
  693. while (last < in)
  694. *out++ = *last++;
  695. }
  696. *out = 0;
  697. return problems;
  698. }
  699. /*
  700. * check one character
  701. */
  702. int genxCharClass(genxWriter w, int c)
  703. {
  704. int ret = 0;
  705. if (isXMLChar(w, c))
  706. ret |= GENX_XML_CHAR;
  707. if (isNameChar(w, c))
  708. ret |= GENX_NAMECHAR;
  709. if (isLetter(w, c))
  710. ret |= GENX_LETTER;
  711. return ret;
  712. }
  713. static genxStatus checkNCName(genxWriter w, constUtf8 name)
  714. {
  715. int c;
  716. if (name == NULL || *name == 0)
  717. return GENX_BAD_NAME;
  718. c = genxNextUnicodeChar(&name);
  719. if (!isLetter(w, c) && c != ':' && c != '_')
  720. return GENX_BAD_NAME;
  721. while (*name)
  722. {
  723. c = genxNextUnicodeChar(&name);
  724. if (c == -1)
  725. return GENX_BAD_UTF8;
  726. if (!isNameChar(w, c))
  727. return GENX_BAD_NAME;
  728. }
  729. return GENX_SUCCESS;
  730. }
  731. char * genxGetErrorMessage(genxWriter w, genxStatus status)
  732. {
  733. return w->etext[status];
  734. }
  735. char * genxLastErrorMessage(genxWriter w)
  736. {
  737. return w->etext[w->status];
  738. }
  739. /*******************************
  740. * Declarations: namespace/element/attribute
  741. */
  742. /*
  743. * DeclareNamespace - by far the most complex routine in Genx
  744. */
  745. genxNamespace genxDeclareNamespace(genxWriter w, constUtf8 uri,
  746. constUtf8 defaultPref,
  747. genxStatus * statusP)
  748. {
  749. genxNamespace ns;
  750. genxAttribute defaultDecl;
  751. unsigned char newPrefix[100];
  752. if (uri == NULL || uri[0] == 0)
  753. {
  754. w->status = GENX_BAD_NAMESPACE_NAME;
  755. goto busted;
  756. }
  757. if ((w->status = genxCheckText(w, uri)) != GENX_SUCCESS)
  758. goto busted;
  759. /* if a prefix is provided, it has to be an NCname */
  760. if (defaultPref != NULL && defaultPref[0] != 0 &&
  761. (w->status = checkNCName(w, defaultPref)) != GENX_SUCCESS)
  762. goto busted;
  763. /* previously declared? */
  764. if ((ns = findNamespace(&w->namespaces, uri)))
  765. {
  766. /* just a lookup, really */
  767. if ((defaultPref == NULL) ||
  768. (defaultPref[0] == 0 && ns->defaultDecl == w->xmlnsEquals) ||
  769. (strcmp((const char *) ns->defaultDecl->name + STRLEN_XMLNS_COLON,
  770. (const char *) defaultPref) == 0))
  771. {
  772. w->status = *statusP = GENX_SUCCESS;
  773. return ns;
  774. }
  775. }
  776. /* wasn't already declared */
  777. else
  778. {
  779. /* make a default prefix if none provided */
  780. if (defaultPref == NULL)
  781. {
  782. sprintf((char *) newPrefix, "g%d", w->nextPrefix++);
  783. defaultPref = newPrefix;
  784. }
  785. ns = (genxNamespace) allocate(w, sizeof(struct genxNamespace_rec));
  786. if (ns == NULL)
  787. {
  788. w->status = GENX_ALLOC_FAILED;
  789. goto busted;
  790. }
  791. ns->writer = w;
  792. ns->baroque = False;
  793. if ((ns->name = copy(w, uri)) == NULL)
  794. {
  795. w->status = GENX_ALLOC_FAILED;
  796. goto busted;
  797. }
  798. if ((w->status = listAppend(&w->namespaces, ns)) != GENX_SUCCESS)
  799. goto busted;
  800. ns->defaultDecl = ns->declaration = NULL;
  801. ns->declCount = 0;
  802. }
  803. if (defaultPref[0] == 0)
  804. {
  805. if (w->defaultNsDeclared)
  806. {
  807. w->status = GENX_DUPLICATE_PREFIX;
  808. goto busted;
  809. }
  810. defaultDecl = w->xmlnsEquals;
  811. w->defaultNsDeclared = True;
  812. }
  813. else
  814. {
  815. /* this catches dupes too */
  816. if ((defaultPref = storePrefix(w, defaultPref, False)) == NULL)
  817. goto busted;
  818. defaultDecl = declareAttribute(w, NULL, defaultPref, ns->name, statusP);
  819. if (defaultDecl == NULL || *statusP != GENX_SUCCESS)
  820. {
  821. w->status = *statusP;
  822. return NULL;
  823. }
  824. }
  825. if (ns->defaultDecl != NULL && defaultDecl != ns->defaultDecl)
  826. ns->baroque = True;
  827. ns->defaultDecl = defaultDecl;
  828. *statusP = GENX_SUCCESS;
  829. return ns;
  830. busted:
  831. *statusP = w->status;
  832. return NULL;
  833. }
  834. /*
  835. * get namespace prefix
  836. */
  837. utf8 genxGetNamespacePrefix(genxNamespace ns)
  838. {
  839. if (ns->declaration == NULL)
  840. return NULL;
  841. if (ns->declaration == ns->writer->xmlnsEquals)
  842. return ns->writer->empty;
  843. return ns->declaration->name + STRLEN_XMLNS_COLON;
  844. }
  845. /*
  846. * DeclareElement - see genx.h for details
  847. */
  848. genxElement genxDeclareElement(genxWriter w,
  849. genxNamespace ns, constUtf8 type,
  850. genxStatus * statusP)
  851. {
  852. genxElement old;
  853. genxElement el;
  854. if ((w->status = checkNCName(w, type)) != GENX_SUCCESS)
  855. {
  856. *statusP = w->status;
  857. return NULL;
  858. }
  859. /* already declared? */
  860. old = findElement(&w->elements, (ns == NULL) ? NULL : ns->name, type);
  861. if (old)
  862. return old;
  863. if ((el = (genxElement) allocate(w, sizeof(struct genxElement_rec))) == NULL)
  864. {
  865. w->status = *statusP = GENX_ALLOC_FAILED;
  866. return NULL;
  867. }
  868. el->writer = w;
  869. el->ns = ns;
  870. if ((el->type = copy(w, type)) == NULL)
  871. {
  872. w->status = *statusP = GENX_ALLOC_FAILED;
  873. return NULL;
  874. }
  875. if ((w->status = listAppend(&w->elements, el)) != GENX_SUCCESS)
  876. {
  877. *statusP = w->status;
  878. return NULL;
  879. }
  880. *statusP = GENX_SUCCESS;
  881. return el;
  882. }
  883. /*
  884. * C14n ordering for attributes:
  885. * - first, namespace declarations by the prefix being declared
  886. * - second, unprefixed attributes by attr name
  887. * - third, prefixed attrs by ns uri then local part
  888. */
  889. static int orderAttributes(genxAttribute a1, genxAttribute a2)
  890. {
  891. if (a1->atype == a2->atype)
  892. {
  893. if (a1->atype == ATTR_PREFIXED && a1->ns != a2->ns)
  894. return strcmp((const char *) a1->ns->name, (const char *) a2->ns->name);
  895. else
  896. return strcmp((const char *) a1->name, (const char *) a2->name);
  897. }
  898. else if (a1->atype == ATTR_NSDECL)
  899. return -1;
  900. else if (a1->atype == ATTR_NAKED)
  901. {
  902. if (a2->atype == ATTR_NSDECL)
  903. return 1;
  904. else
  905. return -1;
  906. }
  907. else
  908. return 1;
  909. }
  910. /*
  911. * internal declare-attribute. This one allows colonized values for
  912. * names, so that you can declare xmlns:-type attributes
  913. */
  914. static genxAttribute declareAttribute(genxWriter w, genxNamespace ns,
  915. constUtf8 name, constUtf8 valuestr,
  916. genxStatus * statusP)
  917. {
  918. int high, low;
  919. genxAttribute * aa = (genxAttribute *) w->attributes.pointers;
  920. genxAttribute a;
  921. w->arec.ns = ns;
  922. w->arec.name = (utf8) name;
  923. if (ns)
  924. w->arec.atype = ATTR_PREFIXED;
  925. else if (strncmp((const char *) name, "xmlns", STRLEN_XMLNS_COLON - 1) == 0)
  926. w->arec.atype = ATTR_NSDECL;
  927. else
  928. w->arec.atype = ATTR_NAKED;
  929. if (ns && (ns->defaultDecl == w->xmlnsEquals))
  930. {
  931. w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE;
  932. goto busted;
  933. }
  934. /* attribute list has to be kept sorted per c14n rules */
  935. high = (int) w->attributes.count;
  936. low = -1;
  937. while (high - low > 1)
  938. {
  939. int probe = (high + low) / 2;
  940. if (orderAttributes(&w->arec, aa[probe]) < 0)
  941. high = probe;
  942. else
  943. low = probe;
  944. }
  945. /* if it was already there */
  946. if (low != -1 && orderAttributes(&w->arec, aa[low]) == 0)
  947. return aa[low];
  948. /* not there, build it */
  949. a = (genxAttribute) allocate(w, sizeof(struct genxAttribute_rec));
  950. if (a == NULL)
  951. {
  952. w->status = GENX_ALLOC_FAILED;
  953. goto busted;
  954. }
  955. a->writer = w;
  956. a->ns = ns;
  957. a->provided = False;
  958. a->atype = w->arec.atype;
  959. a->next = NULL;
  960. if ((a->name = copy(w, name)) == NULL)
  961. {
  962. w->status = GENX_ALLOC_FAILED;
  963. goto busted;
  964. }
  965. if ((w->status = initCollector(w, &a->value)) != GENX_SUCCESS)
  966. goto busted;
  967. if (valuestr)
  968. if ((w->status = collectString(w, &a->value, valuestr)) != GENX_SUCCESS)
  969. goto busted;
  970. w->status = listInsert(&w->attributes, a, (size_t) high);
  971. if (w->status != GENX_SUCCESS)
  972. goto busted;
  973. *statusP = GENX_SUCCESS;
  974. return a;
  975. busted:
  976. *statusP = w->status;
  977. return NULL;
  978. }
  979. /*
  980. * genxDeclareAttribute - see genx.h for details
  981. */
  982. genxAttribute genxDeclareAttribute(genxWriter w,
  983. genxNamespace ns, constUtf8 name,
  984. genxStatus * statusP)
  985. {
  986. if ((w->status = checkNCName(w, name)) != GENX_SUCCESS)
  987. {
  988. *statusP = w->status;
  989. return NULL;
  990. }
  991. return declareAttribute(w, ns, name, NULL, statusP);
  992. }
  993. /*******************************
  994. * I/O
  995. */
  996. static genxStatus sendx(genxWriter w, constUtf8 s)
  997. {
  998. if (w->sender)
  999. return (*w->sender->send)(w->userData, s);
  1000. else
  1001. return GENX_IO_ERROR;
  1002. }
  1003. static genxStatus sendxBounded(genxWriter w, constUtf8 start, constUtf8 end)
  1004. {
  1005. if (w->sender)
  1006. return (*w->sender->sendBounded)(w->userData, start, end);
  1007. else
  1008. return GENX_IO_ERROR;
  1009. }
  1010. #define SendCheck(w,s) if ((w->status=sendx(w,(constUtf8)s))!=GENX_SUCCESS) return w->status
  1011. /*******************************
  1012. * XML writing routines. The semantics of the externally-facing ones are
  1013. * written up in genx.h. Commentary here is implementation notes and
  1014. * for internal routines.
  1015. */
  1016. genxStatus genxStartDocSender(genxWriter w, genxSender * sender)
  1017. {
  1018. if (w->sequence != SEQUENCE_NO_DOC)
  1019. return w->status = GENX_SEQUENCE_ERROR;
  1020. w->sequence = SEQUENCE_PRE_DOC;
  1021. w->sender = sender;
  1022. if (w->ppIndent)
  1023. {
  1024. w->ppSimple = True;
  1025. w->ppDepth = 0;
  1026. }
  1027. return GENX_SUCCESS;
  1028. }
  1029. /*
  1030. * Output new line and indentation.
  1031. */
  1032. static genxStatus writeIndentation(genxWriter w)
  1033. {
  1034. int i, n;
  1035. SendCheck(w, "\n");
  1036. n = w->ppDepth * w->ppIndent;
  1037. for (i = 0; i < n; i++)
  1038. SendCheck(w, " ");
  1039. return w->status;
  1040. }
  1041. /*
  1042. * Output attribute.
  1043. */
  1044. static genxStatus writeAttribute(genxAttribute a)
  1045. {
  1046. genxWriter w = a->writer;
  1047. if (a->ns && a->ns->baroque && a->ns->declaration == w->xmlnsEquals)
  1048. return w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE;
  1049. SendCheck(w, " ");
  1050. if (a->ns)
  1051. {
  1052. SendCheck(w, a->ns->declaration->name + STRLEN_XMLNS_COLON);
  1053. SendCheck(w, ":");
  1054. }
  1055. SendCheck(w, a->name);
  1056. SendCheck(w, "=\"");
  1057. SendCheck(w, a->value.buf);
  1058. SendCheck(w, "\"");
  1059. return w->status;
  1060. }
  1061. /*
  1062. * Write out the attributes we've been gathering up for an element. We save
  1063. * them until we've gathered them all so they can be writen in canonical
  1064. * order.
  1065. * Also, we end the start-tag.
  1066. * The trick here is that we keep the attribute list properly sorted as
  1067. * we build it, then as each attribute is added, we fill in its value and
  1068. * mark the fact that it's been added, in the "provided" field.
  1069. */
  1070. static genxStatus writeStartTag(genxWriter w, Boolean close)
  1071. {
  1072. size_t i;
  1073. genxAttribute * aa = (genxAttribute *) w->attributes.pointers;
  1074. genxElement e = w->nowStarting;
  1075. /*
  1076. * make sure the right namespace decls are in effect;
  1077. * if they are these might create an error, so ignore it
  1078. */
  1079. if (e->ns)
  1080. addNamespace(e->ns, NULL);
  1081. else
  1082. unsetDefaultNamespace(w);
  1083. w->status = GENX_SUCCESS;
  1084. if (w->ppIndent)
  1085. {
  1086. if (w->ppDepth)
  1087. if (writeIndentation (w) != GENX_SUCCESS)
  1088. return w->status;
  1089. if (!close)
  1090. {
  1091. w->ppDepth++;
  1092. w->ppSimple = True;
  1093. }
  1094. }
  1095. SendCheck(w, "<");
  1096. if (e->ns && (e->ns->declaration != w->xmlnsEquals))
  1097. {
  1098. SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON);
  1099. SendCheck(w, ":");
  1100. }
  1101. SendCheck(w, e->type);
  1102. /* If we are canonicalizing, then write sorted attributes. Otherwise
  1103. write them in the order specified. */
  1104. if (w->canonical)
  1105. {
  1106. for (i = 0; i < w->attributes.count; i++)
  1107. {
  1108. if (aa[i]->provided)
  1109. {
  1110. if (writeAttribute (aa[i]) != GENX_SUCCESS)
  1111. return w->status;
  1112. aa[i]->provided = False;
  1113. }
  1114. }
  1115. }
  1116. else
  1117. {
  1118. /* Keep the chain consistent even if we bail out mid way because of
  1119. an error. This way we will still be able to clear it in reset().*/
  1120. while (w->firstAttribute != NULL)
  1121. {
  1122. genxAttribute t = w->firstAttribute->next;
  1123. if (writeAttribute (w->firstAttribute) != GENX_SUCCESS)
  1124. return w->status;
  1125. w->firstAttribute->provided = False;
  1126. w->firstAttribute->next = NULL;
  1127. w->firstAttribute = t;
  1128. }
  1129. w->lastAttribute = NULL;
  1130. }
  1131. if (close)
  1132. SendCheck(w, "/");
  1133. SendCheck(w, ">");
  1134. return GENX_SUCCESS;
  1135. }
  1136. /*
  1137. * internal clear-er; no sequence checking
  1138. */
  1139. static genxStatus unsetDefaultNamespace(genxWriter w)
  1140. {
  1141. int i;
  1142. Boolean found = False;
  1143. /* don't put it in if not needed */
  1144. i = (int) (w->stack.count) - 1;
  1145. while (found == False && i > 0)
  1146. {
  1147. while (w->stack.pointers[i] != NULL)
  1148. {
  1149. genxAttribute decl = (genxAttribute) w->stack.pointers[i--];
  1150. genxNamespace ns = (genxNamespace) w->stack.pointers[i--];
  1151. /* if already unset */
  1152. if (ns == NULL)
  1153. return w->status = GENX_SUCCESS;
  1154. /*
  1155. * the default namespace was declared. This namespace now
  1156. * becomes baroque
  1157. */
  1158. if (decl == w->xmlnsEquals)
  1159. {
  1160. ns->baroque = True;
  1161. found = True;
  1162. break;
  1163. }
  1164. }
  1165. i -= 2;
  1166. }
  1167. if (!found)
  1168. return GENX_SUCCESS;
  1169. /*
  1170. * push a signal on the stack
  1171. */
  1172. if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS)
  1173. return w->status;
  1174. w->status = listAppend(&w->stack, w->xmlnsEquals);
  1175. if (w->status != GENX_SUCCESS)
  1176. return w->status;
  1177. /* add the xmlns= attribute, it must be the first one */
  1178. return addAttribute(w->xmlnsEquals, w->empty);
  1179. }
  1180. /*
  1181. * clear the default namespace declaration
  1182. */
  1183. genxStatus genxUnsetDefaultNamespace(genxWriter w)
  1184. {
  1185. /* can only do this while in start-tag mode */
  1186. if (w->sequence != SEQUENCE_START_TAG)
  1187. return w->status = GENX_SEQUENCE_ERROR;
  1188. return unsetDefaultNamespace(w);
  1189. }
  1190. genxStatus genxStartElement(genxElement e)
  1191. {
  1192. genxWriter w = e->writer;
  1193. switch (w->sequence)
  1194. {
  1195. case SEQUENCE_NO_DOC:
  1196. case SEQUENCE_POST_DOC:
  1197. case SEQUENCE_START_ATTR:
  1198. return w->status = GENX_SEQUENCE_ERROR;
  1199. case SEQUENCE_START_TAG:
  1200. case SEQUENCE_ATTRIBUTES:
  1201. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1202. return w->status;
  1203. break;
  1204. case SEQUENCE_PRE_DOC:
  1205. case SEQUENCE_CONTENT:
  1206. break;
  1207. }
  1208. w->sequence = SEQUENCE_START_TAG;
  1209. /*
  1210. * push the stack. We push a NULL after a pointer to this element
  1211. * because the stack will also contain pointers to the namespace
  1212. * attributes that got declared here, so we can keep track of what's
  1213. * in effect. I.e. a single stack entry consists logically of a pointer
  1214. * to an element object, a NULL, then zero or more pairs of pointers to
  1215. * namespace objects/declarations
  1216. */
  1217. if ((w->status = listAppend(&w->stack, e)) != GENX_SUCCESS)
  1218. return w->status;
  1219. if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS)
  1220. return w->status;
  1221. w->nowStarting = e;
  1222. return GENX_SUCCESS;
  1223. }
  1224. /*
  1225. * internal namespace adder; no sequence checking
  1226. */
  1227. static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix)
  1228. {
  1229. genxWriter w = ns->writer;
  1230. genxAttribute decl;
  1231. int i;
  1232. genxElement e;
  1233. /*
  1234. * first, we'll find the declaring attribute
  1235. */
  1236. if (prefix == NULL)
  1237. decl = ns->defaultDecl;
  1238. else
  1239. {
  1240. if (prefix[0] == 0)
  1241. decl = w->xmlnsEquals;
  1242. else
  1243. {
  1244. if ((prefix = storePrefix(w, prefix, True)) == NULL)
  1245. return w->status;
  1246. decl = declareAttribute(w, NULL, prefix, ns->name, &w->status);
  1247. if (decl == NULL || w->status != GENX_SUCCESS)
  1248. return w->status;
  1249. }
  1250. }
  1251. if (decl != ns->defaultDecl)
  1252. ns->baroque = True;
  1253. /*
  1254. * avoid doing anything if this namespace is already declared. If
  1255. * they've shown good taste we can do this cheaply
  1256. */
  1257. if (!ns->baroque)
  1258. {
  1259. if (ns->declCount > 0)
  1260. return w->status = GENX_SUCCESS;
  1261. }
  1262. else
  1263. {
  1264. /*
  1265. * First, we'll run all the way up the stack to see if there is
  1266. * another declaration for this namespace/prefix in scope, in which
  1267. * case it's a no-op; or, if there's another declaration for this
  1268. * prefix on another namespace, in which case we have to over-ride
  1269. */
  1270. i = (int) (w->stack.count) - 1;
  1271. while (i > 0)
  1272. {
  1273. while (w->stack.pointers[i] != NULL)
  1274. {
  1275. genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--];
  1276. genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--];
  1277. if (ns == otherNs)
  1278. {
  1279. if (decl == otherDecl)
  1280. return w->status = GENX_SUCCESS;
  1281. else
  1282. {
  1283. i = 0;
  1284. break;
  1285. }
  1286. }
  1287. else
  1288. {
  1289. /* different namespace, same prefix? */
  1290. if (decl == otherDecl)
  1291. {
  1292. i = 0;
  1293. break;
  1294. }
  1295. }
  1296. }
  1297. i -= 2;
  1298. }
  1299. }
  1300. /*
  1301. * If this namespace is already declared on
  1302. * this element (with different prefix/decl) which is an error.
  1303. */
  1304. i = (int) (w->stack.count) - 1;
  1305. while (w->stack.pointers[i] != NULL)
  1306. {
  1307. genxNamespace otherNs;
  1308. i--; /* don't need declaration */
  1309. otherNs = (genxNamespace) w->stack.pointers[i--];
  1310. if (ns == otherNs)
  1311. return w->status = GENX_DUPLICATE_NAMESPACE;
  1312. }
  1313. /* move pointer from NULL to element */
  1314. --i;
  1315. /*
  1316. * It's also an error if this is a default-namespace declaration and the
  1317. * element is in no namespace.
  1318. */
  1319. e = (genxElement) w->stack.pointers[i];
  1320. if (e->ns == NULL && decl == w->xmlnsEquals)
  1321. return w->status = GENX_BAD_DEFAULT_DECLARATION;
  1322. if ((w->status = listAppend(&w->stack, ns)) != GENX_SUCCESS)
  1323. return w->status;
  1324. if ((w->status = listAppend(&w->stack, decl)) != GENX_SUCCESS)
  1325. return w->status;
  1326. ns->declaration = decl;
  1327. ns->declCount++;
  1328. return addAttribute(decl, ns->name);
  1329. }
  1330. /*
  1331. * Add a namespace declaration
  1332. */
  1333. genxStatus genxAddNamespace(genxNamespace ns, constUtf8 prefix)
  1334. {
  1335. if (ns->writer->sequence != SEQUENCE_START_TAG)
  1336. return ns->writer->status = GENX_SEQUENCE_ERROR;
  1337. return addNamespace(ns, prefix);
  1338. }
  1339. /*
  1340. * Private attribute-adding code
  1341. * most of the work here is normalizing the value, which is the same
  1342. * as regular normalization except for " is replaced by "&quot;"
  1343. */
  1344. static genxStatus collectAttributeValue (genxWriter w, collector* value,
  1345. constUtf8 start, constUtf8 end)
  1346. {
  1347. /* If end is NULL then the length of the value is unknown and
  1348. the value is 0-terminated. */
  1349. utf8 last = (utf8) start;
  1350. while (end != NULL ? start < end : *start)
  1351. {
  1352. int c = genxNextUnicodeChar(&start);
  1353. if (c == -1)
  1354. return w->status = GENX_BAD_UTF8;
  1355. if (!isXMLChar(w, c))
  1356. return w->status = GENX_NON_XML_CHARACTER;
  1357. switch(c)
  1358. {
  1359. case 9:
  1360. collectPiece(w, value, "&#x9;", 5);
  1361. break;
  1362. case 0xa:
  1363. collectPiece(w, value, "&#xA;", 5);
  1364. break;
  1365. case 0xd:
  1366. collectPiece(w, value, "&#xD;", 5);
  1367. break;
  1368. case '"':
  1369. collectPiece(w, value, "&quot;", 6);
  1370. break;
  1371. case '<':
  1372. collectPiece(w, value, "&lt;", 4);
  1373. break;
  1374. case '&':
  1375. collectPiece(w, value, "&amp;", 5);
  1376. break;
  1377. /*
  1378. case '>':
  1379. collectPiece(w, value, "&gt;", 4);
  1380. break;
  1381. */
  1382. default:
  1383. collectPiece(w, value, (const char *) last, start - last);
  1384. break;
  1385. }
  1386. last = (utf8) start;
  1387. }
  1388. return GENX_SUCCESS;
  1389. }
  1390. static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr)
  1391. {
  1392. genxWriter w = a->writer;
  1393. /* if valuestr not provided, this is an xmlns with a pre-cooked value */
  1394. if (valuestr)
  1395. {
  1396. startCollect(&a->value);
  1397. if (collectAttributeValue (w, &a->value, valuestr, NULL) != GENX_SUCCESS)
  1398. return w->status;
  1399. endCollect(&a->value);
  1400. }
  1401. /* now add the namespace attribute; might fail if it's been hand-declared */
  1402. if (a->ns)
  1403. addNamespace(a->ns, NULL);
  1404. if (valuestr && a->provided)
  1405. return w->status = GENX_DUPLICATE_ATTRIBUTE;
  1406. a->provided = True;
  1407. /* Add the attribute to the ordered list if not canonical. */
  1408. if (!w->canonical)
  1409. {
  1410. if (w->lastAttribute != NULL)
  1411. w->lastAttribute = w->lastAttribute->next = a;
  1412. else
  1413. w->lastAttribute = w->firstAttribute = a;
  1414. }
  1415. return GENX_SUCCESS;
  1416. }
  1417. /*
  1418. * public attribute adder.
  1419. * The only difference is that it doesn't allow a NULL value
  1420. */
  1421. genxStatus genxAddAttribute(genxAttribute a, constUtf8 valuestr)
  1422. {
  1423. if (a->writer->sequence != SEQUENCE_START_TAG &&
  1424. a->writer->sequence != SEQUENCE_ATTRIBUTES)
  1425. return a->writer->status = GENX_SEQUENCE_ERROR;
  1426. a->writer->sequence = SEQUENCE_ATTRIBUTES;
  1427. if (valuestr == NULL)
  1428. return a->writer->status = GENX_MISSING_VALUE;
  1429. return addAttribute(a, valuestr);
  1430. }
  1431. genxStatus genxStartAttribute(genxAttribute a)
  1432. {
  1433. genxWriter w = a->writer;
  1434. if (w->sequence != SEQUENCE_START_TAG &&
  1435. w->sequence != SEQUENCE_ATTRIBUTES)
  1436. return w->status = GENX_SEQUENCE_ERROR;
  1437. w->sequence = SEQUENCE_START_ATTR;
  1438. w->nowStartingAttr = a;
  1439. startCollect(&a->value);
  1440. return GENX_SUCCESS;
  1441. }
  1442. genxStatus genxEndAttribute(genxWriter w)
  1443. {
  1444. genxAttribute a;
  1445. if (w->sequence != SEQUENCE_START_ATTR)
  1446. return w->status = GENX_SEQUENCE_ERROR;
  1447. a = w->nowStartingAttr;
  1448. w->sequence = SEQUENCE_ATTRIBUTES;
  1449. endCollect(&a->value);
  1450. /* now add the namespace attribute; might fail if it's been hand-declared */
  1451. if (a->ns)
  1452. addNamespace(a->ns, NULL);
  1453. if (a->provided)
  1454. return w->status = GENX_DUPLICATE_ATTRIBUTE;
  1455. a->provided = True;
  1456. /* Add the attribute to the ordered list if not canonical. */
  1457. if (!w->canonical)
  1458. {
  1459. if (w->lastAttribute != NULL)
  1460. w->lastAttribute = w->lastAttribute->next = a;
  1461. else
  1462. w->lastAttribute = w->firstAttribute = a;
  1463. }
  1464. return GENX_SUCCESS;
  1465. }
  1466. genxStatus genxEndElement(genxWriter w)
  1467. {
  1468. int i;
  1469. Boolean close = True;
  1470. switch (w->sequence)
  1471. {
  1472. case SEQUENCE_NO_DOC:
  1473. case SEQUENCE_PRE_DOC:
  1474. case SEQUENCE_POST_DOC:
  1475. case SEQUENCE_START_ATTR:
  1476. return w->status = GENX_SEQUENCE_ERROR;
  1477. case SEQUENCE_START_TAG:
  1478. case SEQUENCE_ATTRIBUTES:
  1479. if ((w->status = writeStartTag(w, !w->canonical)) != GENX_SUCCESS)
  1480. return w->status;
  1481. close = w->canonical;
  1482. break;
  1483. case SEQUENCE_CONTENT:
  1484. break;
  1485. }
  1486. /*
  1487. * Output the closing tag.
  1488. */
  1489. if (close)
  1490. {
  1491. genxElement e;
  1492. /*
  1493. * first peek into the stack to find the right namespace declaration
  1494. * (if any) so we can properly prefix the end-tag. Have to do this
  1495. * before unwinding the stack because that might reset some xmlns
  1496. * prefixes to the context in the parent element
  1497. */
  1498. for (i = (int) (w->stack.count) - 1;
  1499. w->stack.pointers[i] != NULL;
  1500. i -= 2)
  1501. ;
  1502. e = (genxElement) w->stack.pointers[--i];
  1503. if (w->ppIndent)
  1504. {
  1505. w->ppDepth--;
  1506. if (!w->ppSimple)
  1507. if (writeIndentation (w) != GENX_SUCCESS)
  1508. return w->status;
  1509. }
  1510. SendCheck(w, "</");
  1511. if (e->ns && e->ns->declaration != w->xmlnsEquals)
  1512. {
  1513. SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON);
  1514. SendCheck(w, ":");
  1515. }
  1516. SendCheck(w, e->type);
  1517. SendCheck(w, ">");
  1518. }
  1519. if (w->ppIndent)
  1520. w->ppSimple = False;
  1521. /*
  1522. * pop zero or more namespace declarations, then a null, then the
  1523. * start-element declaration off the stack
  1524. */
  1525. w->stack.count--;
  1526. while (w->stack.pointers[w->stack.count] != NULL)
  1527. {
  1528. genxNamespace ns = (genxNamespace) w->stack.pointers[--w->stack.count];
  1529. w->stack.count--; /* don't need decl */
  1530. /* if not a fake unset-default namespace */
  1531. if (ns)
  1532. {
  1533. /*
  1534. * if they've stupidly jammed in their own namespace-prefix
  1535. * declarations, we have to go looking to see if there's another
  1536. * one in effect
  1537. */
  1538. if (ns->baroque)
  1539. {
  1540. i = (int) w->stack.count;
  1541. while (i > 0)
  1542. {
  1543. while (w->stack.pointers[i] != NULL)
  1544. {
  1545. genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--];
  1546. genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--];
  1547. if (otherNs == ns)
  1548. {
  1549. ns->declaration = otherDecl;
  1550. i = 0;
  1551. break;
  1552. }
  1553. }
  1554. /* skip NULL & element */
  1555. i -= 2;
  1556. }
  1557. }
  1558. ns->declCount--;
  1559. if (ns->declCount == 0)
  1560. ns->baroque = False;
  1561. }
  1562. }
  1563. /* pop the NULL */
  1564. if (w->stack.count == 0)
  1565. return w->status = GENX_NO_START_TAG;
  1566. --w->stack.count;
  1567. if (w->stack.count == 0)
  1568. w->sequence = SEQUENCE_POST_DOC;
  1569. else
  1570. w->sequence = SEQUENCE_CONTENT;
  1571. return GENX_SUCCESS;
  1572. }
  1573. /*
  1574. * Internal character-adder. It tries to keep the number of sendx()
  1575. * calls down by looking at each character but only doing the output
  1576. * when it has to escape something; ordinary text gets saved up in
  1577. * chunks the start of which is indicated by *breaker.
  1578. * c is the character, next points to the UTF8 representing the next
  1579. * lastsP indirectly points to the UTF8 representing the
  1580. * character, breakerP* indirectly points to the last place genx
  1581. * changed the UTF8, e.g. by escaping a '<'
  1582. */
  1583. static genxStatus addChar(genxWriter w, int c, constUtf8 next,
  1584. constUtf8 * lastsP, constUtf8 * breakerP)
  1585. {
  1586. if (c == -1)
  1587. return GENX_BAD_UTF8;
  1588. if (!isXMLChar(w, c))
  1589. return GENX_NON_XML_CHARACTER;
  1590. switch(c)
  1591. {
  1592. case 0xd:
  1593. if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
  1594. return w->status;
  1595. *breakerP = next;
  1596. sendx(w, (utf8) "&#xD;");
  1597. break;
  1598. case '<':
  1599. if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
  1600. return w->status;
  1601. *breakerP = next;
  1602. sendx(w, (utf8) "&lt;");
  1603. break;
  1604. case '&':
  1605. if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
  1606. return w->status;
  1607. *breakerP = next;
  1608. sendx(w, (utf8) "&amp;");
  1609. break;
  1610. case '>':
  1611. if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
  1612. return w->status;
  1613. *breakerP = next;
  1614. sendx(w, (utf8) "&gt;");
  1615. break;
  1616. default:
  1617. break;
  1618. }
  1619. *lastsP = next;
  1620. return GENX_SUCCESS;
  1621. }
  1622. genxStatus genxAddText(genxWriter w, constUtf8 start)
  1623. {
  1624. constUtf8 lasts = start;
  1625. constUtf8 breaker = start;
  1626. if (w->sequence == SEQUENCE_START_TAG ||
  1627. w->sequence == SEQUENCE_ATTRIBUTES)
  1628. {
  1629. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1630. return w->status;
  1631. w->sequence = SEQUENCE_CONTENT;
  1632. }
  1633. if (w->sequence == SEQUENCE_CONTENT)
  1634. {
  1635. while (*start)
  1636. {
  1637. int c = genxNextUnicodeChar(&start);
  1638. w->status = addChar(w, c, start, &lasts, &breaker);
  1639. if (w->status != GENX_SUCCESS)
  1640. return w->status;
  1641. }
  1642. return sendxBounded(w, breaker, (utf8) start);
  1643. }
  1644. else if (w->sequence == SEQUENCE_START_ATTR)
  1645. {
  1646. return collectAttributeValue (w, &w->nowStartingAttr->value, start, NULL);
  1647. }
  1648. else
  1649. return w->status = GENX_SEQUENCE_ERROR;
  1650. }
  1651. genxStatus genxAddBoundedText(genxWriter w, constUtf8 start, constUtf8 end)
  1652. {
  1653. constUtf8 lasts = start;
  1654. constUtf8 breaker = start;
  1655. if (w->sequence == SEQUENCE_START_TAG ||
  1656. w->sequence == SEQUENCE_ATTRIBUTES)
  1657. {
  1658. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1659. return w->status;
  1660. w->sequence = SEQUENCE_CONTENT;
  1661. }
  1662. if (w->sequence == SEQUENCE_CONTENT)
  1663. {
  1664. while (start < end)
  1665. {
  1666. int c = genxNextUnicodeChar(&start);
  1667. w->status = addChar(w, c, (utf8) start, &lasts, &breaker);
  1668. if (w->status != GENX_SUCCESS)
  1669. return w->status;
  1670. }
  1671. return sendxBounded(w, breaker, (utf8) start);
  1672. }
  1673. else if (w->sequence == SEQUENCE_START_ATTR)
  1674. {
  1675. return collectAttributeValue (w, &w->nowStartingAttr->value, start, end);
  1676. }
  1677. else
  1678. return w->status = GENX_SEQUENCE_ERROR;
  1679. }
  1680. genxStatus genxAddCountedText(genxWriter w, constUtf8 start, size_t byteCount)
  1681. {
  1682. utf8 end = (utf8) (start + byteCount);
  1683. return genxAddBoundedText(w, start, end);
  1684. }
  1685. genxStatus genxAddCharacter(genxWriter w, int c)
  1686. {
  1687. unsigned char cUTF8[10];
  1688. utf8 lasts, breaker, next;
  1689. if (w->sequence == SEQUENCE_START_TAG ||
  1690. w->sequence == SEQUENCE_ATTRIBUTES)
  1691. {
  1692. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1693. return w->status;
  1694. w->sequence = SEQUENCE_CONTENT;
  1695. }
  1696. if (!isXMLChar(w, c))
  1697. return w->status = GENX_NON_XML_CHARACTER;
  1698. if (w->sequence == SEQUENCE_START_ATTR)
  1699. {
  1700. int done = 1;
  1701. collector* value = &w->nowStartingAttr->value;
  1702. switch(c)
  1703. {
  1704. case 9:
  1705. collectPiece(w, value, "&#x9;", 5);
  1706. break;
  1707. case 0xa:
  1708. collectPiece(w, value, "&#xA;", 5);
  1709. break;
  1710. case 0xd:
  1711. collectPiece(w, value, "&#xD;", 5);
  1712. break;
  1713. case '"':
  1714. collectPiece(w, value, "&quot;", 6);
  1715. break;
  1716. case '<':
  1717. collectPiece(w, value, "&lt;", 4);
  1718. break;
  1719. case '&':
  1720. collectPiece(w, value, "&amp;", 5);
  1721. break;
  1722. /*
  1723. case '>':
  1724. collectPiece(w, value, "&gt;", 4);
  1725. break;
  1726. */
  1727. default:
  1728. done = 0;
  1729. break;
  1730. }
  1731. if (done)
  1732. return GENX_SUCCESS;
  1733. }
  1734. /* make UTF8 representation of character */
  1735. lasts = breaker = next = cUTF8;
  1736. if (c < 0x80)
  1737. *next++ = c;
  1738. else if (c < 0x800)
  1739. {
  1740. *next++ = 0xc0 | (c >> 6);
  1741. *next++ = 0x80 | (c & 0x3f);
  1742. }
  1743. else if (c < 0x10000)
  1744. {
  1745. *next++ = 0xe0 | (c >> 12);
  1746. *next++ = 0x80 | ((c & 0xfc0) >> 6);
  1747. *next++ = 0x80 | (c & 0x3f);
  1748. }
  1749. else
  1750. {
  1751. *next++ = 0xf0 | (c >> 18);
  1752. *next++ = 0x80 | ((c & 0x3f000) >> 12);
  1753. *next++ = 0x80 | ((c & 0xfc0) >> 6);
  1754. *next++ = 0x80 | (c & 0x3f);
  1755. }
  1756. *next = 0;
  1757. if (w->sequence == SEQUENCE_CONTENT)
  1758. {
  1759. w->status =
  1760. addChar(w, c, next, (constUtf8 *) &lasts, (constUtf8 *) &breaker);
  1761. if (w->status != GENX_SUCCESS)
  1762. return w->status;
  1763. return sendxBounded(w, breaker, next);
  1764. }
  1765. else if (w->sequence == SEQUENCE_START_ATTR)
  1766. {
  1767. collectPiece(w, &w->nowStartingAttr->value,
  1768. (const char *) cUTF8, next - cUTF8);
  1769. return GENX_SUCCESS;
  1770. }
  1771. else
  1772. return w->status = GENX_SEQUENCE_ERROR;
  1773. }
  1774. genxStatus genxEndDocument(genxWriter w)
  1775. {
  1776. if (w->sequence != SEQUENCE_POST_DOC)
  1777. return w->status = GENX_SEQUENCE_ERROR;
  1778. /* Write a newline after the closing tag. */
  1779. SendCheck (w, "\n");
  1780. if ((w->status = (*w->sender->flush)(w->userData)) != GENX_SUCCESS)
  1781. return w->status;
  1782. w->sequence = SEQUENCE_NO_DOC;
  1783. return GENX_SUCCESS;
  1784. }
  1785. genxStatus genxXmlDeclaration(genxWriter w,
  1786. constUtf8 ver,
  1787. constUtf8 enc,
  1788. constUtf8 stl)
  1789. {
  1790. if (w->sequence != SEQUENCE_PRE_DOC)
  1791. return w->status = GENX_SEQUENCE_ERROR;
  1792. if ((w->status = genxCheckText(w, ver)) != GENX_SUCCESS)
  1793. return w->status;
  1794. if (enc != NULL && (w->status = genxCheckText(w, enc)) != GENX_SUCCESS)
  1795. return w->status;
  1796. if (stl != NULL && (w->status = genxCheckText(w, stl)) != GENX_SUCCESS)
  1797. return w->status;
  1798. SendCheck (w, "<?xml version=\"");
  1799. SendCheck (w, ver);
  1800. if (enc != NULL)
  1801. {
  1802. SendCheck (w, "\" encoding=\"");
  1803. SendCheck (w, enc);
  1804. }
  1805. if (stl != NULL)
  1806. {
  1807. SendCheck (w, "\" standalone=\"");
  1808. SendCheck (w, stl);
  1809. }
  1810. SendCheck (w, "\" ?>\n");
  1811. return GENX_SUCCESS;
  1812. }
  1813. genxStatus genxComment(genxWriter w, constUtf8 text)
  1814. {
  1815. size_t i;
  1816. if (w->sequence == SEQUENCE_NO_DOC ||
  1817. w->sequence == SEQUENCE_START_ATTR)
  1818. return w->status = GENX_SEQUENCE_ERROR;
  1819. if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS)
  1820. return w->status;
  1821. /* no leading '-', no trailing '-', no '--' */
  1822. if (text[0] == '-')
  1823. return w->status = GENX_MALFORMED_COMMENT;
  1824. for (i = 0; text[i]; i++)
  1825. if (text[i] == '-' && (text[i + 1] == '-' || text[i + 1] == 0))
  1826. return w->status = GENX_MALFORMED_COMMENT;
  1827. if (w->sequence == SEQUENCE_START_TAG ||
  1828. w->sequence == SEQUENCE_ATTRIBUTES)
  1829. {
  1830. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1831. return w->status;
  1832. w->sequence = SEQUENCE_CONTENT;
  1833. }
  1834. else if (w->sequence == SEQUENCE_POST_DOC)
  1835. if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS)
  1836. return w->status;
  1837. if ((w->status = sendx(w, (utf8) "<!--")) != GENX_SUCCESS)
  1838. return w->status;
  1839. if ((w->status = sendx(w, (utf8) text)) != GENX_SUCCESS)
  1840. return w->status;
  1841. if ((w->status = sendx(w, (utf8) "-->")) != GENX_SUCCESS)
  1842. return w->status;
  1843. if (w->sequence == SEQUENCE_PRE_DOC)
  1844. if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS)
  1845. return w->status;
  1846. return GENX_SUCCESS;
  1847. }
  1848. genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text)
  1849. {
  1850. size_t i;
  1851. if (w->sequence == SEQUENCE_NO_DOC ||
  1852. w->sequence == SEQUENCE_START_ATTR)
  1853. return w->status = GENX_SEQUENCE_ERROR;
  1854. if ((w->status = genxCheckText(w, target)) != GENX_SUCCESS)
  1855. return w->status;
  1856. if ((w->status = checkNCName(w, target)) != GENX_SUCCESS)
  1857. return w->status;
  1858. if ((strlen((const char *) target) >= 3) &&
  1859. (target[0] == 'x' || target[0] == 'X') &&
  1860. (target[1] == 'm' || target[1] == 'M') &&
  1861. (target[2] == 'l' || target[2] == 'L') &&
  1862. (target[3] == 0))
  1863. return w->status = GENX_XML_PI_TARGET;
  1864. if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS)
  1865. return w->status;
  1866. /* no ?> within */
  1867. for (i = 1; text[i]; i++)
  1868. if (text[i] == '>' && text[i - 1] == '?')
  1869. return w->status = GENX_MALFORMED_PI;
  1870. if (w->sequence == SEQUENCE_START_TAG ||
  1871. w->sequence == SEQUENCE_ATTRIBUTES)
  1872. {
  1873. if ((w->status = writeStartTag(w, False)) != GENX_SUCCESS)
  1874. return w->status;
  1875. w->sequence = SEQUENCE_CONTENT;
  1876. }
  1877. else if (w->sequence == SEQUENCE_POST_DOC)
  1878. if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS)
  1879. return w->status;
  1880. if ((w->status = sendx(w, (utf8) "<?")) != GENX_SUCCESS)
  1881. return w->status;
  1882. if ((w->status = sendx(w, target)) != GENX_SUCCESS)
  1883. return w->status;
  1884. if (text[0])
  1885. {
  1886. if ((w->status = sendx(w, (utf8) " ")) != GENX_SUCCESS)
  1887. return w->status;
  1888. if ((w->status = sendx(w, text)) != GENX_SUCCESS)
  1889. return w->status;
  1890. }
  1891. if ((w->status = sendx(w, (utf8) "?>")) != GENX_SUCCESS)
  1892. return w->status;
  1893. if (w->sequence == SEQUENCE_PRE_DOC)
  1894. if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS)
  1895. return w->status;
  1896. return GENX_SUCCESS;
  1897. }
  1898. /*******************************
  1899. * Literal versions of the writing routines
  1900. */
  1901. genxStatus genxStartElementLiteral(genxWriter w,
  1902. constUtf8 xmlns, constUtf8 type)
  1903. {
  1904. genxNamespace ns = NULL;
  1905. genxElement e;
  1906. if (xmlns)
  1907. {
  1908. ns = genxDeclareNamespace(w, xmlns, NULL, &w->status);
  1909. if (ns == NULL || w->status != GENX_SUCCESS)
  1910. return w->status;
  1911. }
  1912. e = genxDeclareElement(w, ns, type, &w->status);
  1913. if (e == NULL || w->status != GENX_SUCCESS)
  1914. return w->status;
  1915. return genxStartElement(e);
  1916. }
  1917. genxStatus genxAddAttributeLiteral(genxWriter w, constUtf8 xmlns,
  1918. constUtf8 name, constUtf8 value)
  1919. {
  1920. genxNamespace ns = NULL;
  1921. genxAttribute a;
  1922. if (xmlns)
  1923. {
  1924. ns = genxDeclareNamespace(w, xmlns, NULL, &w->status);
  1925. if (ns == NULL && w->status != GENX_SUCCESS)
  1926. return w->status;
  1927. }
  1928. a = genxDeclareAttribute(w, ns, name, &w->status);
  1929. if (a == NULL || w->status != GENX_SUCCESS)
  1930. return w->status;
  1931. return genxAddAttribute(a, value);
  1932. }
  1933. genxStatus genxStartAttributeLiteral(genxWriter w,
  1934. constUtf8 xmlns, constUtf8 name)
  1935. {
  1936. genxNamespace ns = NULL;
  1937. genxAttribute a;
  1938. if (xmlns)
  1939. {
  1940. ns = genxDeclareNamespace(w, xmlns, NULL, &w->status);
  1941. if (ns == NULL && w->status != GENX_SUCCESS)
  1942. return w->status;
  1943. }
  1944. a = genxDeclareAttribute(w, ns, name, &w->status);
  1945. if (a == NULL || w->status != GENX_SUCCESS)
  1946. return w->status;
  1947. return genxStartAttribute(a);
  1948. }
  1949. genxStatus genxAddNamespaceLiteral(genxWriter w,
  1950. constUtf8 uri, constUtf8 prefix)
  1951. {
  1952. genxNamespace ns = genxDeclareNamespace(w, uri, prefix, &w->status);
  1953. if (ns == NULL && w->status != GENX_SUCCESS)
  1954. return w->status;
  1955. return genxAddNamespace(ns, NULL);
  1956. }
  1957. /*
  1958. * return version
  1959. */
  1960. char * genxGetVersion()
  1961. {
  1962. return GENX_VERSION;
  1963. }