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