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