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 /*****************************************************************************\
27 * parse.c: *
28 * *
29 * XPM library *
30 * Parse an XPM file or array and store the found informations *
31 * in the given XpmImage structure. *
32 * *
33 * Developed by Arnaud Le Hors *
34 \*****************************************************************************/
35
36 /*
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
39 */
40
41 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46 #include "XpmI.h"
47 #include <ctype.h>
48 #include <string.h>
49
50 /**
51 * like strlcat() but returns true on success and false if the string got
52 * truncated.
53 */
54 static inline Bool
xstrlcat(char * dst,const char * src,size_t dstsize)55 xstrlcat(char *dst, const char *src, size_t dstsize)
56 {
57 #if defined(HAS_STRLCAT) || defined(HAVE_STRLCAT)
58 return strlcat(dst, src, dstsize) < dstsize;
59 #else
60 if ((strlen(dst) + strlen(src)) < dstsize) {
61 strcat(dst, src);
62 return True;
63 } else {
64 return False;
65 }
66 #endif
67 }
68
69 /**
70 * like strlcpy() but returns true on success and false if the string got
71 * truncated.
72 */
73 static inline Bool
xstrlcpy(char * dst,const char * src,size_t dstsize)74 xstrlcpy(char *dst, const char *src, size_t dstsize)
75 {
76 #if defined(HAS_STRLCAT) || defined(HAVE_STRLCAT)
77 return strlcpy(dst, src, dstsize) < dstsize;
78 #else
79 if (strlen(src) < dstsize) {
80 strcpy(dst, src);
81 return True;
82 } else {
83 return False;
84 }
85 #endif
86 }
87
88 LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
89 unsigned int height, unsigned int ncolors,
90 unsigned int cpp, XpmColor *colorTable,
91 xpmHashTable *hashtable, unsigned int **pixels));
92
93 const char *xpmColorKeys[] = {
94 "s", /* key #1: symbol */
95 "m", /* key #2: mono visual */
96 "g4", /* key #3: 4 grays visual */
97 "g", /* key #4: gray visual */
98 "c", /* key #5: color visual */
99 };
100
101 int
xpmParseValues(xpmData * data,unsigned int * width,unsigned int * height,unsigned int * ncolors,unsigned int * cpp,unsigned int * x_hotspot,unsigned int * y_hotspot,unsigned int * hotspot,unsigned int * extensions)102 xpmParseValues(
103 xpmData *data,
104 unsigned int *width,
105 unsigned int *height,
106 unsigned int *ncolors,
107 unsigned int *cpp,
108 unsigned int *x_hotspot,
109 unsigned int *y_hotspot,
110 unsigned int *hotspot,
111 unsigned int *extensions)
112 {
113 unsigned int l;
114 char buf[BUFSIZ + 1];
115
116 if (!data->format) { /* XPM 2 or 3 */
117
118 /*
119 * read values: width, height, ncolors, chars_per_pixel
120 */
121 if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
122 && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
123 return (XpmFileInvalid);
124
125 /*
126 * read optional information (hotspot and/or XPMEXT) if any
127 */
128 l = xpmNextWord(data, buf, BUFSIZ);
129 if (l) {
130 *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
131 if (*extensions)
132 *hotspot = (xpmNextUI(data, x_hotspot)
133 && xpmNextUI(data, y_hotspot));
134 else {
135 *hotspot = (xpmatoui(buf, l, x_hotspot)
136 && xpmNextUI(data, y_hotspot));
137 l = xpmNextWord(data, buf, BUFSIZ);
138 *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
139 }
140 }
141 } else {
142
143 /*
144 * XPM 1 file read values: width, height, ncolors, chars_per_pixel
145 */
146 int i;
147 char *ptr;
148 Bool got_one, saw_width = False, saw_height = False;
149 Bool saw_ncolors = False, saw_chars_per_pixel = False;
150
151 for (i = 0; i < 4; i++) {
152 l = xpmNextWord(data, buf, BUFSIZ);
153 if (l != 7 || strncmp("#define", buf, 7))
154 return (XpmFileInvalid);
155 l = xpmNextWord(data, buf, BUFSIZ);
156 if (!l)
157 return (XpmFileInvalid);
158 buf[l] = '\0';
159 ptr = buf;
160 got_one = False;
161 while (!got_one) {
162 ptr = strchr(ptr, '_');
163 if (!ptr)
164 return (XpmFileInvalid);
165 switch (l - (ptr - buf)) {
166 case 6:
167 if (saw_width || strncmp("_width", ptr, 6)
168 || !xpmNextUI(data, width))
169 return (XpmFileInvalid);
170 else
171 saw_width = True;
172 got_one = True;
173 break;
174 case 7:
175 if (saw_height || strncmp("_height", ptr, 7)
176 || !xpmNextUI(data, height))
177 return (XpmFileInvalid);
178 else
179 saw_height = True;
180 got_one = True;
181 break;
182 case 8:
183 if (saw_ncolors || strncmp("_ncolors", ptr, 8)
184 || !xpmNextUI(data, ncolors))
185 return (XpmFileInvalid);
186 else
187 saw_ncolors = True;
188 got_one = True;
189 break;
190 case 16:
191 if (saw_chars_per_pixel
192 || strncmp("_chars_per_pixel", ptr, 16)
193 || !xpmNextUI(data, cpp))
194 return (XpmFileInvalid);
195 else
196 saw_chars_per_pixel = True;
197 got_one = True;
198 break;
199 default:
200 ptr++;
201 }
202 }
203 /* skip the end of line */
204 xpmNextString(data);
205 }
206 if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel)
207 return (XpmFileInvalid);
208
209 *hotspot = 0;
210 *extensions = 0;
211 }
212 return (XpmSuccess);
213 }
214
215 int
xpmParseColors(xpmData * data,unsigned int ncolors,unsigned int cpp,XpmColor ** colorTablePtr,xpmHashTable * hashtable)216 xpmParseColors(
217 xpmData *data,
218 unsigned int ncolors,
219 unsigned int cpp,
220 XpmColor **colorTablePtr,
221 xpmHashTable *hashtable)
222 {
223 unsigned int key = 0, l, a, b, len;
224 unsigned int curkey; /* current color key */
225 unsigned int lastwaskey; /* key read */
226 char buf[BUFSIZ+1];
227 char curbuf[BUFSIZ]; /* current buffer */
228 const char **sptr;
229 char *s;
230 XpmColor *color;
231 XpmColor *colorTable;
232 char **defaults;
233 int ErrorStatus;
234
235 if (ncolors >= UINT_MAX / sizeof(XpmColor))
236 return (XpmNoMemory);
237 colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor));
238 if (!colorTable)
239 return (XpmNoMemory);
240
241 if (!data->format) { /* XPM 2 or 3 */
242 for (a = 0, color = colorTable; a < ncolors; a++, color++) {
243 xpmNextString(data); /* skip the line */
244
245 /*
246 * read pixel value
247 */
248 if (cpp >= UINT_MAX - 1) {
249 ErrorStatus = XpmNoMemory;
250 goto error;
251 }
252 color->string = (char *) XpmMalloc(cpp + 1);
253 if (!color->string) {
254 ErrorStatus = XpmNoMemory;
255 goto error;
256 }
257 for (b = 0, s = color->string; b < cpp; b++, s++) {
258 int c = xpmGetC(data);
259 if (c < 0) {
260 ErrorStatus = XpmFileInvalid;
261 goto error;
262 }
263 *s = (char) c;
264 }
265 *s = '\0';
266
267 /*
268 * store the string in the hashtable with its color index number
269 */
270 if (USE_HASHTABLE) {
271 ErrorStatus =
272 xpmHashIntern(hashtable, color->string, HashAtomData(a));
273 if (ErrorStatus != XpmSuccess) {
274 goto error;
275 }
276 }
277
278 /*
279 * read color keys and values
280 */
281 defaults = (char **) color;
282 curkey = 0;
283 lastwaskey = 0;
284 *curbuf = '\0'; /* init curbuf */
285 while ((l = xpmNextWord(data, buf, BUFSIZ))) {
286 if (!lastwaskey) {
287 for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++,
288 sptr++)
289 if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
290 break;
291 }
292 if (!lastwaskey && key < NKEYS) { /* open new key */
293 if (curkey) { /* flush string */
294 len = strlen(curbuf) + 1;
295 s = (char *) XpmMalloc(len);
296 if (!s) {
297 ErrorStatus = XpmNoMemory;
298 goto error;
299 }
300 defaults[curkey] = s;
301 memcpy(s, curbuf, len);
302 }
303 curkey = key + 1; /* set new key */
304 *curbuf = '\0'; /* reset curbuf */
305 lastwaskey = 1;
306 } else {
307 if (!curkey) { /* key without value */
308 ErrorStatus = XpmFileInvalid;
309 goto error;
310 }
311 if (!lastwaskey) {
312 if (!xstrlcat(curbuf, " ", sizeof(curbuf))) { /* append space */
313 ErrorStatus = XpmFileInvalid;
314 goto error;
315 }
316 }
317 buf[l] = '\0';
318 if (!xstrlcat(curbuf, buf, sizeof(curbuf))) { /* append buf */
319 ErrorStatus = XpmFileInvalid;
320 goto error;
321 }
322 lastwaskey = 0;
323 }
324 }
325 if (!curkey) { /* key without value */
326 ErrorStatus = XpmFileInvalid;
327 goto error;
328 }
329 len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */
330 s = defaults[curkey] = (char *) XpmMalloc(len);
331 if (!s) {
332 ErrorStatus = XpmNoMemory;
333 goto error;
334 }
335 memcpy(s, curbuf, len);
336 }
337 } else { /* XPM 1 */
338 /* get to the beginning of the first string */
339 data->Bos = '"';
340 data->Eos = '\0';
341 xpmNextString(data);
342 data->Eos = '"';
343 for (a = 0, color = colorTable; a < ncolors; a++, color++) {
344
345 /*
346 * read pixel value
347 */
348 if (cpp >= UINT_MAX - 1) {
349 ErrorStatus = XpmNoMemory;
350 goto error;
351 }
352 color->string = (char *) XpmMalloc(cpp + 1);
353 if (!color->string) {
354 ErrorStatus = XpmNoMemory;
355 goto error;
356 }
357 for (b = 0, s = color->string; b < cpp; b++, s++) {
358 int c = xpmGetC(data);
359 if (c < 0) {
360 ErrorStatus = XpmFileInvalid;
361 goto error;
362 }
363 *s = (char) c;
364 }
365 *s = '\0';
366
367 /*
368 * store the string in the hashtable with its color index number
369 */
370 if (USE_HASHTABLE) {
371 ErrorStatus =
372 xpmHashIntern(hashtable, color->string, HashAtomData(a));
373 if (ErrorStatus != XpmSuccess) {
374 goto error;
375 }
376 }
377
378 /*
379 * read color values
380 */
381 xpmNextString(data); /* get to the next string */
382 *curbuf = '\0'; /* init curbuf */
383 while ((l = xpmNextWord(data, buf, BUFSIZ))) {
384 if (*curbuf != '\0') {
385 if (!xstrlcat(curbuf, " ", sizeof(curbuf))) { /* append space */
386 ErrorStatus = XpmFileInvalid;
387 goto error;
388 }
389 }
390 buf[l] = '\0';
391 if (!xstrlcat(curbuf, buf, sizeof(curbuf))) { /* append buf */
392 ErrorStatus = XpmFileInvalid;
393 goto error;
394 }
395 }
396 len = strlen(curbuf) + 1;
397 s = (char *) XpmMalloc(len);
398 if (!s) {
399 ErrorStatus = XpmNoMemory;
400 goto error;
401 }
402 memcpy(s, curbuf, len);
403 color->c_color = s;
404 *curbuf = '\0'; /* reset curbuf */
405 if (a < ncolors - 1) /* can we trust ncolors -> leave data's bounds */
406 xpmNextString(data); /* get to the next string */
407 }
408 }
409 *colorTablePtr = colorTable;
410 return (XpmSuccess);
411
412 error:
413 xpmFreeColorTable(colorTable, ncolors);
414 return ErrorStatus;
415 }
416
417 static int
ParsePixels(xpmData * data,unsigned int width,unsigned int height,unsigned int ncolors,unsigned int cpp,XpmColor * colorTable,xpmHashTable * hashtable,unsigned int ** pixels)418 ParsePixels(
419 xpmData *data,
420 unsigned int width,
421 unsigned int height,
422 unsigned int ncolors,
423 unsigned int cpp,
424 XpmColor *colorTable,
425 xpmHashTable *hashtable,
426 unsigned int **pixels)
427 {
428 unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */
429 unsigned int a, x, y;
430
431 if ((height > 0 && width >= UINT_MAX / height) ||
432 width * height >= UINT_MAX / sizeof(unsigned int))
433 return XpmNoMemory;
434 #ifndef FOR_MSW
435 iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height);
436 #else
437
438 /*
439 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
440 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
441 */
442 iptr2 = (unsigned int *)
443 XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height);
444 #endif
445 if (!iptr2)
446 return (XpmNoMemory);
447
448 iptr = iptr2;
449
450 switch (cpp) {
451
452 case (1): /* Optimize for single character
453 * colors */
454 {
455 unsigned short colidx[256];
456
457 if (ncolors > 256) {
458 XpmFree(iptr2); /* found by Egbert Eich */
459 return (XpmFileInvalid);
460 }
461
462 bzero((char *)colidx, 256 * sizeof(short));
463 for (a = 0; a < ncolors; a++)
464 colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
465
466 for (y = 0; y < height; y++) {
467 xpmNextString(data);
468 for (x = 0; x < width; x++, iptr++) {
469 int c = xpmGetC(data);
470
471 if (c > 0 && c < 256 && colidx[c] != 0)
472 *iptr = colidx[c] - 1;
473 else {
474 XpmFree(iptr2);
475 return (XpmFileInvalid);
476 }
477 }
478 }
479 }
480 break;
481
482 case (2): /* Optimize for double character
483 * colors */
484 {
485
486 /* free all allocated pointers at all exits */
487 #define FREE_CIDX \
488 do \
489 { \
490 int f; for (f = 0; f < 256; f++) \
491 if (cidx[f]) XpmFree(cidx[f]); \
492 } while(0)
493
494 /* array of pointers malloced by need */
495 unsigned short *cidx[256];
496 unsigned int char1;
497
498 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
499 for (a = 0; a < ncolors; a++) {
500 char1 = (unsigned char) colorTable[a].string[0];
501 if (cidx[char1] == NULL) { /* get new memory */
502 cidx[char1] = (unsigned short *)
503 XpmCalloc(256, sizeof(unsigned short));
504 if (cidx[char1] == NULL) { /* new block failed */
505 FREE_CIDX;
506 XpmFree(iptr2);
507 return (XpmNoMemory);
508 }
509 }
510 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
511 }
512
513 for (y = 0; y < height; y++) {
514 xpmNextString(data);
515 for (x = 0; x < width; x++, iptr++) {
516 int cc1 = xpmGetC(data);
517 if (cc1 > 0 && cc1 < 256) {
518 int cc2 = xpmGetC(data);
519 if (cc2 > 0 && cc2 < 256 &&
520 cidx[cc1] && cidx[cc1][cc2] != 0)
521 *iptr = cidx[cc1][cc2] - 1;
522 else {
523 FREE_CIDX;
524 XpmFree(iptr2);
525 return (XpmFileInvalid);
526 }
527 } else {
528 FREE_CIDX;
529 XpmFree(iptr2);
530 return (XpmFileInvalid);
531 }
532 }
533 }
534 FREE_CIDX;
535 }
536 break;
537
538 default: /* Non-optimized case of long color
539 * names */
540 {
541 char *s;
542 char buf[BUFSIZ];
543
544 if (cpp >= sizeof(buf)) {
545 XpmFree(iptr2); /* found by Egbert Eich */
546 return (XpmFileInvalid);
547 }
548
549 buf[cpp] = '\0';
550 if (USE_HASHTABLE) {
551 xpmHashAtom *slot;
552
553 for (y = 0; y < height; y++) {
554 xpmNextString(data);
555 for (x = 0; x < width; x++, iptr++) {
556 for (a = 0, s = buf; a < cpp; a++, s++) {
557 int c = xpmGetC(data);
558 if (c < 0) {
559 XpmFree(iptr2);
560 return (XpmFileInvalid);
561 }
562 *s = (char) c;
563 }
564 slot = xpmHashSlot(hashtable, buf);
565 if (!*slot) { /* no color matches */
566 XpmFree(iptr2);
567 return (XpmFileInvalid);
568 }
569 *iptr = HashColorIndex(slot);
570 }
571 }
572 } else {
573 for (y = 0; y < height; y++) {
574 xpmNextString(data);
575 for (x = 0; x < width; x++, iptr++) {
576 for (a = 0, s = buf; a < cpp; a++, s++) {
577 int c = xpmGetC(data);
578 if (c < 0) {
579 XpmFree(iptr2);
580 return (XpmFileInvalid);
581 }
582 *s = (char) c;
583 }
584 for (a = 0; a < ncolors; a++)
585 if (!strcmp(colorTable[a].string, buf))
586 break;
587 if (a == ncolors) { /* no color matches */
588 XpmFree(iptr2);
589 return (XpmFileInvalid);
590 }
591 *iptr = a;
592 }
593 }
594 }
595 }
596 break;
597 }
598 *pixels = iptr2;
599 return (XpmSuccess);
600 }
601
602 int
xpmParseExtensions(xpmData * data,XpmExtension ** extensions,unsigned int * nextensions)603 xpmParseExtensions(
604 xpmData *data,
605 XpmExtension **extensions,
606 unsigned int *nextensions)
607 {
608 XpmExtension *exts = NULL, *ext;
609 unsigned int num = 0;
610 unsigned int nlines, a, l, notstart, notend = 0;
611 int status;
612 char *string, *s, *s2, **sp;
613
614 xpmNextString(data);
615 exts = (XpmExtension *) XpmMalloc(sizeof(XpmExtension));
616 /* get the whole string */
617 status = xpmGetString(data, &string, &l);
618 if (status != XpmSuccess) {
619 XpmFree(exts);
620 return (status);
621 }
622 /* look for the key word XPMEXT, skip lines before this */
623 while ((notstart = strncmp("XPMEXT", string, 6))
624 && (notend = strncmp("XPMENDEXT", string, 9))) {
625 XpmFree(string);
626 xpmNextString(data);
627 status = xpmGetString(data, &string, &l);
628 if (status != XpmSuccess) {
629 XpmFree(exts);
630 return (status);
631 }
632 }
633 if (!notstart)
634 notend = strncmp("XPMENDEXT", string, 9);
635 while (!notstart && notend) {
636 /* there starts an extension */
637 ext = (XpmExtension *)
638 XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); /* can the loop be forced to iterate often enough to make "(num + 1) * sizeof(XpmExtension)" wrapping? */
639 if (!ext) {
640 XpmFree(string);
641 XpmFreeExtensions(exts, num);
642 return (XpmNoMemory);
643 }
644 exts = ext;
645 ext += num;
646 /* skip whitespace and store its name */
647 s2 = s = string + 6;
648 while (isspace(*s2))
649 s2++;
650 a = s2 - s;
651 ext->name = (char *) XpmMalloc(l - a - 6);
652 if (!ext->name) {
653 XpmFree(string);
654 ext->lines = NULL;
655 ext->nlines = 0;
656 XpmFreeExtensions(exts, num + 1);
657 return (XpmNoMemory);
658 }
659 strncpy(ext->name, s + a, l - a - 6);
660 XpmFree(string);
661 /* now store the related lines */
662 xpmNextString(data);
663 status = xpmGetString(data, &string, &l);
664 if (status != XpmSuccess) {
665 ext->lines = NULL;
666 ext->nlines = 0;
667 XpmFreeExtensions(exts, num + 1);
668 return (status);
669 }
670 ext->lines = (char **) XpmMalloc(sizeof(char *));
671 nlines = 0;
672 while ((notstart = strncmp("XPMEXT", string, 6))
673 && (notend = strncmp("XPMENDEXT", string, 9))) {
674 sp = (char **)
675 XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); /* can we iterate enough for a wrapping? */
676 if (!sp) {
677 XpmFree(string);
678 ext->nlines = nlines;
679 XpmFreeExtensions(exts, num + 1);
680 return (XpmNoMemory);
681 }
682 ext->lines = sp;
683 ext->lines[nlines] = string;
684 nlines++;
685 xpmNextString(data);
686 status = xpmGetString(data, &string, &l);
687 if (status != XpmSuccess) {
688 ext->nlines = nlines;
689 XpmFreeExtensions(exts, num + 1);
690 return (status);
691 }
692 }
693 if (!nlines) {
694 XpmFree(ext->lines);
695 ext->lines = NULL;
696 }
697 ext->nlines = nlines;
698 num++;
699 }
700 if (!num) {
701 XpmFree(string);
702 XpmFree(exts);
703 exts = NULL;
704 } else if (!notend)
705 XpmFree(string);
706 *nextensions = num;
707 *extensions = exts;
708 return (XpmSuccess);
709 }
710
711
712 /* function call in case of error */
713 #undef RETURN
714 #define RETURN(status) \
715 do { \
716 goto error; \
717 } while(0)
718
719 /*
720 * This function parses an Xpm file or data and store the found informations
721 * in an an XpmImage structure which is returned.
722 */
723 int
xpmParseData(xpmData * data,XpmImage * image,XpmInfo * info)724 xpmParseData(
725 xpmData *data,
726 XpmImage *image,
727 XpmInfo *info)
728 {
729 /* variables to return */
730 unsigned int width, height, ncolors, cpp;
731 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
732 XpmColor *colorTable = NULL;
733 unsigned int *pixelindex = NULL;
734 char *hints_cmt = NULL;
735 char *colors_cmt = NULL;
736 char *pixels_cmt = NULL;
737
738 unsigned int cmts;
739 int ErrorStatus;
740 xpmHashTable hashtable;
741
742 cmts = info && (info->valuemask & XpmReturnComments);
743
744 /*
745 * parse the header
746 */
747 ErrorStatus = xpmParseHeader(data);
748 if (ErrorStatus != XpmSuccess)
749 return (ErrorStatus);
750
751 /*
752 * read values
753 */
754 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
755 &x_hotspot, &y_hotspot, &hotspot,
756 &extensions);
757 if (ErrorStatus != XpmSuccess)
758 return (ErrorStatus);
759
760 /*
761 * store the hints comment line
762 */
763 if (cmts)
764 xpmGetCmt(data, &hints_cmt);
765
766 /*
767 * init the hashtable
768 */
769 if (USE_HASHTABLE) {
770 ErrorStatus = xpmHashTableInit(&hashtable);
771 if (ErrorStatus != XpmSuccess)
772 RETURN(ErrorStatus);
773 }
774
775 /*
776 * read colors
777 */
778 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
779 if (ErrorStatus != XpmSuccess) {
780 if (USE_HASHTABLE)
781 xpmHashTableFree(&hashtable);
782 RETURN(ErrorStatus);
783 }
784
785 /*
786 * store the colors comment line
787 */
788 if (cmts)
789 xpmGetCmt(data, &colors_cmt);
790
791 /*
792 * read pixels and index them on color number
793 */
794 ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
795 &hashtable, &pixelindex);
796
797 /*
798 * free the hastable
799 */
800 if (USE_HASHTABLE)
801 xpmHashTableFree(&hashtable);
802
803 if (ErrorStatus != XpmSuccess)
804 RETURN(ErrorStatus);
805
806 /*
807 * store the pixels comment line
808 */
809 if (cmts)
810 xpmGetCmt(data, &pixels_cmt);
811
812 /*
813 * parse extensions
814 */
815 if (info && (info->valuemask & XpmReturnExtensions)) {
816 if (extensions) {
817 ErrorStatus = xpmParseExtensions(data, &info->extensions,
818 &info->nextensions);
819 if (ErrorStatus != XpmSuccess)
820 RETURN(ErrorStatus);
821 } else {
822 info->extensions = NULL;
823 info->nextensions = 0;
824 }
825 }
826
827 /*
828 * store found informations in the XpmImage structure
829 */
830 image->width = width;
831 image->height = height;
832 image->cpp = cpp;
833 image->ncolors = ncolors;
834 image->colorTable = colorTable;
835 image->data = pixelindex;
836
837 if (info) {
838 if (cmts) {
839 info->hints_cmt = hints_cmt;
840 info->colors_cmt = colors_cmt;
841 info->pixels_cmt = pixels_cmt;
842 }
843 if (hotspot) {
844 info->x_hotspot = x_hotspot;
845 info->y_hotspot = y_hotspot;
846 info->valuemask |= XpmHotspot;
847 }
848 }
849 return (XpmSuccess);
850
851 /* exit point in case of error, free only locally allocated variables */
852 error:
853 if (colorTable)
854 xpmFreeColorTable(colorTable, ncolors);
855 if (pixelindex)
856 XpmFree(pixelindex);
857 if (hints_cmt)
858 XpmFree(hints_cmt);
859 if (colors_cmt)
860 XpmFree(colors_cmt);
861 if (pixels_cmt)
862 XpmFree(pixels_cmt);
863
864 return(ErrorStatus);
865 }
866