Back to index

plt-scheme  4.2.1
data.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 * data.c:                                                                     *
00028 *                                                                             *
00029 *  XPM library                                                                *
00030 *  IO utilities                                                               *
00031 *                                                                             *
00032 *  Developed by Arnaud Le Hors                                                *
00033 \*****************************************************************************/
00034 
00035 /* Official version number */
00036 static char *RCS_Version = "$XpmVersion: 3.4g $";
00037 
00038 /* Internal version number */
00039 
00040 #include "xpmP.h"
00041 #include <ctype.h>
00042 #if defined(SYSV) || defined(SVR4) || defined(VMS) || defined(__GNUC__)
00043 #include <string.h>
00044 #else
00045 #include <strings.h>
00046 #endif
00047 
00048 
00049 LFUNC(ParseComment, int, (xpmData * mdata));
00050 
00051 static int
00052 ParseComment(mdata)
00053     xpmData *mdata;
00054 {
00055     if (mdata->type == XPMBUFFER) {
00056        register char c;
00057        register unsigned int n = 0;
00058        unsigned int notend;
00059        char *s, *s2;
00060 
00061        s = mdata->Comment;
00062        *s = mdata->Bcmt[0];
00063 
00064        /* skip the string beginning comment */
00065        s2 = mdata->Bcmt;
00066        do {
00067            c = *mdata->cptr++;
00068            *++s = c;
00069            n++;
00070            s2++;
00071        } while (c == *s2 && *s2 != '\0' && c);
00072 
00073        if (*s2 != '\0') {
00074            /* this wasn't the beginning of a comment */
00075            mdata->cptr -= n;
00076            return 0;
00077        }
00078        /* store comment */
00079        mdata->Comment[0] = *s;
00080        s = mdata->Comment;
00081        notend = 1;
00082        n = 0;
00083        while (notend) {
00084            s2 = mdata->Ecmt;
00085            while (*s != *s2 && c) {
00086               c = *mdata->cptr++;
00087               if (n == XPMMAXCMTLEN - 1)  { /* forget it */
00088                   s = mdata->Comment;
00089                   n = 0;
00090               }
00091               *++s = c;
00092               n++;
00093            }
00094            mdata->CommentLength = n;
00095            do {
00096               c = *mdata->cptr++;
00097               if (n == XPMMAXCMTLEN - 1)  { /* forget it */
00098                   s = mdata->Comment;
00099                   n = 0;
00100               }
00101               *++s = c;
00102               n++;
00103               s2++;
00104            } while (c == *s2 && *s2 != '\0' && c);
00105            if (*s2 == '\0') {
00106               /* this is the end of the comment */
00107               notend = 0;
00108               mdata->cptr--;
00109            }
00110        }
00111        return 0;
00112     } else {
00113        FILE *file = mdata->stream.file;
00114        register int c;
00115        register unsigned int n = 0, a;
00116        unsigned int notend;
00117        char *s, *s2;
00118 
00119        s = mdata->Comment;
00120        *s = mdata->Bcmt[0];
00121 
00122        /* skip the string beginning comment */
00123        s2 = mdata->Bcmt;
00124        do {
00125            c = getc(file);
00126            *++s = c;
00127            n++;
00128            s2++;
00129        } while (c == *s2 && *s2 != '\0' && c != EOF);
00130 
00131        if (*s2 != '\0') {
00132            /* this wasn't the beginning of a comment */
00133            /* put characters back in the order that we got them */
00134            for (a = n; a > 0; a--, s--)
00135               ungetc(*s, file);
00136            return 0;
00137        }
00138        /* store comment */
00139        mdata->Comment[0] = *s;
00140        s = mdata->Comment;
00141        notend = 1;
00142        n = 0;
00143        while (notend) {
00144            s2 = mdata->Ecmt;
00145            while (*s != *s2 && c != EOF) {
00146               c = getc(file);
00147               if (n == XPMMAXCMTLEN - 1)  { /* forget it */
00148                   s = mdata->Comment;
00149                   n = 0;
00150               }
00151               *++s = c;
00152               n++;
00153            }
00154            mdata->CommentLength = n;
00155            do {
00156               c = getc(file);
00157               if (n == XPMMAXCMTLEN - 1)  { /* forget it */
00158                   s = mdata->Comment;
00159                   n = 0;
00160               }
00161               *++s = c;
00162               n++;
00163               s2++;
00164            } while (c == *s2 && *s2 != '\0' && c != EOF);
00165            if (*s2 == '\0') {
00166               /* this is the end of the comment */
00167               notend = 0;
00168               ungetc(*s, file);
00169            }
00170        }
00171        return 0;
00172     }
00173 }
00174 
00175 /*
00176  * skip to the end of the current string and the beginning of the next one
00177  */
00178 int
00179 xpmNextString(mdata)
00180     xpmData *mdata;
00181 {
00182     if (!mdata->type)
00183        mdata->cptr = (mdata->stream.data)[++mdata->line];
00184     else if (mdata->type == XPMBUFFER) {
00185        register char c;
00186 
00187        /* get to the end of the current string */
00188        if (mdata->Eos)
00189            while ((c = *mdata->cptr++) && c != mdata->Eos);
00190 
00191        /*
00192         * then get to the beginning of the next string looking for possible
00193         * comment
00194         */
00195        if (mdata->Bos) {
00196            while ((c = *mdata->cptr++) && c != mdata->Bos)
00197               if (mdata->Bcmt && c == mdata->Bcmt[0])
00198                   ParseComment(mdata);
00199        } else if (mdata->Bcmt) {   /* XPM2 natural */
00200            while ((c = *mdata->cptr++) == mdata->Bcmt[0])
00201               ParseComment(mdata);
00202            mdata->cptr--;
00203        }
00204     } else {
00205        register int c;
00206        FILE *file = mdata->stream.file;
00207 
00208        /* get to the end of the current string */
00209        if (mdata->Eos)
00210            while ((c = getc(file)) != mdata->Eos && c != EOF);
00211 
00212        /*
00213         * then get to the beginning of the next string looking for possible
00214         * comment
00215         */
00216        if (mdata->Bos) {
00217            while ((c = getc(file)) != mdata->Bos && c != EOF)
00218               if (mdata->Bcmt && c == mdata->Bcmt[0])
00219                   ParseComment(mdata);
00220 
00221        } else if (mdata->Bcmt) {   /* XPM2 natural */
00222            while ((c = getc(file)) == mdata->Bcmt[0])
00223               ParseComment(mdata);
00224            ungetc(c, file);
00225        }
00226     }
00227     return 0;
00228 }
00229 
00230 
00231 /*
00232  * skip whitespace and compute the following unsigned int,
00233  * returns 1 if one is found and 0 if not
00234  */
00235 int
00236 xpmNextUI(mdata, ui_return)
00237     xpmData *mdata;
00238     unsigned int *ui_return;
00239 {
00240     char buf[BUFSIZ];
00241     int l;
00242 
00243     l = xpmNextWord(mdata, buf, BUFSIZ);
00244     return xpmatoui(buf, l, ui_return);
00245 }
00246 
00247 /*
00248  * skip whitespace and return the following word
00249  */
00250 unsigned int
00251 xpmNextWord(mdata, buf, buflen)
00252     xpmData *mdata;
00253     char *buf;
00254     unsigned int buflen;
00255 {
00256     register unsigned int n = 0;
00257     int c;
00258 
00259     if (!mdata->type || mdata->type == XPMBUFFER) {
00260        while (isspace(c = *mdata->cptr) && c != mdata->Eos)
00261            mdata->cptr++;
00262        do {
00263            c = *mdata->cptr++;
00264            *buf++ = c;
00265            n++;
00266        } while (!isspace(c) && c != mdata->Eos && n < buflen);
00267        n--;
00268        mdata->cptr--;
00269     } else {
00270        FILE *file = mdata->stream.file;
00271 
00272        while ((c = getc(file)) != EOF && isspace(c) && c != mdata->Eos);
00273        while (!isspace(c) && c != mdata->Eos && c != EOF && n < buflen) {
00274            *buf++ = c;
00275            n++;
00276            c = getc(file);
00277        }
00278        ungetc(c, file);
00279     }
00280     return (n);
00281 }
00282 
00283 /*
00284  * return end of string - WARNING: malloc!
00285  */
00286 int
00287 xpmGetString(mdata, sptr, l)
00288     xpmData *mdata;
00289     char **sptr;
00290     unsigned int *l;
00291 {
00292     unsigned int i, n = 0;
00293     int c;
00294     char *p = NULL, *q, buf[BUFSIZ];
00295 
00296     if (!mdata->type || mdata->type == XPMBUFFER) {
00297        if (mdata->cptr) {
00298            char *start = mdata->cptr;
00299            while ((c = *mdata->cptr) && c != mdata->Eos)
00300               mdata->cptr++;
00301            n = mdata->cptr - start + 1;
00302            p = (char *) XpmMalloc(n);
00303            if (!p)
00304               return (XpmNoMemory);
00305            strncpy(p, start, n);
00306            if (mdata->type)        /* XPMBUFFER */
00307               p[n - 1] = '\0';
00308        }
00309     } else {
00310        FILE *file = mdata->stream.file;
00311 
00312        if ((c = getc(file)) == EOF)
00313            return (XpmFileInvalid);
00314 
00315        i = 0;
00316        q = buf;
00317        p = (char *) XpmMalloc(1);
00318        while (c != mdata->Eos && c != EOF) {
00319            if (i == BUFSIZ) {
00320               /* get to the end of the buffer */
00321               /* malloc needed memory */
00322               q = (char *) XpmRealloc(p, n + i);
00323               if (!q) {
00324                   XpmFree(p);
00325                   return (XpmNoMemory);
00326               }
00327               p = q;
00328               q += n;
00329               /* and copy what we already have */
00330               strncpy(q, buf, i);
00331               n += i;
00332               i = 0;
00333               q = buf;
00334            }
00335            *q++ = c;
00336            i++;
00337            c = getc(file);
00338        }
00339        if (c == EOF) {
00340            XpmFree(p);
00341            return (XpmFileInvalid);
00342        }
00343        if (n + i != 0) {
00344            /* malloc needed memory */
00345            q = (char *) XpmRealloc(p, n + i + 1);
00346            if (!q) {
00347               XpmFree(p);
00348               return (XpmNoMemory);
00349            }
00350            p = q;
00351            q += n;
00352            /* and copy the buffer */
00353            strncpy(q, buf, i);
00354            n += i;
00355            p[n++] = '\0';
00356        } else {
00357            *p = '\0';
00358            n = 1;
00359        }
00360        ungetc(c, file);
00361     }
00362     *sptr = p;
00363     *l = n;
00364     return (XpmSuccess);
00365 }
00366 
00367 /*
00368  * get the current comment line
00369  */
00370 int
00371 xpmGetCmt(mdata, cmt)
00372     xpmData *mdata;
00373     char **cmt;
00374 {
00375     if (!mdata->type)
00376        *cmt = NULL;
00377     else if (mdata->CommentLength) {
00378        *cmt = (char *) XpmMalloc(mdata->CommentLength + 1);
00379        strncpy(*cmt, mdata->Comment, mdata->CommentLength);
00380        (*cmt)[mdata->CommentLength] = '\0';
00381        mdata->CommentLength = 0;
00382     } else
00383        *cmt = NULL;
00384     return 0;
00385 }
00386 
00387 xpmDataType xpmDataTypes[] =
00388 {
00389     "", "!", "\n", '\0', '\n', "", "", "", "",   /* Natural type */
00390     "C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n",
00391     "Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n",
00392 #ifdef VMS
00393     NULL
00394 #else
00395     NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL
00396 #endif
00397 };
00398 
00399 /*
00400  * parse xpm header
00401  */
00402 int
00403 xpmParseHeader(mdata)
00404     xpmData *mdata;
00405 {
00406     char buf[BUFSIZ];
00407     int l, n = 0;
00408 
00409     if (mdata->type) {
00410        mdata->Bos = '\0';
00411        mdata->Eos = '\n';
00412        mdata->Bcmt = mdata->Ecmt = NULL;
00413        l = xpmNextWord(mdata, buf, BUFSIZ);
00414        if (l == 7 && !strncmp("#define", buf, 7)) {
00415            /* this maybe an XPM 1 file */
00416            char *ptr;
00417 
00418            l = xpmNextWord(mdata, buf, BUFSIZ);
00419            if (!l)
00420               return (XpmFileInvalid);
00421            buf[l] = '\0';
00422            ptr = rindex(buf, '_');
00423            if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
00424               return XpmFileInvalid;
00425            /* this is definitely an XPM 1 file */
00426            mdata->format = 1;
00427            n = 1;                  /* handle XPM1 as mainly XPM2 C */
00428        } else {
00429 
00430            /*
00431             * skip the first word, get the second one, and see if this is
00432             * XPM 2 or 3
00433             */
00434            l = xpmNextWord(mdata, buf, BUFSIZ);
00435            if ((l == 3 && !strncmp("XPM", buf, 3)) ||
00436               (l == 4 && !strncmp("XPM2", buf, 4))) {
00437               if (l == 3)
00438                   n = 1;           /* handle XPM as XPM2 C */
00439               else {
00440                   /* get the type key word */
00441                   l = xpmNextWord(mdata, buf, BUFSIZ);
00442 
00443                   /*
00444                    * get infos about this type
00445                    */
00446                   while (xpmDataTypes[n].type
00447                         && strncmp(xpmDataTypes[n].type, buf, l))
00448                      n++;
00449               }
00450               mdata->format = 0;
00451            } else
00452               /* nope this is not an XPM file */
00453               return XpmFileInvalid;
00454        }
00455        if (xpmDataTypes[n].type) {
00456            if (n == 0) {           /* natural type */
00457               mdata->Bcmt = xpmDataTypes[n].Bcmt;
00458               mdata->Ecmt = xpmDataTypes[n].Ecmt;
00459               xpmNextString(mdata);       /* skip the end of the headerline */
00460               mdata->Bos = xpmDataTypes[n].Bos;
00461               mdata->Eos = xpmDataTypes[n].Eos;
00462            } else {
00463               mdata->Bcmt = xpmDataTypes[n].Bcmt;
00464               mdata->Ecmt = xpmDataTypes[n].Ecmt;
00465               if (!mdata->format) {       /* XPM 2 or 3 */
00466                   mdata->Bos = xpmDataTypes[n].Bos;
00467                   mdata->Eos = '\0';
00468                   /* get to the beginning of the first string */
00469                   xpmNextString(mdata);
00470                   mdata->Eos = xpmDataTypes[n].Eos;
00471               } else               /* XPM 1 skip end of line */
00472                   xpmNextString(mdata);
00473            }
00474        } else
00475            /* we don't know about that type of XPM file... */
00476            return XpmFileInvalid;
00477     }
00478     return XpmSuccess;
00479 }