mxml-node.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. /*
  2. * "$Id: mxml-node.c 462 2016-06-11 20:51:49Z msweet $"
  3. *
  4. * Node support code for Mini-XML, a small XML-like file parsing library.
  5. *
  6. * Copyright 2003-2016 by Michael R Sweet.
  7. *
  8. * These coded instructions, statements, and computer programs are the
  9. * property of Michael R Sweet and are protected by Federal copyright
  10. * law. Distribution and use rights are outlined in the file "COPYING"
  11. * which should have been included with this file. If this file is
  12. * missing or damaged, see the license at:
  13. *
  14. * http://www.msweet.org/projects.php/Mini-XML
  15. */
  16. /*
  17. * Include necessary headers...
  18. */
  19. #include "config.h"
  20. #include "mxml.h"
  21. /*
  22. * Local functions...
  23. */
  24. static void mxml_free(mxml_node_t *node);
  25. static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
  26. /*
  27. * 'mxmlAdd()' - Add a node to a tree.
  28. *
  29. * Adds the specified node to the parent. If the child argument is not
  30. * NULL, puts the new node before or after the specified child depending
  31. * on the value of the where argument. If the child argument is NULL,
  32. * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
  33. * or at the end of the child list (MXML_ADD_AFTER). The constant
  34. * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
  35. */
  36. void
  37. mxmlAdd(mxml_node_t *parent, /* I - Parent node */
  38. int where, /* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */
  39. mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */
  40. mxml_node_t *node) /* I - Node to add */
  41. {
  42. #ifdef DEBUG
  43. fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
  44. where, child, node);
  45. #endif /* DEBUG */
  46. /*
  47. * Range check input...
  48. */
  49. if (!parent || !node)
  50. return;
  51. #if DEBUG > 1
  52. fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
  53. if (parent)
  54. {
  55. fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child);
  56. fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child);
  57. fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev);
  58. fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next);
  59. }
  60. #endif /* DEBUG > 1 */
  61. /*
  62. * Remove the node from any existing parent...
  63. */
  64. if (node->parent)
  65. mxmlRemove(node);
  66. /*
  67. * Reset pointers...
  68. */
  69. node->parent = parent;
  70. switch (where)
  71. {
  72. case MXML_ADD_BEFORE :
  73. if (!child || child == parent->child || child->parent != parent)
  74. {
  75. /*
  76. * Insert as first node under parent...
  77. */
  78. node->next = parent->child;
  79. if (parent->child)
  80. parent->child->prev = node;
  81. else
  82. parent->last_child = node;
  83. parent->child = node;
  84. }
  85. else
  86. {
  87. /*
  88. * Insert node before this child...
  89. */
  90. node->next = child;
  91. node->prev = child->prev;
  92. if (child->prev)
  93. child->prev->next = node;
  94. else
  95. parent->child = node;
  96. child->prev = node;
  97. }
  98. break;
  99. case MXML_ADD_AFTER :
  100. if (!child || child == parent->last_child || child->parent != parent)
  101. {
  102. /*
  103. * Insert as last node under parent...
  104. */
  105. node->parent = parent;
  106. node->prev = parent->last_child;
  107. if (parent->last_child)
  108. parent->last_child->next = node;
  109. else
  110. parent->child = node;
  111. parent->last_child = node;
  112. }
  113. else
  114. {
  115. /*
  116. * Insert node after this child...
  117. */
  118. node->prev = child;
  119. node->next = child->next;
  120. if (child->next)
  121. child->next->prev = node;
  122. else
  123. parent->last_child = node;
  124. child->next = node;
  125. }
  126. break;
  127. }
  128. #if DEBUG > 1
  129. fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
  130. if (parent)
  131. {
  132. fprintf(stderr, " AFTER: parent->child=%p\n", parent->child);
  133. fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child);
  134. fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev);
  135. fprintf(stderr, " AFTER: parent->next=%p\n", parent->next);
  136. }
  137. #endif /* DEBUG > 1 */
  138. }
  139. /*
  140. * 'mxmlDelete()' - Delete a node and all of its children.
  141. *
  142. * If the specified node has a parent, this function first removes the
  143. * node from its parent using the mxmlRemove() function.
  144. */
  145. void
  146. mxmlDelete(mxml_node_t *node) /* I - Node to delete */
  147. {
  148. mxml_node_t *current, /* Current node */
  149. *next; /* Next node */
  150. #ifdef DEBUG
  151. fprintf(stderr, "mxmlDelete(node=%p)\n", node);
  152. #endif /* DEBUG */
  153. /*
  154. * Range check input...
  155. */
  156. if (!node)
  157. return;
  158. /*
  159. * Remove the node from its parent, if any...
  160. */
  161. mxmlRemove(node);
  162. /*
  163. * Delete children...
  164. */
  165. for (current = node->child; current; current = next)
  166. {
  167. /*
  168. * Get the next node...
  169. */
  170. if ((next = current->child) != NULL)
  171. {
  172. /*
  173. * Free parent nodes after child nodes have been freed...
  174. */
  175. current->child = NULL;
  176. continue;
  177. }
  178. if ((next = current->next) == NULL)
  179. {
  180. mxml_node_t *temp = current->parent;
  181. /* Pointer to parent node */
  182. if (temp == node)
  183. {
  184. /*
  185. * Got back to the top node...
  186. */
  187. next = NULL;
  188. }
  189. else if ((next = temp->next) == NULL)
  190. {
  191. if ((next = temp->parent) == node)
  192. next = NULL;
  193. }
  194. }
  195. mxml_free(current);
  196. }
  197. /*
  198. * Then free the memory used by this node...
  199. */
  200. mxml_free(node);
  201. }
  202. /*
  203. * 'mxmlGetRefCount()' - Get the current reference (use) count for a node.
  204. *
  205. * The initial reference count of new nodes is 1. Use the @link mxmlRetain@
  206. * and @link mxmlRelease@ functions to increment and decrement a node's
  207. * reference count.
  208. *
  209. * @since Mini-XML 2.7@.
  210. */
  211. int /* O - Reference count */
  212. mxmlGetRefCount(mxml_node_t *node) /* I - Node */
  213. {
  214. /*
  215. * Range check input...
  216. */
  217. if (!node)
  218. return (0);
  219. /*
  220. * Return the reference count...
  221. */
  222. return (node->ref_count);
  223. }
  224. /*
  225. * 'mxmlNewCDATA()' - Create a new CDATA node.
  226. *
  227. * The new CDATA node is added to the end of the specified parent's child
  228. * list. The constant MXML_NO_PARENT can be used to specify that the new
  229. * CDATA node has no parent. The data string must be nul-terminated and
  230. * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
  231. *
  232. * @since Mini-XML 2.3@
  233. */
  234. mxml_node_t * /* O - New node */
  235. mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  236. const char *data) /* I - Data string */
  237. {
  238. mxml_node_t *node; /* New node */
  239. #ifdef DEBUG
  240. fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
  241. parent, data ? data : "(null)");
  242. #endif /* DEBUG */
  243. /*
  244. * Range check input...
  245. */
  246. if (!data)
  247. return (NULL);
  248. /*
  249. * Create the node and set the name value...
  250. */
  251. if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
  252. node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
  253. return (node);
  254. }
  255. /*
  256. * 'mxmlNewCustom()' - Create a new custom data node.
  257. *
  258. * The new custom node is added to the end of the specified parent's child
  259. * list. The constant MXML_NO_PARENT can be used to specify that the new
  260. * element node has no parent. NULL can be passed when the data in the
  261. * node is not dynamically allocated or is separately managed.
  262. *
  263. * @since Mini-XML 2.1@
  264. */
  265. mxml_node_t * /* O - New node */
  266. mxmlNewCustom(
  267. mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  268. void *data, /* I - Pointer to data */
  269. mxml_custom_destroy_cb_t destroy) /* I - Function to destroy data */
  270. {
  271. mxml_node_t *node; /* New node */
  272. #ifdef DEBUG
  273. fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
  274. data, destroy);
  275. #endif /* DEBUG */
  276. /*
  277. * Create the node and set the value...
  278. */
  279. if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
  280. {
  281. node->value.custom.data = data;
  282. node->value.custom.destroy = destroy;
  283. }
  284. return (node);
  285. }
  286. /*
  287. * 'mxmlNewElement()' - Create a new element node.
  288. *
  289. * The new element node is added to the end of the specified parent's child
  290. * list. The constant MXML_NO_PARENT can be used to specify that the new
  291. * element node has no parent.
  292. */
  293. mxml_node_t * /* O - New node */
  294. mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  295. const char *name) /* I - Name of element */
  296. {
  297. mxml_node_t *node; /* New node */
  298. #ifdef DEBUG
  299. fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
  300. name ? name : "(null)");
  301. #endif /* DEBUG */
  302. /*
  303. * Range check input...
  304. */
  305. if (!name)
  306. return (NULL);
  307. /*
  308. * Create the node and set the element name...
  309. */
  310. if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
  311. node->value.element.name = strdup(name);
  312. return (node);
  313. }
  314. /*
  315. * 'mxmlNewInteger()' - Create a new integer node.
  316. *
  317. * The new integer node is added to the end of the specified parent's child
  318. * list. The constant MXML_NO_PARENT can be used to specify that the new
  319. * integer node has no parent.
  320. */
  321. mxml_node_t * /* O - New node */
  322. mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  323. int integer) /* I - Integer value */
  324. {
  325. mxml_node_t *node; /* New node */
  326. #ifdef DEBUG
  327. fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
  328. #endif /* DEBUG */
  329. /*
  330. * Create the node and set the element name...
  331. */
  332. if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
  333. node->value.integer = integer;
  334. return (node);
  335. }
  336. /*
  337. * 'mxmlNewOpaque()' - Create a new opaque string.
  338. *
  339. * The new opaque node is added to the end of the specified parent's child
  340. * list. The constant MXML_NO_PARENT can be used to specify that the new
  341. * opaque node has no parent. The opaque string must be nul-terminated and
  342. * is copied into the new node.
  343. */
  344. mxml_node_t * /* O - New node */
  345. mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  346. const char *opaque) /* I - Opaque string */
  347. {
  348. mxml_node_t *node; /* New node */
  349. #ifdef DEBUG
  350. fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
  351. opaque ? opaque : "(null)");
  352. #endif /* DEBUG */
  353. /*
  354. * Range check input...
  355. */
  356. if (!opaque)
  357. return (NULL);
  358. /*
  359. * Create the node and set the element name...
  360. */
  361. if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
  362. node->value.opaque = strdup(opaque);
  363. return (node);
  364. }
  365. /*
  366. * 'mxmlNewReal()' - Create a new real number node.
  367. *
  368. * The new real number node is added to the end of the specified parent's
  369. * child list. The constant MXML_NO_PARENT can be used to specify that
  370. * the new real number node has no parent.
  371. */
  372. mxml_node_t * /* O - New node */
  373. mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  374. double real) /* I - Real number value */
  375. {
  376. mxml_node_t *node; /* New node */
  377. #ifdef DEBUG
  378. fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
  379. #endif /* DEBUG */
  380. /*
  381. * Create the node and set the element name...
  382. */
  383. if ((node = mxml_new(parent, MXML_REAL)) != NULL)
  384. node->value.real = real;
  385. return (node);
  386. }
  387. /*
  388. * 'mxmlNewText()' - Create a new text fragment node.
  389. *
  390. * The new text node is added to the end of the specified parent's child
  391. * list. The constant MXML_NO_PARENT can be used to specify that the new
  392. * text node has no parent. The whitespace parameter is used to specify
  393. * whether leading whitespace is present before the node. The text
  394. * string must be nul-terminated and is copied into the new node.
  395. */
  396. mxml_node_t * /* O - New node */
  397. mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  398. int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
  399. const char *string) /* I - String */
  400. {
  401. mxml_node_t *node; /* New node */
  402. #ifdef DEBUG
  403. fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
  404. parent, whitespace, string ? string : "(null)");
  405. #endif /* DEBUG */
  406. /*
  407. * Range check input...
  408. */
  409. if (!string)
  410. return (NULL);
  411. /*
  412. * Create the node and set the text value...
  413. */
  414. if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
  415. {
  416. node->value.text.whitespace = whitespace;
  417. node->value.text.string = strdup(string);
  418. }
  419. return (node);
  420. }
  421. /*
  422. * 'mxmlNewTextf()' - Create a new formatted text fragment node.
  423. *
  424. * The new text node is added to the end of the specified parent's child
  425. * list. The constant MXML_NO_PARENT can be used to specify that the new
  426. * text node has no parent. The whitespace parameter is used to specify
  427. * whether leading whitespace is present before the node. The format
  428. * string must be nul-terminated and is formatted into the new node.
  429. */
  430. mxml_node_t * /* O - New node */
  431. mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
  432. int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
  433. const char *format, /* I - Printf-style frmat string */
  434. ...) /* I - Additional args as needed */
  435. {
  436. mxml_node_t *node; /* New node */
  437. va_list ap; /* Pointer to arguments */
  438. #ifdef DEBUG
  439. fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
  440. parent, whitespace, format ? format : "(null)");
  441. #endif /* DEBUG */
  442. /*
  443. * Range check input...
  444. */
  445. if (!format)
  446. return (NULL);
  447. /*
  448. * Create the node and set the text value...
  449. */
  450. if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
  451. {
  452. va_start(ap, format);
  453. node->value.text.whitespace = whitespace;
  454. node->value.text.string = _mxml_vstrdupf(format, ap);
  455. va_end(ap);
  456. }
  457. return (node);
  458. }
  459. /*
  460. * 'mxmlRemove()' - Remove a node from its parent.
  461. *
  462. * Does not free memory used by the node - use mxmlDelete() for that.
  463. * This function does nothing if the node has no parent.
  464. */
  465. void
  466. mxmlRemove(mxml_node_t *node) /* I - Node to remove */
  467. {
  468. #ifdef DEBUG
  469. fprintf(stderr, "mxmlRemove(node=%p)\n", node);
  470. #endif /* DEBUG */
  471. /*
  472. * Range check input...
  473. */
  474. if (!node || !node->parent)
  475. return;
  476. /*
  477. * Remove from parent...
  478. */
  479. #if DEBUG > 1
  480. fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
  481. if (node->parent)
  482. {
  483. fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child);
  484. fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
  485. }
  486. fprintf(stderr, " BEFORE: node->child=%p\n", node->child);
  487. fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child);
  488. fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev);
  489. fprintf(stderr, " BEFORE: node->next=%p\n", node->next);
  490. #endif /* DEBUG > 1 */
  491. if (node->prev)
  492. node->prev->next = node->next;
  493. else
  494. node->parent->child = node->next;
  495. if (node->next)
  496. node->next->prev = node->prev;
  497. else
  498. node->parent->last_child = node->prev;
  499. node->parent = NULL;
  500. node->prev = NULL;
  501. node->next = NULL;
  502. #if DEBUG > 1
  503. fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
  504. if (node->parent)
  505. {
  506. fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child);
  507. fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child);
  508. }
  509. fprintf(stderr, " AFTER: node->child=%p\n", node->child);
  510. fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child);
  511. fprintf(stderr, " AFTER: node->prev=%p\n", node->prev);
  512. fprintf(stderr, " AFTER: node->next=%p\n", node->next);
  513. #endif /* DEBUG > 1 */
  514. }
  515. /*
  516. * 'mxmlNewXML()' - Create a new XML document tree.
  517. *
  518. * The "version" argument specifies the version number to put in the
  519. * ?xml element node. If NULL, version 1.0 is assumed.
  520. *
  521. * @since Mini-XML 2.3@
  522. */
  523. mxml_node_t * /* O - New ?xml node */
  524. mxmlNewXML(const char *version) /* I - Version number to use */
  525. {
  526. char element[1024]; /* Element text */
  527. snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?",
  528. version ? version : "1.0");
  529. return (mxmlNewElement(NULL, element));
  530. }
  531. /*
  532. * 'mxmlRelease()' - Release a node.
  533. *
  534. * When the reference count reaches zero, the node (and any children)
  535. * is deleted via mxmlDelete().
  536. *
  537. * @since Mini-XML 2.3@
  538. */
  539. int /* O - New reference count */
  540. mxmlRelease(mxml_node_t *node) /* I - Node */
  541. {
  542. if (node)
  543. {
  544. if ((-- node->ref_count) <= 0)
  545. {
  546. mxmlDelete(node);
  547. return (0);
  548. }
  549. else
  550. return (node->ref_count);
  551. }
  552. else
  553. return (-1);
  554. }
  555. /*
  556. * 'mxmlRetain()' - Retain a node.
  557. *
  558. * @since Mini-XML 2.3@
  559. */
  560. int /* O - New reference count */
  561. mxmlRetain(mxml_node_t *node) /* I - Node */
  562. {
  563. if (node)
  564. return (++ node->ref_count);
  565. else
  566. return (-1);
  567. }
  568. /*
  569. * 'mxml_free()' - Free the memory used by a node.
  570. *
  571. * Note: Does not free child nodes, does not remove from parent.
  572. */
  573. static void
  574. mxml_free(mxml_node_t *node) /* I - Node */
  575. {
  576. int i; /* Looping var */
  577. switch (node->type)
  578. {
  579. case MXML_ELEMENT :
  580. if (node->value.element.name)
  581. free(node->value.element.name);
  582. if (node->value.element.num_attrs)
  583. {
  584. for (i = 0; i < node->value.element.num_attrs; i ++)
  585. {
  586. if (node->value.element.attrs[i].name)
  587. free(node->value.element.attrs[i].name);
  588. if (node->value.element.attrs[i].value)
  589. free(node->value.element.attrs[i].value);
  590. }
  591. free(node->value.element.attrs);
  592. }
  593. break;
  594. case MXML_INTEGER :
  595. /* Nothing to do */
  596. break;
  597. case MXML_OPAQUE :
  598. if (node->value.opaque)
  599. free(node->value.opaque);
  600. break;
  601. case MXML_REAL :
  602. /* Nothing to do */
  603. break;
  604. case MXML_TEXT :
  605. if (node->value.text.string)
  606. free(node->value.text.string);
  607. break;
  608. case MXML_CUSTOM :
  609. if (node->value.custom.data &&
  610. node->value.custom.destroy)
  611. (*(node->value.custom.destroy))(node->value.custom.data);
  612. break;
  613. default :
  614. break;
  615. }
  616. /*
  617. * Free this node...
  618. */
  619. free(node);
  620. }
  621. /*
  622. * 'mxml_new()' - Create a new node.
  623. */
  624. static mxml_node_t * /* O - New node */
  625. mxml_new(mxml_node_t *parent, /* I - Parent node */
  626. mxml_type_t type) /* I - Node type */
  627. {
  628. mxml_node_t *node; /* New node */
  629. #if DEBUG > 1
  630. fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
  631. #endif /* DEBUG > 1 */
  632. /*
  633. * Allocate memory for the node...
  634. */
  635. if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
  636. {
  637. #if DEBUG > 1
  638. fputs(" returning NULL\n", stderr);
  639. #endif /* DEBUG > 1 */
  640. return (NULL);
  641. }
  642. #if DEBUG > 1
  643. fprintf(stderr, " returning %p\n", node);
  644. #endif /* DEBUG > 1 */
  645. /*
  646. * Set the node type...
  647. */
  648. node->type = type;
  649. node->ref_count = 1;
  650. /*
  651. * Add to the parent if present...
  652. */
  653. if (parent)
  654. mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
  655. /*
  656. * Return the new node...
  657. */
  658. return (node);
  659. }
  660. /*
  661. * End of "$Id: mxml-node.c 462 2016-06-11 20:51:49Z msweet $".
  662. */