File: | parse.c |
Location: | line 387, column 30 |
Description: | Call to 'malloc' has an allocation size of 0 bytes |
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_H1 | ||||
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 { if ((strlen(dst) + strlen(src)) < (dstsize)) strcat(dst , src); else return (-2); } while(0) do { \ | ||||
52 | if (strlcat(dst, src, dstsize) >= (dstsize)) \ | ||||
53 | return (XpmFileInvalid-2); } while(0) | ||||
54 | # define STRLCPY(dst, src, dstsize)do { if (strlen(src) < (dstsize)) strcpy(dst, src); else return (-2); } while(0) do { \ | ||||
55 | if (strlcpy(dst, src, dstsize) >= (dstsize)) \ | ||||
56 | return (XpmFileInvalid-2); } while(0) | ||||
57 | #else | ||||
58 | # define STRLCAT(dst, src, dstsize)do { if ((strlen(dst) + strlen(src)) < (dstsize)) strcat(dst , src); else return (-2); } while(0) do { \ | ||||
59 | if ((strlen(dst) + strlen(src)) < (dstsize)) \ | ||||
60 | strcat(dst, src); \ | ||||
61 | else return (XpmFileInvalid-2); } while(0) | ||||
62 | # define STRLCPY(dst, src, dstsize)do { if (strlen(src) < (dstsize)) strcpy(dst, src); else return (-2); } while(0) do { \ | ||||
63 | if (strlen(src) < (dstsize)) \ | ||||
64 | strcpy(dst, src); \ | ||||
65 | else return (XpmFileInvalid-2); } while(0) | ||||
66 | #endif | ||||
67 | |||||
68 | LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | ||||
69 | unsigned int height, unsigned int ncolors,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | ||||
70 | unsigned int cpp, XpmColor *colorTable,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | ||||
71 | xpmHashTable *hashtable, unsigned int **pixels))static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, 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[BUFSIZ8192 + 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-2); | ||||
104 | |||||
105 | /* | ||||
106 | * read optional information (hotspot and/or XPMEXT) if any | ||||
107 | */ | ||||
108 | l = xpmNextWord(data, buf, BUFSIZ8192); | ||||
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, BUFSIZ8192); | ||||
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 | Boolint got_one, saw_width = False0, saw_height = False0; | ||||
129 | Boolint saw_ncolors = False0, saw_chars_per_pixel = False0; | ||||
130 | |||||
131 | for (i = 0; i < 4; i++) { | ||||
132 | l = xpmNextWord(data, buf, BUFSIZ8192); | ||||
133 | if (l != 7 || strncmp("#define", buf, 7)) | ||||
134 | return (XpmFileInvalid-2); | ||||
135 | l = xpmNextWord(data, buf, BUFSIZ8192); | ||||
136 | if (!l) | ||||
137 | return (XpmFileInvalid-2); | ||||
138 | buf[l] = '\0'; | ||||
139 | ptr = buf; | ||||
140 | got_one = False0; | ||||
141 | while (!got_one) { | ||||
142 | ptr = strchr(ptr, '_'); | ||||
143 | if (!ptr) | ||||
144 | return (XpmFileInvalid-2); | ||||
145 | switch (l - (ptr - buf)) { | ||||
146 | case 6: | ||||
147 | if (saw_width || strncmp("_width", ptr, 6) | ||||
148 | || !xpmNextUI(data, width)) | ||||
149 | return (XpmFileInvalid-2); | ||||
150 | else | ||||
151 | saw_width = True1; | ||||
152 | got_one = True1; | ||||
153 | break; | ||||
154 | case 7: | ||||
155 | if (saw_height || strncmp("_height", ptr, 7) | ||||
156 | || !xpmNextUI(data, height)) | ||||
157 | return (XpmFileInvalid-2); | ||||
158 | else | ||||
159 | saw_height = True1; | ||||
160 | got_one = True1; | ||||
161 | break; | ||||
162 | case 8: | ||||
163 | if (saw_ncolors || strncmp("_ncolors", ptr, 8) | ||||
164 | || !xpmNextUI(data, ncolors)) | ||||
165 | return (XpmFileInvalid-2); | ||||
166 | else | ||||
167 | saw_ncolors = True1; | ||||
168 | got_one = True1; | ||||
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-2); | ||||
175 | else | ||||
176 | saw_chars_per_pixel = True1; | ||||
177 | got_one = True1; | ||||
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-2); | ||||
188 | |||||
189 | *hotspot = 0; | ||||
190 | *extensions = 0; | ||||
191 | } | ||||
192 | return (XpmSuccess0); | ||||
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[BUFSIZ8192+1]; | ||||
207 | char curbuf[BUFSIZ8192]; /* 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(2147483647 *2U +1U) / sizeof(XpmColor)) | ||||
216 | return (XpmNoMemory-3); | ||||
217 | colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor))calloc((ncolors), (sizeof(XpmColor))); | ||||
218 | if (!colorTable) | ||||
219 | return (XpmNoMemory-3); | ||||
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(2147483647 *2U +1U) - 1) { | ||||
229 | xpmFreeColorTable(colorTable, ncolors); | ||||
230 | return (XpmNoMemory-3); | ||||
231 | } | ||||
232 | color->string = (char *) XpmMalloc(cpp + 1)malloc((cpp + 1)); | ||||
233 | if (!color->string) { | ||||
234 | xpmFreeColorTable(colorTable, ncolors); | ||||
235 | return (XpmNoMemory-3); | ||||
236 | } | ||||
237 | for (b = 0, s = color->string; b < cpp; b++, s++) | ||||
238 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); | ||||
239 | *s = '\0'; | ||||
240 | |||||
241 | /* | ||||
242 | * store the string in the hashtable with its color index number | ||||
243 | */ | ||||
244 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | ||||
245 | ErrorStatus = | ||||
246 | xpmHashIntern(hashtable, color->string, HashAtomData(a)((void *)(long)a)); | ||||
247 | if (ErrorStatus != XpmSuccess0) { | ||||
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, BUFSIZ8192))) { | ||||
261 | if (!lastwaskey) { | ||||
262 | for (key = 0, sptr = xpmColorKeys; key < NKEYS5; key++, | ||||
263 | sptr++) | ||||
264 | if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l))) | ||||
265 | break; | ||||
266 | } | ||||
267 | if (!lastwaskey && key < NKEYS5) { /* open new key */ | ||||
268 | if (curkey) { /* flush string */ | ||||
269 | len = strlen(curbuf) + 1; | ||||
270 | s = (char *) XpmMalloc(len)malloc((len)); | ||||
271 | if (!s) { | ||||
272 | xpmFreeColorTable(colorTable, ncolors); | ||||
273 | return (XpmNoMemory-3); | ||||
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-2); | ||||
285 | } | ||||
286 | if (!lastwaskey) | ||||
287 | STRLCAT(curbuf, " ", sizeof(curbuf))do { if ((strlen(curbuf) + strlen(" ")) < (sizeof(curbuf)) ) strcat(curbuf, " "); else return (-2); } while(0);/* append space */ | ||||
288 | buf[l] = '\0'; | ||||
289 | STRLCAT(curbuf, buf, sizeof(curbuf))do { if ((strlen(curbuf) + strlen(buf)) < (sizeof(curbuf)) ) strcat(curbuf, buf); else return (-2); } while(0); /* append buf */ | ||||
290 | lastwaskey = 0; | ||||
291 | } | ||||
292 | } | ||||
293 | if (!curkey) { /* key without value */ | ||||
294 | xpmFreeColorTable(colorTable, ncolors); | ||||
295 | return (XpmFileInvalid-2); | ||||
296 | } | ||||
297 | len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */ | ||||
298 | s = defaults[curkey] = (char *) XpmMalloc(len)malloc((len)); | ||||
299 | if (!s) { | ||||
300 | xpmFreeColorTable(colorTable, ncolors); | ||||
301 | return (XpmNoMemory-3); | ||||
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(2147483647 *2U +1U) - 1) { | ||||
317 | xpmFreeColorTable(colorTable, ncolors); | ||||
318 | return (XpmNoMemory-3); | ||||
319 | } | ||||
320 | color->string = (char *) XpmMalloc(cpp + 1)malloc((cpp + 1)); | ||||
321 | if (!color->string) { | ||||
322 | xpmFreeColorTable(colorTable, ncolors); | ||||
323 | return (XpmNoMemory-3); | ||||
324 | } | ||||
325 | for (b = 0, s = color->string; b < cpp; b++, s++) | ||||
326 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); | ||||
327 | *s = '\0'; | ||||
328 | |||||
329 | /* | ||||
330 | * store the string in the hashtable with its color index number | ||||
331 | */ | ||||
332 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | ||||
333 | ErrorStatus = | ||||
334 | xpmHashIntern(hashtable, color->string, HashAtomData(a)((void *)(long)a)); | ||||
335 | if (ErrorStatus != XpmSuccess0) { | ||||
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, BUFSIZ8192))) { | ||||
347 | if (*curbuf != '\0') | ||||
348 | STRLCAT(curbuf, " ", sizeof(curbuf))do { if ((strlen(curbuf) + strlen(" ")) < (sizeof(curbuf)) ) strcat(curbuf, " "); else return (-2); } while(0);/* append space */ | ||||
349 | buf[l] = '\0'; | ||||
350 | STRLCAT(curbuf, buf, sizeof(curbuf))do { if ((strlen(curbuf) + strlen(buf)) < (sizeof(curbuf)) ) strcat(curbuf, buf); else return (-2); } while(0); /* append buf */ | ||||
351 | } | ||||
352 | len = strlen(curbuf) + 1; | ||||
353 | s = (char *) XpmMalloc(len)malloc((len)); | ||||
354 | if (!s) { | ||||
355 | xpmFreeColorTable(colorTable, ncolors); | ||||
356 | return (XpmNoMemory-3); | ||||
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 (XpmSuccess0); | ||||
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((void*)0); /* found by Egbert Eich */ | ||||
381 | unsigned int a, x, y; | ||||
382 | |||||
383 | if ((height > 0 && width >= UINT_MAX(2147483647 *2U +1U) / height) || | ||||
| |||||
| |||||
384 | width * height >= UINT_MAX(2147483647 *2U +1U) / sizeof(unsigned int)) | ||||
385 | return XpmNoMemory-3; | ||||
386 | #ifndef FOR_MSW | ||||
387 | iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height)malloc((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)malloc(((long) sizeof(unsigned int) * (long) width * (long) height )); | ||||
396 | #endif | ||||
397 | if (!iptr2) | ||||
398 | return (XpmNoMemory-3); | ||||
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)free(iptr2); /* found by Egbert Eich */ | ||||
411 | return (XpmFileInvalid-2); | ||||
412 | } | ||||
413 | |||||
414 | bzero((char *)colidx, 256 * sizeof(short))memset((char *)colidx,0,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)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); | ||||
422 | |||||
423 | if (c > 0 && c < 256 && colidx[c] != 0) | ||||
424 | *iptr = colidx[c] - 1; | ||||
425 | else { | ||||
426 | XpmFree(iptr2)free(iptr2); | ||||
427 | return (XpmFileInvalid-2); | ||||
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_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0) \ | ||||
440 | do \ | ||||
441 | { \ | ||||
442 | int f; for (f = 0; f < 256; f++) \ | ||||
443 | if (cidx[f]) XpmFree(cidx[f])free(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 *))memset((char *)cidx,0,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((void*)0)) { /* get new memory */ | ||||
454 | cidx[char1] = (unsigned short *) | ||||
455 | XpmCalloc(256, sizeof(unsigned short))calloc((256), (sizeof(unsigned short))); | ||||
456 | if (cidx[char1] == NULL((void*)0)) { /* new block failed */ | ||||
457 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | ||||
458 | XpmFree(iptr2)free(iptr2); | ||||
459 | return (XpmNoMemory-3); | ||||
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)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); | ||||
469 | if (cc1 > 0 && cc1 < 256) { | ||||
470 | int cc2 = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); | ||||
471 | if (cc2 > 0 && cc2 < 256 && | ||||
472 | cidx[cc1] && cidx[cc1][cc2] != 0) | ||||
473 | *iptr = cidx[cc1][cc2] - 1; | ||||
474 | else { | ||||
475 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | ||||
476 | XpmFree(iptr2)free(iptr2); | ||||
477 | return (XpmFileInvalid-2); | ||||
478 | } | ||||
479 | } else { | ||||
480 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | ||||
481 | XpmFree(iptr2)free(iptr2); | ||||
482 | return (XpmFileInvalid-2); | ||||
483 | } | ||||
484 | } | ||||
485 | } | ||||
486 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | ||||
487 | } | ||||
488 | break; | ||||
489 | |||||
490 | default: /* Non-optimized case of long color | ||||
491 | * names */ | ||||
492 | { | ||||
493 | char *s; | ||||
494 | char buf[BUFSIZ8192]; | ||||
495 | |||||
496 | if (cpp >= sizeof(buf)) { | ||||
497 | XpmFree(iptr2)free(iptr2); /* found by Egbert Eich */ | ||||
498 | return (XpmFileInvalid-2); | ||||
499 | } | ||||
500 | |||||
501 | buf[cpp] = '\0'; | ||||
502 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | ||||
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)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); /* int assigned to char, not a problem here */ | ||||
510 | slot = xpmHashSlot(hashtable, buf); | ||||
511 | if (!*slot) { /* no color matches */ | ||||
512 | XpmFree(iptr2)free(iptr2); | ||||
513 | return (XpmFileInvalid-2); | ||||
514 | } | ||||
515 | *iptr = HashColorIndex(slot)((unsigned long)((*slot)->data)); | ||||
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)((!data->type || data->type == 3) ? (*data->cptr++) : (_IO_getc (data->stream.file))); /* 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)free(iptr2); | ||||
529 | return (XpmFileInvalid-2); | ||||
530 | } | ||||
531 | *iptr = a; | ||||
532 | } | ||||
533 | } | ||||
534 | } | ||||
535 | } | ||||
536 | break; | ||||
537 | } | ||||
538 | *pixels = iptr2; | ||||
539 | return (XpmSuccess0); | ||||
540 | } | ||||
541 | |||||
542 | int | ||||
543 | xpmParseExtensions( | ||||
544 | xpmData *data, | ||||
545 | XpmExtension **extensions, | ||||
546 | unsigned int *nextensions) | ||||
547 | { | ||||
548 | XpmExtension *exts = NULL((void*)0), *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))malloc((sizeof(XpmExtension))); | ||||
556 | /* get the whole string */ | ||||
557 | status = xpmGetString(data, &string, &l); | ||||
558 | if (status != XpmSuccess0) { | ||||
559 | XpmFree(exts)free(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)free(string); | ||||
566 | xpmNextString(data); | ||||
567 | status = xpmGetString(data, &string, &l); | ||||
568 | if (status != XpmSuccess0) { | ||||
569 | XpmFree(exts)free(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))realloc((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)free(string); | ||||
581 | XpmFreeExtensions(exts, num); | ||||
582 | return (XpmNoMemory-3); | ||||
583 | } | ||||
584 | exts = ext; | ||||
585 | ext += num; | ||||
586 | /* skip whitespace and store its name */ | ||||
587 | s2 = s = string + 6; | ||||
588 | while (isspace(*s2)((*__ctype_b_loc ())[(int) ((*s2))] & (unsigned short int ) _ISspace)) | ||||
589 | s2++; | ||||
590 | a = s2 - s; | ||||
591 | ext->name = (char *) XpmMalloc(l - a - 6)malloc((l - a - 6)); | ||||
592 | if (!ext->name) { | ||||
593 | XpmFree(string)free(string); | ||||
594 | ext->lines = NULL((void*)0); | ||||
595 | ext->nlines = 0; | ||||
596 | XpmFreeExtensions(exts, num + 1); | ||||
597 | return (XpmNoMemory-3); | ||||
598 | } | ||||
599 | strncpy(ext->name, s + a, l - a - 6); | ||||
600 | XpmFree(string)free(string); | ||||
601 | /* now store the related lines */ | ||||
602 | xpmNextString(data); | ||||
603 | status = xpmGetString(data, &string, &l); | ||||
604 | if (status != XpmSuccess0) { | ||||
605 | ext->lines = NULL((void*)0); | ||||
606 | ext->nlines = 0; | ||||
607 | XpmFreeExtensions(exts, num + 1); | ||||
608 | return (status); | ||||
609 | } | ||||
610 | ext->lines = (char **) XpmMalloc(sizeof(char *))malloc((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 *))realloc((ext->lines), ((nlines + 1) * sizeof(char *))); /* can we iterate enough for a wrapping? */ | ||||
616 | if (!sp) { | ||||
617 | XpmFree(string)free(string); | ||||
618 | ext->nlines = nlines; | ||||
619 | XpmFreeExtensions(exts, num + 1); | ||||
620 | return (XpmNoMemory-3); | ||||
621 | } | ||||
622 | ext->lines = sp; | ||||
623 | ext->lines[nlines] = string; | ||||
624 | nlines++; | ||||
625 | xpmNextString(data); | ||||
626 | status = xpmGetString(data, &string, &l); | ||||
627 | if (status != XpmSuccess0) { | ||||
628 | ext->nlines = nlines; | ||||
629 | XpmFreeExtensions(exts, num + 1); | ||||
630 | return (status); | ||||
631 | } | ||||
632 | } | ||||
633 | if (!nlines) { | ||||
634 | XpmFree(ext->lines)free(ext->lines); | ||||
635 | ext->lines = NULL((void*)0); | ||||
636 | } | ||||
637 | ext->nlines = nlines; | ||||
638 | num++; | ||||
639 | } | ||||
640 | if (!num) { | ||||
641 | XpmFree(string)free(string); | ||||
642 | XpmFree(exts)free(exts); | ||||
643 | exts = NULL((void*)0); | ||||
644 | } else if (!notend) | ||||
645 | XpmFree(string)free(string); | ||||
646 | *nextensions = num; | ||||
647 | *extensions = exts; | ||||
648 | return (XpmSuccess0); | ||||
649 | } | ||||
650 | |||||
651 | |||||
652 | /* function call in case of error */ | ||||
653 | #undef RETURN | ||||
654 | #define RETURN(status)do { goto error; } while(0) \ | ||||
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((void*)0); | ||||
673 | unsigned int *pixelindex = NULL((void*)0); | ||||
674 | char *hints_cmt = NULL((void*)0); | ||||
675 | char *colors_cmt = NULL((void*)0); | ||||
676 | char *pixels_cmt = NULL((void*)0); | ||||
677 | |||||
678 | unsigned int cmts; | ||||
679 | int ErrorStatus; | ||||
680 | xpmHashTable hashtable; | ||||
681 | |||||
682 | cmts = info && (info->valuemask & XpmReturnComments(1L<<8)); | ||||
683 | |||||
684 | /* | ||||
685 | * parse the header | ||||
686 | */ | ||||
687 | ErrorStatus = xpmParseHeader(data); | ||||
688 | if (ErrorStatus != XpmSuccess0) | ||||
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 != XpmSuccess0) | ||||
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(cpp > 2 && ncolors > 4)) { | ||||
710 | ErrorStatus = xpmHashTableInit(&hashtable); | ||||
711 | if (ErrorStatus != XpmSuccess0) | ||||
712 | RETURN(ErrorStatus)do { goto error; } while(0); | ||||
713 | } | ||||
714 | |||||
715 | /* | ||||
716 | * read colors | ||||
717 | */ | ||||
718 | ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); | ||||
719 | if (ErrorStatus != XpmSuccess0) { | ||||
720 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) | ||||
721 | xpmHashTableFree(&hashtable); | ||||
722 | RETURN(ErrorStatus)do { goto error; } while(0); | ||||
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(cpp > 2 && ncolors > 4)) | ||||
741 | xpmHashTableFree(&hashtable); | ||||
742 | |||||
743 | if (ErrorStatus != XpmSuccess0) | ||||
744 | RETURN(ErrorStatus)do { goto error; } while(0); | ||||
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(1L<<10))) { | ||||
756 | if (extensions) { | ||||
757 | ErrorStatus = xpmParseExtensions(data, &info->extensions, | ||||
758 | &info->nextensions); | ||||
759 | if (ErrorStatus != XpmSuccess0) | ||||
760 | RETURN(ErrorStatus)do { goto error; } while(0); | ||||
761 | } else { | ||||
762 | info->extensions = NULL((void*)0); | ||||
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(1L<<4); | ||||
787 | } | ||||
788 | } | ||||
789 | return (XpmSuccess0); | ||||
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)free(pixelindex); | ||||
797 | if (hints_cmt) | ||||
798 | XpmFree(hints_cmt)free(hints_cmt); | ||||
799 | if (colors_cmt) | ||||
800 | XpmFree(colors_cmt)free(colors_cmt); | ||||
801 | if (pixels_cmt) | ||||
802 | XpmFree(pixels_cmt)free(pixels_cmt); | ||||
803 | |||||
804 | return(ErrorStatus); | ||||
805 | } |