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