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