~ubuntu-branches/ubuntu/quantal/libxpm/quantal

« back to all changes in this revision

Viewing changes to src/parse.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Stone
  • Date: 2005-07-23 01:33:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050723013331-3azqgwnbdc7sjosd
Tags: upstream-3.5.2
ImportĀ upstreamĀ versionĀ 3.5.2

Show diffs side-by-side

added added

removed removed

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