parse.c revision 97cf2ee2
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 73const 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 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 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 369static int 370ParsePixels( 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 \ 440do \ 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 542int 543xpmParseExtensions( 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) \ 655do { \ 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 */ 663int 664xpmParseData( 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 */ 792error: 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} 806