Back to index

plt-scheme  4.2.1
parse.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1989-95 GROUPE BULL
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to
00006  * deal in the Software without restriction, including without limitation the
00007  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00008  * sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00017  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00018  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00019  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00020  *
00021  * Except as contained in this notice, the name of GROUPE BULL shall not be
00022  * used in advertising or otherwise to promote the sale, use or other dealings
00023  * in this Software without prior written authorization from GROUPE BULL.
00024  */
00025 
00026 /*****************************************************************************\
00027 * parse.c:                                                                    *
00028 *                                                                             *
00029 *  XPM library                                                                *
00030 *  Parse an XPM file or array and store the found informations                *
00031 *  in the given XpmImage structure.                                           *
00032 *                                                                             *
00033 *  Developed by Arnaud Le Hors                                                *
00034 \*****************************************************************************/
00035 
00036 /*
00037  * The code related to FOR_MSW has been added by
00038  * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
00039  */
00040 
00041 #include "xpmP.h"
00042 #include <ctype.h>
00043 #if defined(SYSV) || defined(SVR4) || defined(VMS) || defined(__GNUC__)
00044 #include <string.h>
00045 #else
00046 #include <strings.h>
00047 #endif
00048 
00049 LFUNC(ParseValues, int, (xpmData *data, unsigned int *width,
00050                       unsigned int *height, unsigned int *ncolors,
00051                       unsigned int *cpp, unsigned int *x_hotspot,
00052                       unsigned int *y_hotspot, unsigned int *hotspot,
00053                       unsigned int *extensions));
00054 
00055 LFUNC(ParseColors, int, (xpmData *data, unsigned int ncolors, unsigned int cpp,
00056                       XpmColor **colorTablePtr, xpmHashTable *hashtable));
00057 
00058 LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
00059                       unsigned int height, unsigned int ncolors,
00060                       unsigned int cpp, XpmColor *colorTable,
00061                       xpmHashTable *hashtable, unsigned int **pixels));
00062 
00063 LFUNC(ParseExtensions, int, (xpmData *data, XpmExtension **extensions,
00064                           unsigned int *nextensions));
00065 
00066 char *xpmColorKeys[] = {
00067     "s",                           /* key #1: symbol */
00068     "m",                           /* key #2: mono visual */
00069     "g4",                          /* key #3: 4 grays visual */
00070     "g",                           /* key #4: gray visual */
00071     "c",                           /* key #5: color visual */
00072 };
00073 
00074 
00075 /* function call in case of error, frees only locally allocated variables */
00076 #undef RETURN
00077 #define RETURN(status) \
00078 { \
00079     if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
00080     if (pixelindex) XpmFree(pixelindex); \
00081     if (hints_cmt)  XpmFree(hints_cmt); \
00082     if (colors_cmt) XpmFree(colors_cmt); \
00083     if (pixels_cmt) XpmFree(pixels_cmt); \
00084     return(status); \
00085 }
00086 
00087 /*
00088  * This function parses an Xpm file or data and store the found informations
00089  * in an an XpmImage structure which is returned.
00090  */
00091 int
00092 xpmParseData(data, image, info)
00093     xpmData *data;
00094     XpmImage *image;
00095     XpmInfo *info;
00096 {
00097     /* variables to return */
00098     unsigned int width, height, ncolors, cpp;
00099     unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
00100     XpmColor *colorTable = NULL;
00101     unsigned int *pixelindex = NULL;
00102     char *hints_cmt = NULL;
00103     char *colors_cmt = NULL;
00104     char *pixels_cmt = NULL;
00105 
00106     unsigned int cmts;
00107     int ErrorStatus;
00108     xpmHashTable hashtable;
00109 
00110     cmts = info && (info->valuemask & XpmReturnComments);
00111 
00112     /*
00113      * parse the header
00114      */
00115     ErrorStatus = xpmParseHeader(data);
00116     if (ErrorStatus != XpmSuccess)
00117        return (ErrorStatus);
00118 
00119     /*
00120      * read values
00121      */
00122     ErrorStatus = ParseValues(data, &width, &height, &ncolors, &cpp,
00123                          &x_hotspot, &y_hotspot, &hotspot, &extensions);
00124     if (ErrorStatus != XpmSuccess)
00125        return (ErrorStatus);
00126 
00127     /*
00128      * store the hints comment line
00129      */
00130     if (cmts)
00131        xpmGetCmt(data, &hints_cmt);
00132 
00133     /*
00134      * init the hastable
00135      */
00136     if (USE_HASHTABLE) {
00137        ErrorStatus = xpmHashTableInit(&hashtable);
00138        if (ErrorStatus != XpmSuccess)
00139            return (ErrorStatus);
00140     }
00141 
00142     /*
00143      * read colors
00144      */
00145     ErrorStatus = ParseColors(data, ncolors, cpp, &colorTable, &hashtable);
00146     if (ErrorStatus != XpmSuccess) {
00147        if (USE_HASHTABLE)
00148            xpmHashTableFree(&hashtable);
00149        RETURN(ErrorStatus);
00150     }
00151 
00152     /*
00153      * store the colors comment line
00154      */
00155     if (cmts)
00156        xpmGetCmt(data, &colors_cmt);
00157 
00158     /*
00159      * read pixels and index them on color number
00160      */
00161     ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
00162                            &hashtable, &pixelindex);
00163 
00164     /*
00165      * free the hastable
00166      */
00167     if (USE_HASHTABLE)
00168        xpmHashTableFree(&hashtable);
00169 
00170     if (ErrorStatus != XpmSuccess)
00171        RETURN(ErrorStatus);
00172 
00173     /*
00174      * store the pixels comment line
00175      */
00176     if (cmts)
00177        xpmGetCmt(data, &pixels_cmt);
00178 
00179     /*
00180      * parse extensions
00181      */
00182     if (info && (info->valuemask & XpmReturnExtensions))
00183        if (extensions) {
00184            ErrorStatus = ParseExtensions(data, &info->extensions,
00185                                      &info->nextensions);
00186            if (ErrorStatus != XpmSuccess)
00187               RETURN(ErrorStatus);
00188        } else {
00189            info->extensions = NULL;
00190            info->nextensions = 0;
00191        }
00192 
00193     /*
00194      * store found informations in the XpmImage structure
00195      */
00196     image->width = width;
00197     image->height = height;
00198     image->cpp = cpp;
00199     image->ncolors = ncolors;
00200     image->colorTable = colorTable;
00201     image->data = pixelindex;
00202 
00203     if (info) {
00204        if (cmts) {
00205            info->hints_cmt = hints_cmt;
00206            info->colors_cmt = colors_cmt;
00207            info->pixels_cmt = pixels_cmt;
00208        }
00209        if (hotspot) {
00210            info->x_hotspot = x_hotspot;
00211            info->y_hotspot = y_hotspot;
00212            info->valuemask |= XpmHotspot;
00213        }
00214     }
00215     return (XpmSuccess);
00216 }
00217 
00218 static int
00219 ParseValues(data, width, height, ncolors, cpp,
00220            x_hotspot, y_hotspot, hotspot, extensions)
00221     xpmData *data;
00222     unsigned int *width, *height, *ncolors, *cpp;
00223     unsigned int *x_hotspot, *y_hotspot, *hotspot;
00224     unsigned int *extensions;
00225 {
00226     unsigned int l;
00227     char buf[BUFSIZ];
00228 
00229     if (!data->format) {           /* XPM 2 or 3 */
00230 
00231        /*
00232         * read values: width, height, ncolors, chars_per_pixel
00233         */
00234        if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
00235              && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
00236            return (XpmFileInvalid);
00237 
00238        /*
00239         * read optional information (hotspot and/or XPMEXT) if any
00240         */
00241        l = xpmNextWord(data, buf, BUFSIZ);
00242        if (l) {
00243            *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
00244            if (*extensions)
00245               *hotspot = (xpmNextUI(data, x_hotspot)
00246                          && xpmNextUI(data, y_hotspot));
00247            else {
00248               *hotspot = (xpmatoui(buf, l, x_hotspot)
00249                          && xpmNextUI(data, y_hotspot));
00250               l = xpmNextWord(data, buf, BUFSIZ);
00251               *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
00252            }
00253        }
00254     } else {
00255 
00256        /*
00257         * XPM 1 file read values: width, height, ncolors, chars_per_pixel
00258         */
00259        int i;
00260        char *ptr;
00261        Bool got_one, saw_width = False, saw_height = False;
00262        Bool saw_ncolors = False, saw_chars_per_pixel = False;
00263 
00264        for (i = 0; i < 4; i++) {
00265            l = xpmNextWord(data, buf, BUFSIZ);
00266            if (l != 7 || strncmp("#define", buf, 7))
00267               return (XpmFileInvalid);
00268            l = xpmNextWord(data, buf, BUFSIZ);
00269            if (!l)
00270               return (XpmFileInvalid);
00271            buf[l] = '\0';
00272            ptr = buf;
00273            got_one = False;
00274            while (!got_one) {
00275               ptr = index(ptr, '_');
00276               if (!ptr)
00277                   return (XpmFileInvalid);
00278               switch (l - (ptr - buf)) {
00279               case 6:
00280                   if (saw_width || strncmp("_width", ptr, 6)
00281                      || !xpmNextUI(data, width))
00282                      return (XpmFileInvalid);
00283                   else
00284                      saw_width = True;
00285                   got_one = True;
00286                   break;
00287               case 7:
00288                   if (saw_height || strncmp("_height", ptr, 7)
00289                      || !xpmNextUI(data, height))
00290                      return (XpmFileInvalid);
00291                   else
00292                      saw_height = True;
00293                   got_one = True;
00294                   break;
00295               case 8:
00296                   if (saw_ncolors || strncmp("_ncolors", ptr, 8)
00297                      || !xpmNextUI(data, ncolors))
00298                      return (XpmFileInvalid);
00299                   else
00300                      saw_ncolors = True;
00301                   got_one = True;
00302                   break;
00303               case 16:
00304                   if (saw_chars_per_pixel
00305                      || strncmp("_chars_per_pixel", ptr, 16)
00306                      || !xpmNextUI(data, cpp))
00307                      return (XpmFileInvalid);
00308                   else
00309                      saw_chars_per_pixel = True;
00310                   got_one = True;
00311                   break;
00312               default:
00313                   ptr++;
00314               }
00315            }
00316            /* skip the end of line */
00317            xpmNextString(data);
00318        }
00319        if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel)
00320          return (XpmFileInvalid);
00321 
00322        *hotspot = 0;
00323        *extensions = 0;
00324     }
00325     return (XpmSuccess);
00326 }
00327 
00328 static int
00329 ParseColors(data, ncolors, cpp, colorTablePtr, hashtable)
00330     xpmData *data;
00331     unsigned int ncolors;
00332     unsigned int cpp;
00333     XpmColor **colorTablePtr;
00334     xpmHashTable *hashtable;
00335 {
00336     unsigned int key, l, a, b;
00337     unsigned int curkey;           /* current color key */
00338     unsigned int lastwaskey;              /* key read */
00339     char buf[BUFSIZ];
00340     char curbuf[BUFSIZ];           /* current buffer */
00341     char **sptr, *s;
00342     XpmColor *color;
00343     XpmColor *colorTable;
00344     char **defaults;
00345     int ErrorStatus;
00346 
00347     colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor));
00348     if (!colorTable)
00349        return (XpmNoMemory);
00350 
00351     if (!data->format) {           /* XPM 2 or 3 */
00352        for (a = 0, color = colorTable; a < ncolors; a++, color++) {
00353            xpmNextString(data);    /* skip the line */
00354 
00355            /*
00356             * read pixel value
00357             */
00358            color->string = (char *) XpmMalloc(cpp + 1);
00359            if (!color->string) {
00360               xpmFreeColorTable(colorTable, ncolors);
00361               return (XpmNoMemory);
00362            }
00363            for (b = 0, s = color->string; b < cpp; b++, s++)
00364               *s = xpmGetC(data);
00365            *s = '\0';
00366 
00367            /*
00368             * store the string in the hashtable with its color index number
00369             */
00370            if (USE_HASHTABLE) {
00371               ErrorStatus =
00372                   xpmHashIntern(hashtable, color->string, HashAtomData(a));
00373               if (ErrorStatus != XpmSuccess) {
00374                   xpmFreeColorTable(colorTable, ncolors);
00375                   return (ErrorStatus);
00376               }
00377            }
00378 
00379            /*
00380             * read color keys and values
00381             */
00382            defaults = (char **) color;
00383            curkey = 0;
00384            lastwaskey = 0;
00385            *curbuf = '\0';         /* init curbuf */
00386            while (l = xpmNextWord(data, buf, BUFSIZ)) {
00387               if (!lastwaskey) {
00388                   for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++,
00389                       sptr++)
00390                      if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
00391                          break;
00392               }
00393               if (!lastwaskey && key < NKEYS) {  /* open new key */
00394                   if (curkey) {    /* flush string */
00395                      s = (char *) XpmMalloc(strlen(curbuf) + 1);
00396                      if (!s) {
00397                          xpmFreeColorTable(colorTable, ncolors);
00398                          return (XpmNoMemory);
00399                      }
00400                      defaults[curkey] = s;
00401                      strcpy(s, curbuf);
00402                   }
00403                   curkey = key + 1;       /* set new key  */
00404                   *curbuf = '\0';  /* reset curbuf */
00405                   lastwaskey = 1;
00406               } else {
00407                   if (!curkey) {   /* key without value */
00408                      xpmFreeColorTable(colorTable, ncolors);
00409                      return (XpmFileInvalid);
00410                   }
00411                   if (!lastwaskey)
00412                      strcat(curbuf, " "); /* append space */
00413                   buf[l] = '\0';
00414                   strcat(curbuf, buf);/* append buf */
00415                   lastwaskey = 0;
00416               }
00417            }
00418            if (!curkey) {          /* key without value */
00419               xpmFreeColorTable(colorTable, ncolors);
00420               return (XpmFileInvalid);
00421            }
00422            s = defaults[curkey] = (char *) XpmMalloc(strlen(curbuf) + 1);
00423            if (!s) {
00424               xpmFreeColorTable(colorTable, ncolors);
00425               return (XpmNoMemory);
00426            }
00427            strcpy(s, curbuf);
00428        }
00429     } else {                       /* XPM 1 */
00430        /* get to the beginning of the first string */
00431        data->Bos = '"';
00432        data->Eos = '\0';
00433        xpmNextString(data);
00434        data->Eos = '"';
00435        for (a = 0, color = colorTable; a < ncolors; a++, color++) {
00436 
00437            /*
00438             * read pixel value
00439             */
00440            color->string = (char *) XpmMalloc(cpp + 1);
00441            if (!color->string) {
00442               xpmFreeColorTable(colorTable, ncolors);
00443               return (XpmNoMemory);
00444            }
00445            for (b = 0, s = color->string; b < cpp; b++, s++)
00446               *s = xpmGetC(data);
00447            *s = '\0';
00448 
00449            /*
00450             * store the string in the hashtable with its color index number
00451             */
00452            if (USE_HASHTABLE) {
00453               ErrorStatus =
00454                   xpmHashIntern(hashtable, color->string, HashAtomData(a));
00455               if (ErrorStatus != XpmSuccess) {
00456                   xpmFreeColorTable(colorTable, ncolors);
00457                   return (ErrorStatus);
00458               }
00459            }
00460 
00461            /*
00462             * read color values
00463             */
00464            xpmNextString(data);    /* get to the next string */
00465            *curbuf = '\0';         /* init curbuf */
00466            while (l = xpmNextWord(data, buf, BUFSIZ)) {
00467               if (*curbuf != '\0')
00468                   strcat(curbuf, " ");/* append space */
00469               buf[l] = '\0';
00470               strcat(curbuf, buf); /* append buf */
00471            }
00472            s = (char *) XpmMalloc(strlen(curbuf) + 1);
00473            if (!s) {
00474               xpmFreeColorTable(colorTable, ncolors);
00475               return (XpmNoMemory);
00476            }
00477            strcpy(s, curbuf);
00478            color->c_color = s;
00479            *curbuf = '\0';         /* reset curbuf */
00480            if (a < ncolors - 1)
00481               xpmNextString(data); /* get to the next string */
00482        }
00483     }
00484     *colorTablePtr = colorTable;
00485     return (XpmSuccess);
00486 }
00487 
00488 static int
00489 ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
00490     xpmData *data;
00491     unsigned int width;
00492     unsigned int height;
00493     unsigned int ncolors;
00494     unsigned int cpp;
00495     XpmColor *colorTable;
00496     xpmHashTable *hashtable;
00497     unsigned int **pixels;
00498 {
00499     unsigned int *iptr, *iptr2;
00500     unsigned int a, x, y;
00501 
00502 #ifndef FOR_MSW
00503     iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height);
00504 #else
00505 
00506     /*
00507      * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
00508      * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
00509      */
00510     iptr2 = (unsigned int *)
00511        XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height);
00512 #endif
00513     if (!iptr2)
00514        return (XpmNoMemory);
00515 
00516     iptr = iptr2;
00517 
00518     switch (cpp) {
00519 
00520     case (1):                      /* Optimize for single character
00521                                     * colors */
00522        {
00523            unsigned short colidx[256];
00524 
00525            bzero(colidx, 256 * sizeof(short));
00526            for (a = 0; a < ncolors; a++)
00527               colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
00528 
00529            for (y = 0; y < height; y++) {
00530               xpmNextString(data);
00531               for (x = 0; x < width; x++, iptr++) {
00532                   int c = xpmGetC(data);
00533 
00534                   if (c > 0 && c < 256 && colidx[c] != 0)
00535                      *iptr = colidx[c] - 1;
00536                   else {
00537                      XpmFree(iptr2);
00538                      return (XpmFileInvalid);
00539                   }
00540               }
00541            }
00542        }
00543        break;
00544 
00545     case (2):                      /* Optimize for double character
00546                                     * colors */
00547        {
00548 
00549 /* free all allocated pointers at all exits */
00550 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
00551 if (cidx[f]) XpmFree(cidx[f]);}
00552 
00553            /* array of pointers malloced by need */
00554            unsigned short *cidx[256];
00555            int char1;
00556 
00557            bzero(cidx, 256 * sizeof(unsigned short *)); /* init */
00558            for (a = 0; a < ncolors; a++) {
00559               char1 = colorTable[a].string[0];
00560               if (cidx[char1] == NULL) { /* get new memory */
00561                   cidx[char1] = (unsigned short *)
00562                      XpmCalloc(256, sizeof(unsigned short));
00563                   if (cidx[char1] == NULL) { /* new block failed */
00564                      FREE_CIDX;
00565                      XpmFree(iptr2);
00566                      return (XpmNoMemory);
00567                   }
00568               }
00569               cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
00570            }
00571 
00572            for (y = 0; y < height; y++) {
00573               xpmNextString(data);
00574               for (x = 0; x < width; x++, iptr++) {
00575                   int cc1 = xpmGetC(data);
00576                   if (cc1 > 0 && cc1 < 256) {
00577                      int cc2 = xpmGetC(data);
00578                      if (cc2 > 0 && cc2 < 256 && cidx[cc1][cc2] != 0)
00579                          *iptr = cidx[cc1][cc2] - 1;
00580                      else {
00581                          FREE_CIDX;
00582                          XpmFree(iptr2);
00583                          return (XpmFileInvalid);
00584                      }
00585                   } else {
00586                      FREE_CIDX;
00587                      XpmFree(iptr2);
00588                      return (XpmFileInvalid);
00589                   }
00590               }
00591            }
00592            FREE_CIDX;
00593        }
00594        break;
00595 
00596     default:                       /* Non-optimized case of long color
00597                                     * names */
00598        {
00599            char *s;
00600            char buf[BUFSIZ];
00601 
00602            buf[cpp] = '\0';
00603            if (USE_HASHTABLE) {
00604               xpmHashAtom *slot;
00605 
00606               for (y = 0; y < height; y++) {
00607                   xpmNextString(data);
00608                   for (x = 0; x < width; x++, iptr++) {
00609                      for (a = 0, s = buf; a < cpp; a++, s++)
00610                          *s = xpmGetC(data);
00611                      slot = xpmHashSlot(hashtable, buf);
00612                      if (!*slot) { /* no color matches */
00613                          XpmFree(iptr2);
00614                          return (XpmFileInvalid);
00615                      }
00616                      *iptr = HashColorIndex(slot);
00617                   }
00618               }
00619            } else {
00620               for (y = 0; y < height; y++) {
00621                   xpmNextString(data);
00622                   for (x = 0; x < width; x++, iptr++) {
00623                      for (a = 0, s = buf; a < cpp; a++, s++)
00624                          *s = xpmGetC(data);
00625                      for (a = 0; a < ncolors; a++)
00626                          if (!strcmp(colorTable[a].string, buf))
00627                             break;
00628                      if (a == ncolors) {  /* no color matches */
00629                          XpmFree(iptr2);
00630                          return (XpmFileInvalid);
00631                      }
00632                      *iptr = a;
00633                   }
00634               }
00635            }
00636        }
00637        break;
00638     }
00639     *pixels = iptr2;
00640     return (XpmSuccess);
00641 }
00642 
00643 static int
00644 ParseExtensions(data, extensions, nextensions)
00645     xpmData *data;
00646     XpmExtension **extensions;
00647     unsigned int *nextensions;
00648 {
00649     XpmExtension *exts = NULL, *ext;
00650     unsigned int num = 0;
00651     unsigned int nlines, a, l, notstart, notend = 0;
00652     int status;
00653     char *string, *s, *s2, **sp;
00654 
00655     xpmNextString(data);
00656     exts = (XpmExtension *) XpmMalloc(sizeof(XpmExtension));
00657     /* get the whole string */
00658     status = xpmGetString(data, &string, &l);
00659     if (status != XpmSuccess) {
00660        XpmFree(exts);
00661        return (status);
00662     }
00663     /* look for the key word XPMEXT, skip lines before this */
00664     while ((notstart = strncmp("XPMEXT", string, 6))
00665           && (notend = strncmp("XPMENDEXT", string, 9))) {
00666        XpmFree(string);
00667        xpmNextString(data);
00668        status = xpmGetString(data, &string, &l);
00669        if (status != XpmSuccess) {
00670            XpmFree(exts);
00671            return (status);
00672        }
00673     }
00674     if (!notstart)
00675        notend = strncmp("XPMENDEXT", string, 9);
00676     while (!notstart && notend) {
00677        /* there starts an extension */
00678        ext = (XpmExtension *)
00679            XpmRealloc(exts, (num + 1) * sizeof(XpmExtension));
00680        if (!ext) {
00681            XpmFree(string);
00682            XpmFreeExtensions(exts, num);
00683            return (XpmNoMemory);
00684        }
00685        exts = ext;
00686        ext += num;
00687        /* skip whitespace and store its name */
00688        s2 = s = string + 6;
00689        while (isspace(*s2))
00690            s2++;
00691        a = s2 - s;
00692        ext->name = (char *) XpmMalloc(l - a - 6);
00693        if (!ext->name) {
00694            XpmFree(string);
00695            ext->lines = NULL;
00696            ext->nlines = 0;
00697            XpmFreeExtensions(exts, num + 1);
00698            return (XpmNoMemory);
00699        }
00700        strncpy(ext->name, s + a, l - a - 6);
00701        XpmFree(string);
00702        /* now store the related lines */
00703        xpmNextString(data);
00704        status = xpmGetString(data, &string, &l);
00705        if (status != XpmSuccess) {
00706            ext->lines = NULL;
00707            ext->nlines = 0;
00708            XpmFreeExtensions(exts, num + 1);
00709            return (status);
00710        }
00711        ext->lines = (char **) XpmMalloc(sizeof(char *));
00712        nlines = 0;
00713        while ((notstart = strncmp("XPMEXT", string, 6))
00714               && (notend = strncmp("XPMENDEXT", string, 9))) {
00715            sp = (char **)
00716               XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *));
00717            if (!sp) {
00718               XpmFree(string);
00719               ext->nlines = nlines;
00720               XpmFreeExtensions(exts, num + 1);
00721               return (XpmNoMemory);
00722            }
00723            ext->lines = sp;
00724            ext->lines[nlines] = string;
00725            nlines++;
00726            xpmNextString(data);
00727            status = xpmGetString(data, &string, &l);
00728            if (status != XpmSuccess) {
00729               ext->nlines = nlines;
00730               XpmFreeExtensions(exts, num + 1);
00731               return (status);
00732            }
00733        }
00734        if (!nlines) {
00735            XpmFree(ext->lines);
00736            ext->lines = NULL;
00737        }
00738        ext->nlines = nlines;
00739        num++;
00740     }
00741     if (!num) {
00742        XpmFree(string);
00743        XpmFree(exts);
00744        exts = NULL;
00745     } else if (!notend)
00746        XpmFree(string);
00747     *nextensions = num;
00748     *extensions = exts;
00749     return (XpmSuccess);
00750 }