xmledit.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*====================================================================*
  2. *
  3. * xmledit.c -
  4. *
  5. * node.h
  6. *
  7. * Motley Tools by Charles Maier;
  8. * Copyright (c) 2001-2006 by Charles Maier Associates;
  9. * Licensed under the Internet Software Consortium License;
  10. *
  11. *--------------------------------------------------------------------*/
  12. #ifndef XMLEDIT_SOURCE
  13. #define XMLEDIT_SOURCE
  14. /*====================================================================*
  15. * system header files;
  16. *--------------------------------------------------------------------*/
  17. #include <stdint.h>
  18. #include <string.h>
  19. #include <limits.h>
  20. #include <ctype.h>
  21. #include <errno.h>
  22. /*====================================================================*
  23. * custom header files;
  24. *--------------------------------------------------------------------*/
  25. #include "../tools/number.h"
  26. #include "../tools/memory.h"
  27. #include "../tools/error.h"
  28. #include "../nodes/node.h"
  29. /*====================================================================*
  30. * constants;
  31. *--------------------------------------------------------------------*/
  32. #define XML_BAD_NUMBER 1
  33. #define XML_BAD_OFFSET 2
  34. #define XML_BAD_EXTENT 3
  35. /*====================================================================*
  36. * variables;
  37. *--------------------------------------------------------------------*/
  38. static char const * member = "";
  39. static char const * string = "";
  40. static unsigned offset = 0;
  41. static unsigned length = 0;
  42. static bool series = false;
  43. /*====================================================================*
  44. *
  45. * void position (size_t extent);
  46. *
  47. * sanity check offset and extent before editing memory;
  48. *
  49. * Motley Tools by Charles Maier;
  50. * Copyright (c) 2001-2006 by Charles Maier Associates;
  51. * Licensed under the Internet Software Consortium License;
  52. *
  53. *--------------------------------------------------------------------*/
  54. static void position (size_t extent)
  55. {
  56. if (!length)
  57. {
  58. error (XML_BAD_EXTENT, EPERM, "%s has no length", member);
  59. }
  60. if (offset > extent)
  61. {
  62. error (XML_BAD_OFFSET, EPERM, "%s offset of 0x%04X exceeds " DATA_OBJECT " offset of 0x%04X", member, offset, (unsigned int) extent);
  63. }
  64. if ((offset + length) > extent)
  65. {
  66. error (XML_BAD_EXTENT, EPERM, "%s length of %u bytes exceeds " DATA_OBJECT " length of " SIZE_T_SPEC " bytes", member, length, extent);
  67. }
  68. return;
  69. }
  70. /*====================================================================*
  71. *
  72. * signed xmlinteger (NODE const * node, unsigned radix);
  73. *
  74. * convert numeric string to an unsigned integer; all string digits
  75. * string digits must be valid for the specifid radix; radix can be
  76. * 1 through 16 but 2, 8, 10 and 16 are the only sensible choices;
  77. *
  78. * Motley Tools by Charles Maier;
  79. * Copyright (c) 2001-2006 by Charles Maier Associates;
  80. * Licensed under the Internet Software Consortium License;
  81. *
  82. *--------------------------------------------------------------------*/
  83. static unsigned xmlinteger (NODE const * node, unsigned radix)
  84. {
  85. unsigned digit;
  86. unsigned value = 0;
  87. while ((digit = todigit (*string)) < radix)
  88. {
  89. value *= radix;
  90. value += digit;
  91. string++;
  92. }
  93. if (*string)
  94. {
  95. error (XML_BAD_NUMBER, EPERM, "%s %s is not numeric", member, node->text);
  96. }
  97. return (value);
  98. }
  99. /*====================================================================*
  100. *
  101. * void xmlstring (void * memory, size_t extent);
  102. *
  103. * xmlstring is expressed as character text; truncate string and
  104. * pad memory with NULs as needed;
  105. *
  106. * per the schema, an series cannot have a string member;
  107. *
  108. * Motley Tools by Charles Maier;
  109. * Copyright (c) 2001-2006 by Charles Maier Associates;
  110. * Licensed under the Internet Software Consortium License;
  111. *
  112. *--------------------------------------------------------------------*/
  113. static void xmlstring (void * memory, size_t extent)
  114. {
  115. char * buffer = (char *)(memory);
  116. if (series)
  117. {
  118. error (XML_BAD_NUMBER, ENOTSUP, "%s found inside struct", member);
  119. }
  120. if (length)
  121. {
  122. while (length > 1)
  123. {
  124. if (isprint (*string))
  125. {
  126. buffer [offset] = *string++;
  127. }
  128. else
  129. {
  130. buffer [offset] = (char)(0);
  131. }
  132. offset++;
  133. length--;
  134. }
  135. buffer [offset] = (char)(0);
  136. offset++;
  137. length--;
  138. }
  139. return;
  140. }
  141. /*====================================================================*
  142. *
  143. * void xmlmemory (void * memory, size_t extent);
  144. *
  145. * xmlmemory is a hexadecimal string of variable extent; an empty
  146. * string increments offset and decrements length but nothing is
  147. * written to the memory;
  148. *
  149. * per the schema, if xmlmemory is not inside an series then it must
  150. * match the object extent;
  151. *
  152. * Motley Tools by Charles Maier;
  153. * Copyright (c) 2001-2006 by Charles Maier Associates;
  154. * Licensed under the Internet Software Consortium License;
  155. *
  156. *--------------------------------------------------------------------*/
  157. static void xmlmemory (void * memory, size_t extent)
  158. {
  159. uint8_t * buffer = (uint8_t *)(memory);
  160. if (!*string)
  161. {
  162. offset++;
  163. length--;
  164. }
  165. while ((*string) && (length))
  166. {
  167. uint8_t msb = todigit (*string++);
  168. uint8_t lsb = todigit (*string++);
  169. if ((msb > 0x0F) || (lsb > 0x0F))
  170. {
  171. error (XML_BAD_NUMBER, EINVAL, "%s value is not hexadecimal", member);
  172. }
  173. buffer [offset] = (msb << 4) + lsb;
  174. offset++;
  175. length--;
  176. }
  177. if ((length) && (!series))
  178. {
  179. error (XML_BAD_NUMBER, EINVAL, "%s value is too short", member);
  180. }
  181. if (*string)
  182. {
  183. error (XML_BAD_NUMBER, EINVAL, "%s value is too long", member);
  184. }
  185. return;
  186. }
  187. /*====================================================================*
  188. *
  189. * void xmlnumber (void * memory, size_t extent);
  190. *
  191. * xmlnumber is a decimal integer string of variable length; the
  192. * value cannot exceed length bytes and offset is incremented by
  193. * length bytes;
  194. *
  195. * Motley Tools by Charles Maier;
  196. * Copyright (c) 2001-2006 by Charles Maier Associates;
  197. * Licensed under the Internet Software Consortium License;
  198. *
  199. *--------------------------------------------------------------------*/
  200. static void xmlnumber (void * memory, size_t extent)
  201. {
  202. uint64_t number = 0;
  203. uint64_t maximum = 0;
  204. maximum = ~maximum;
  205. if (length < sizeof (number))
  206. {
  207. maximum <<= (length << 3);
  208. maximum = ~maximum;
  209. }
  210. while (isdigit (*string))
  211. {
  212. number *= 10;
  213. number += *string - '0';
  214. if (number > maximum)
  215. {
  216. error (XML_BAD_NUMBER, EINVAL, "%s value exceeds %u bytes", member, length);
  217. }
  218. string++;
  219. }
  220. if (*string)
  221. {
  222. error (XML_BAD_NUMBER, EINVAL, "%s value is not decimal", member);
  223. }
  224. memcpy ((uint8_t *)(memory) + offset, &number, length);
  225. offset += length;
  226. length -= length;
  227. return;
  228. }
  229. /*====================================================================*
  230. *
  231. * void xmlbyte (void * memory, unsigned extent);
  232. *
  233. * xmlbyte is a decimal integer string of variable extent; the
  234. * value cannot exceed 255; an empty string increments offset and
  235. * decrements length but nothing is written to the memory;
  236. *
  237. * per the schema, if xmlbyte is not inside an series then it must
  238. * it must match the object extent which must be 1 by implication;
  239. *
  240. * Motley Tools by Charles Maier;
  241. * Copyright (c) 2001-2006 by Charles Maier Associates;
  242. * Licensed under the Internet Software Consortium License;
  243. *
  244. *--------------------------------------------------------------------*/
  245. static void xmlbyte (void * memory, size_t extent)
  246. {
  247. if (*string)
  248. {
  249. uint16_t number = 0;
  250. while (isdigit (*string))
  251. {
  252. number *= 10;
  253. number += *string - '0';
  254. if (number > 0xFF)
  255. {
  256. error (XML_BAD_NUMBER, EINVAL, "%s value exceeds 8 bits", member);
  257. }
  258. string++;
  259. }
  260. if (*string)
  261. {
  262. error (XML_BAD_NUMBER, EINVAL, "%s value is not decimal", member);
  263. }
  264. memcpy ((uint8_t *)(memory) + offset, &number, sizeof (uint8_t));
  265. }
  266. offset++;
  267. length--;
  268. if ((length) && (!series))
  269. {
  270. error (XML_BAD_NUMBER, EINVAL, "%s is too short", member);
  271. }
  272. return;
  273. }
  274. /*====================================================================*
  275. *
  276. * static char const * xmlcontent1 (struct node const * node);
  277. *
  278. * Motley Tools by Charles Maier;
  279. * Copyright (c) 2001-2006 by Charles Maier Associates;
  280. * Licensed under the Internet Software Consortium License;
  281. *
  282. *--------------------------------------------------------------------*/
  283. static char const * xmlcontent1 (struct node const * node)
  284. {
  285. if (node)
  286. {
  287. node = node->below;
  288. }
  289. while (node)
  290. {
  291. if (node->type == NODE_DATA)
  292. {
  293. return (node->text);
  294. }
  295. node = node->after;
  296. }
  297. return ("");
  298. }
  299. /*====================================================================*
  300. *
  301. * char const * xmlvalue1 (struct node const * node);
  302. *
  303. * Motley Tools by Charles Maier;
  304. * Copyright (c) 2001-2006 by Charles Maier Associates;
  305. * Licensed under the Internet Software Consortium License;
  306. *
  307. *--------------------------------------------------------------------*/
  308. char const * xmlvalue1 (struct node const * node)
  309. {
  310. if (node)
  311. {
  312. node = node->below;
  313. }
  314. while (node)
  315. {
  316. if (node->type == NODE_VALU)
  317. {
  318. return (node->text);
  319. }
  320. node = node->after;
  321. }
  322. return ("");
  323. }
  324. /*====================================================================*
  325. *
  326. * static char const * xmlattribute1 (struct node const * node, char const * name);
  327. *
  328. * Motley Tools by Charles Maier;
  329. * Copyright (c) 2001-2006 by Charles Maier Associates;
  330. * Licensed under the Internet Software Consortium License;
  331. *
  332. *--------------------------------------------------------------------*/
  333. static char const * xmlattribute1 (struct node const * node, char const * name)
  334. {
  335. if (node)
  336. {
  337. node = node->below;
  338. }
  339. while (node)
  340. {
  341. if (node->type == NODE_ATTR)
  342. {
  343. if (!strcmp (node->text, name))
  344. {
  345. name = xmlvalue1 (node);
  346. return (name);
  347. }
  348. }
  349. node=node->after;
  350. }
  351. return ("");
  352. }
  353. /*====================================================================*
  354. *
  355. * signed xmledit (struct node const * node, void * memory, size_t extent);
  356. *
  357. * Motley Tools by Charles Maier;
  358. * Copyright (c) 2001-2006 by Charles Maier Associates;
  359. * Licensed under the Internet Software Consortium License;
  360. *
  361. *--------------------------------------------------------------------*/
  362. signed xmledit (struct node const * node, void * memory, size_t extent)
  363. {
  364. if (node)
  365. {
  366. node = node->below;
  367. }
  368. while (node)
  369. {
  370. if (node->type == NODE_ELEM)
  371. {
  372. if (!strcmp (node->text, DATA_MEMBER))
  373. {
  374. member = xmlattribute1 (node, DATA_NAME);
  375. offset = (unsigned)(-1);
  376. length = (unsigned)(-1);
  377. series = false;
  378. }
  379. else if (!strcmp (node->text, DATA_OFFSET))
  380. {
  381. string = xmlcontent1 (node);
  382. offset = xmlinteger (node, 16);
  383. }
  384. else if (!strcmp (node->text, DATA_LENGTH))
  385. {
  386. string = xmlcontent1 (node);
  387. length = xmlinteger (node, 10);
  388. }
  389. else if (!strcmp (node->text, DATA_STRUCT))
  390. {
  391. series = true;
  392. }
  393. else if (!strcmp (node->text, DATA_STRING))
  394. {
  395. string = xmlcontent1 (node);
  396. position (extent);
  397. xmlstring (memory, extent);
  398. }
  399. else if (!strcmp (node->text, DATA_MEMORY))
  400. {
  401. string = xmlcontent1 (node);
  402. position (extent);
  403. xmlmemory (memory, extent);
  404. }
  405. else if (!strcmp (node->text, DATA_HUGE))
  406. {
  407. length = sizeof (uint64_t);
  408. position (extent);
  409. string = xmlcontent1 (node);
  410. xmlnumber (memory, extent);
  411. }
  412. else if (!strcmp (node->text, DATA_LONG))
  413. {
  414. length = sizeof (uint32_t);
  415. position (extent);
  416. string = xmlcontent1 (node);
  417. xmlnumber (memory, extent);
  418. }
  419. else if (!strcmp (node->text, DATA_WORD))
  420. {
  421. length = sizeof (uint16_t);
  422. position (extent);
  423. string = xmlcontent1 (node);
  424. xmlnumber (memory, extent);
  425. }
  426. else if (!strcmp (node->text, DATA_BYTE))
  427. {
  428. position (extent);
  429. string = xmlcontent1 (node);
  430. xmlbyte (memory, extent);
  431. }
  432. xmledit (node, memory, extent);
  433. }
  434. node = node->after;
  435. }
  436. return (0);
  437. }
  438. /*====================================================================*
  439. *
  440. *--------------------------------------------------------------------*/
  441. #endif