PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/data.c

#
C | 481 lines | 355 code | 35 blank | 91 comment | 165 complexity | e5988abe18451e480135a6b247be6c07 MD5 | raw file
  1. /*
  2. * Copyright (C) 1989-95 GROUPE BULL
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to
  6. * deal in the Software without restriction, including without limitation the
  7. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. * sell copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  18. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. *
  21. * Except as contained in this notice, the name of GROUPE BULL shall not be
  22. * used in advertising or otherwise to promote the sale, use or other dealings
  23. * in this Software without prior written authorization from GROUPE BULL.
  24. */
  25. /*****************************************************************************\
  26. * data.c: *
  27. * *
  28. * XPM library *
  29. * IO utilities *
  30. * *
  31. * Developed by Arnaud Le Hors *
  32. \*****************************************************************************/
  33. /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
  34. #ifndef CXPMPROG
  35. #if 0
  36. /* Official version number */
  37. static char *RCS_Version = "$XpmVersion: 3.4k $";
  38. /* Internal version number */
  39. static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $";
  40. #endif
  41. #ifdef HAVE_CONFIG_H
  42. #include <config.h>
  43. #endif
  44. #include "XpmI.h"
  45. #endif
  46. #include <ctype.h>
  47. #ifndef CXPMPROG
  48. #define Getc(data, file) getc(file)
  49. #define Ungetc(data, c, file) ungetc(c, file)
  50. #endif
  51. static int
  52. ParseComment(xpmData *data)
  53. {
  54. if (data->type == XPMBUFFER) {
  55. register char c;
  56. register unsigned int n = 0;
  57. unsigned int notend;
  58. char *s;
  59. const char *s2;
  60. s = data->Comment;
  61. *s = data->Bcmt[0];
  62. /* skip the string beginning comment */
  63. s2 = data->Bcmt;
  64. do {
  65. c = *data->cptr++;
  66. *++s = c;
  67. n++;
  68. s2++;
  69. } while (c == *s2 && *s2 != '\0' && c);
  70. if (*s2 != '\0') {
  71. /* this wasn't the beginning of a comment */
  72. data->cptr -= n;
  73. return 0;
  74. }
  75. /* store comment */
  76. data->Comment[0] = *s;
  77. s = data->Comment;
  78. notend = 1;
  79. n = 0;
  80. while (notend) {
  81. s2 = data->Ecmt;
  82. while (*s != *s2 && c) {
  83. c = *data->cptr++;
  84. if (n == XPMMAXCMTLEN - 1) { /* forget it */
  85. s = data->Comment;
  86. n = 0;
  87. }
  88. *++s = c;
  89. n++;
  90. }
  91. data->CommentLength = n;
  92. do {
  93. c = *data->cptr++;
  94. if (n == XPMMAXCMTLEN - 1) { /* forget it */
  95. s = data->Comment;
  96. n = 0;
  97. }
  98. *++s = c;
  99. n++;
  100. s2++;
  101. } while (c == *s2 && *s2 != '\0' && c);
  102. if (*s2 == '\0') {
  103. /* this is the end of the comment */
  104. notend = 0;
  105. data->cptr--;
  106. }
  107. }
  108. return 0;
  109. } else {
  110. FILE *file = data->stream.file;
  111. register int c;
  112. register unsigned int n = 0, a;
  113. unsigned int notend;
  114. char *s;
  115. const char *s2;
  116. s = data->Comment;
  117. *s = data->Bcmt[0];
  118. /* skip the string beginning comment */
  119. s2 = data->Bcmt;
  120. do {
  121. c = Getc(data, file);
  122. *++s = c;
  123. n++;
  124. s2++;
  125. } while (c == *s2 && *s2 != '\0' && c != EOF);
  126. if (*s2 != '\0') {
  127. /* this wasn't the beginning of a comment */
  128. /* put characters back in the order that we got them */
  129. for (a = n; a > 0; a--, s--)
  130. Ungetc(data, *s, file);
  131. return 0;
  132. }
  133. /* store comment */
  134. data->Comment[0] = *s;
  135. s = data->Comment;
  136. notend = 1;
  137. n = 0;
  138. while (notend) {
  139. s2 = data->Ecmt;
  140. while (*s != *s2 && c != EOF) {
  141. c = Getc(data, file);
  142. if (n == XPMMAXCMTLEN - 1) { /* forget it */
  143. s = data->Comment;
  144. n = 0;
  145. }
  146. *++s = c;
  147. n++;
  148. }
  149. data->CommentLength = n;
  150. do {
  151. c = Getc(data, file);
  152. if (n == XPMMAXCMTLEN - 1) { /* forget it */
  153. s = data->Comment;
  154. n = 0;
  155. }
  156. *++s = c;
  157. n++;
  158. s2++;
  159. } while (c == *s2 && *s2 != '\0' && c != EOF);
  160. if (*s2 == '\0') {
  161. /* this is the end of the comment */
  162. notend = 0;
  163. Ungetc(data, *s, file);
  164. }
  165. }
  166. return 0;
  167. }
  168. }
  169. /*
  170. * skip to the end of the current string and the beginning of the next one
  171. */
  172. int
  173. xpmNextString(xpmData *data)
  174. {
  175. if (!data->type)
  176. data->cptr = (data->stream.data)[++data->line];
  177. else if (data->type == XPMBUFFER) {
  178. register char c;
  179. /* get to the end of the current string */
  180. if (data->Eos)
  181. while ((c = *data->cptr++) && c != data->Eos);
  182. /*
  183. * then get to the beginning of the next string looking for possible
  184. * comment
  185. */
  186. if (data->Bos) {
  187. while ((c = *data->cptr++) && c != data->Bos)
  188. if (data->Bcmt && c == data->Bcmt[0])
  189. ParseComment(data);
  190. } else if (data->Bcmt) { /* XPM2 natural */
  191. while ((c = *data->cptr++) == data->Bcmt[0])
  192. ParseComment(data);
  193. data->cptr--;
  194. }
  195. } else {
  196. register int c;
  197. FILE *file = data->stream.file;
  198. /* get to the end of the current string */
  199. if (data->Eos)
  200. while ((c = Getc(data, file)) != data->Eos && c != EOF);
  201. /*
  202. * then get to the beginning of the next string looking for possible
  203. * comment
  204. */
  205. if (data->Bos) {
  206. while ((c = Getc(data, file)) != data->Bos && c != EOF)
  207. if (data->Bcmt && c == data->Bcmt[0])
  208. ParseComment(data);
  209. } else if (data->Bcmt) { /* XPM2 natural */
  210. while ((c = Getc(data, file)) == data->Bcmt[0])
  211. ParseComment(data);
  212. Ungetc(data, c, file);
  213. }
  214. }
  215. return 0;
  216. }
  217. /*
  218. * skip whitespace and return the following word
  219. */
  220. unsigned int
  221. xpmNextWord(
  222. xpmData *data,
  223. char *buf,
  224. unsigned int buflen)
  225. {
  226. register unsigned int n = 0;
  227. int c;
  228. if (!data->type || data->type == XPMBUFFER) {
  229. while (isspace(c = *data->cptr) && c != data->Eos)
  230. data->cptr++;
  231. do {
  232. c = *data->cptr++;
  233. *buf++ = c;
  234. n++;
  235. } while (!isspace(c) && c != data->Eos && n < buflen);
  236. n--;
  237. data->cptr--;
  238. } else {
  239. FILE *file = data->stream.file;
  240. while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos);
  241. while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
  242. *buf++ = c;
  243. n++;
  244. c = Getc(data, file);
  245. }
  246. Ungetc(data, c, file);
  247. }
  248. return (n); /* this returns bytes read + 1 */
  249. }
  250. /*
  251. * skip whitespace and compute the following unsigned int,
  252. * returns 1 if one is found and 0 if not
  253. */
  254. int
  255. xpmNextUI(
  256. xpmData *data,
  257. unsigned int *ui_return)
  258. {
  259. char buf[BUFSIZ];
  260. int l;
  261. l = xpmNextWord(data, buf, BUFSIZ);
  262. return xpmatoui(buf, l, ui_return);
  263. }
  264. /*
  265. * return end of string - WARNING: malloc!
  266. */
  267. int
  268. xpmGetString(
  269. xpmData *data,
  270. char **sptr,
  271. unsigned int *l)
  272. {
  273. unsigned int i, n = 0;
  274. int c;
  275. char *p = NULL, *q, buf[BUFSIZ];
  276. if (!data->type || data->type == XPMBUFFER) {
  277. if (data->cptr) {
  278. char *start = data->cptr;
  279. while ((c = *data->cptr) && c != data->Eos)
  280. data->cptr++;
  281. n = data->cptr - start + 1;
  282. p = (char *) XpmMalloc(n);
  283. if (!p)
  284. return (XpmNoMemory);
  285. strncpy(p, start, n);
  286. if (data->type) /* XPMBUFFER */
  287. p[n - 1] = '\0';
  288. }
  289. } else {
  290. FILE *file = data->stream.file;
  291. if ((c = Getc(data, file)) == EOF)
  292. return (XpmFileInvalid);
  293. i = 0;
  294. q = buf;
  295. p = (char *) XpmMalloc(1);
  296. while (c != data->Eos && c != EOF) {
  297. if (i == BUFSIZ) {
  298. /* get to the end of the buffer */
  299. /* malloc needed memory */
  300. q = (char *) XpmRealloc(p, n + i);
  301. if (!q) {
  302. XpmFree(p);
  303. return (XpmNoMemory);
  304. }
  305. p = q;
  306. q += n;
  307. /* and copy what we already have */
  308. strncpy(q, buf, i);
  309. n += i;
  310. i = 0;
  311. q = buf;
  312. }
  313. *q++ = c;
  314. i++;
  315. c = Getc(data, file);
  316. }
  317. if (c == EOF) {
  318. XpmFree(p);
  319. return (XpmFileInvalid);
  320. }
  321. if (n + i != 0) {
  322. /* malloc needed memory */
  323. q = (char *) XpmRealloc(p, n + i + 1);
  324. if (!q) {
  325. XpmFree(p);
  326. return (XpmNoMemory);
  327. }
  328. p = q;
  329. q += n;
  330. /* and copy the buffer */
  331. strncpy(q, buf, i);
  332. n += i;
  333. p[n++] = '\0';
  334. } else {
  335. *p = '\0';
  336. n = 1;
  337. }
  338. Ungetc(data, c, file);
  339. }
  340. *sptr = p;
  341. *l = n;
  342. return (XpmSuccess);
  343. }
  344. /*
  345. * get the current comment line
  346. */
  347. int
  348. xpmGetCmt(
  349. xpmData *data,
  350. char **cmt)
  351. {
  352. if (!data->type)
  353. *cmt = NULL;
  354. else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) {
  355. if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL)
  356. return XpmNoMemory;
  357. strncpy(*cmt, data->Comment, data->CommentLength);
  358. (*cmt)[data->CommentLength] = '\0';
  359. data->CommentLength = 0;
  360. } else
  361. *cmt = NULL;
  362. return 0;
  363. }
  364. xpmDataType xpmDataTypes[] =
  365. {
  366. {"", "!", "\n", '\0', '\n', "", "", "", ""}, /* Natural type */
  367. {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"},
  368. {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"},
  369. {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
  370. };
  371. /*
  372. * parse xpm header
  373. */
  374. int
  375. xpmParseHeader(xpmData *data)
  376. {
  377. char buf[BUFSIZ+1] = {0};
  378. int l, n = 0;
  379. if (data->type) {
  380. data->Bos = '\0';
  381. data->Eos = '\n';
  382. data->Bcmt = data->Ecmt = NULL;
  383. l = xpmNextWord(data, buf, BUFSIZ);
  384. if (l == 7 && !strncmp("#define", buf, 7)) {
  385. /* this maybe an XPM 1 file */
  386. char *ptr;
  387. l = xpmNextWord(data, buf, BUFSIZ);
  388. if (!l)
  389. return (XpmFileInvalid);
  390. buf[l] = '\0';
  391. ptr = strrchr(buf, '_');
  392. if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
  393. return XpmFileInvalid;
  394. /* this is definitely an XPM 1 file */
  395. data->format = 1;
  396. n = 1; /* handle XPM1 as mainly XPM2 C */
  397. } else {
  398. /*
  399. * skip the first word, get the second one, and see if this is
  400. * XPM 2 or 3
  401. */
  402. l = xpmNextWord(data, buf, BUFSIZ);
  403. if ((l == 3 && !strncmp("XPM", buf, 3)) ||
  404. (l == 4 && !strncmp("XPM2", buf, 4))) {
  405. if (l == 3)
  406. n = 1; /* handle XPM as XPM2 C */
  407. else {
  408. /* get the type key word */
  409. l = xpmNextWord(data, buf, BUFSIZ);
  410. /*
  411. * get infos about this type
  412. */
  413. while (xpmDataTypes[n].type
  414. && strncmp(xpmDataTypes[n].type, buf, l))
  415. n++;
  416. }
  417. data->format = 0;
  418. } else
  419. /* nope this is not an XPM file */
  420. return XpmFileInvalid;
  421. }
  422. if (xpmDataTypes[n].type) {
  423. if (n == 0) { /* natural type */
  424. data->Bcmt = xpmDataTypes[n].Bcmt;
  425. data->Ecmt = xpmDataTypes[n].Ecmt;
  426. xpmNextString(data); /* skip the end of the headerline */
  427. data->Bos = xpmDataTypes[n].Bos;
  428. data->Eos = xpmDataTypes[n].Eos;
  429. } else {
  430. data->Bcmt = xpmDataTypes[n].Bcmt;
  431. data->Ecmt = xpmDataTypes[n].Ecmt;
  432. if (!data->format) { /* XPM 2 or 3 */
  433. data->Bos = xpmDataTypes[n].Bos;
  434. data->Eos = '\0';
  435. /* get to the beginning of the first string */
  436. xpmNextString(data);
  437. data->Eos = xpmDataTypes[n].Eos;
  438. } else /* XPM 1 skip end of line */
  439. xpmNextString(data);
  440. }
  441. } else
  442. /* we don't know about that type of XPM file... */
  443. return XpmFileInvalid;
  444. }
  445. return XpmSuccess;
  446. }