diff options
Diffstat (limited to 'libXpm/src/data.c')
-rw-r--r-- | libXpm/src/data.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/libXpm/src/data.c b/libXpm/src/data.c new file mode 100644 index 000000000..94caa61bf --- /dev/null +++ b/libXpm/src/data.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* data.c: * +* * +* XPM library * +* IO utilities * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ +/* $XFree86: xc/extras/Xpm/lib/data.c,v 1.3 2001/10/28 03:32:10 tsi Exp $ */ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifndef CXPMPROG +#if 0 +/* Official version number */ +static char *RCS_Version = "$XpmVersion: 3.4k $"; + +/* Internal version number */ +static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $"; +#endif +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" +#endif +#include <ctype.h> + +#ifndef CXPMPROG +#define Getc(data, file) getc(file) +#define Ungetc(data, c, file) ungetc(c, file) +#endif + +static int +ParseComment(xpmData *data) +{ + if (data->type == XPMBUFFER) { + register char c; + register unsigned int n = 0; + unsigned int notend; + char *s, *s2; + + s = data->Comment; + *s = data->Bcmt[0]; + + /* skip the string beginning comment */ + s2 = data->Bcmt; + do { + c = *data->cptr++; + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c); + + if (*s2 != '\0') { + /* this wasn't the beginning of a comment */ + data->cptr -= n; + return 0; + } + /* store comment */ + data->Comment[0] = *s; + s = data->Comment; + notend = 1; + n = 0; + while (notend) { + s2 = data->Ecmt; + while (*s != *s2 && c) { + c = *data->cptr++; + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + } + data->CommentLength = n; + do { + c = *data->cptr++; + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c); + if (*s2 == '\0') { + /* this is the end of the comment */ + notend = 0; + data->cptr--; + } + } + return 0; + } else { + FILE *file = data->stream.file; + register int c; + register unsigned int n = 0, a; + unsigned int notend; + char *s, *s2; + + s = data->Comment; + *s = data->Bcmt[0]; + + /* skip the string beginning comment */ + s2 = data->Bcmt; + do { + c = Getc(data, file); + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c != EOF); + + if (*s2 != '\0') { + /* this wasn't the beginning of a comment */ + /* put characters back in the order that we got them */ + for (a = n; a > 0; a--, s--) + Ungetc(data, *s, file); + return 0; + } + /* store comment */ + data->Comment[0] = *s; + s = data->Comment; + notend = 1; + n = 0; + while (notend) { + s2 = data->Ecmt; + while (*s != *s2 && c != EOF) { + c = Getc(data, file); + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + } + data->CommentLength = n; + do { + c = Getc(data, file); + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c != EOF); + if (*s2 == '\0') { + /* this is the end of the comment */ + notend = 0; + Ungetc(data, *s, file); + } + } + return 0; + } +} + +/* + * skip to the end of the current string and the beginning of the next one + */ +int +xpmNextString(xpmData *data) +{ + if (!data->type) + data->cptr = (data->stream.data)[++data->line]; + else if (data->type == XPMBUFFER) { + register char c; + + /* get to the end of the current string */ + if (data->Eos) + while ((c = *data->cptr++) && c != data->Eos); + + /* + * then get to the beginning of the next string looking for possible + * comment + */ + if (data->Bos) { + while ((c = *data->cptr++) && c != data->Bos) + if (data->Bcmt && c == data->Bcmt[0]) + ParseComment(data); + } else if (data->Bcmt) { /* XPM2 natural */ + while ((c = *data->cptr++) == data->Bcmt[0]) + ParseComment(data); + data->cptr--; + } + } else { + register int c; + FILE *file = data->stream.file; + + /* get to the end of the current string */ + if (data->Eos) + while ((c = Getc(data, file)) != data->Eos && c != EOF); + + /* + * then get to the beginning of the next string looking for possible + * comment + */ + if (data->Bos) { + while ((c = Getc(data, file)) != data->Bos && c != EOF) + if (data->Bcmt && c == data->Bcmt[0]) + ParseComment(data); + + } else if (data->Bcmt) { /* XPM2 natural */ + while ((c = Getc(data, file)) == data->Bcmt[0]) + ParseComment(data); + Ungetc(data, c, file); + } + } + return 0; +} + + +/* + * skip whitespace and return the following word + */ +unsigned int +xpmNextWord( + xpmData *data, + char *buf, + unsigned int buflen) +{ + register unsigned int n = 0; + int c; + + if (!data->type || data->type == XPMBUFFER) { + while (isspace(c = *data->cptr) && c != data->Eos) + data->cptr++; + do { + c = *data->cptr++; + *buf++ = c; + n++; + } while (!isspace(c) && c != data->Eos && n < buflen); + n--; + data->cptr--; + } else { + FILE *file = data->stream.file; + + while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos); + while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) { + *buf++ = c; + n++; + c = Getc(data, file); + } + Ungetc(data, c, file); + } + return (n); /* this returns bytes read + 1 */ +} + +/* + * skip whitespace and compute the following unsigned int, + * returns 1 if one is found and 0 if not + */ +int +xpmNextUI( + xpmData *data, + unsigned int *ui_return) +{ + char buf[BUFSIZ]; + int l; + + l = xpmNextWord(data, buf, BUFSIZ); + return xpmatoui(buf, l, ui_return); +} + +/* + * return end of string - WARNING: malloc! + */ +int +xpmGetString( + xpmData *data, + char **sptr, + unsigned int *l) +{ + unsigned int i, n = 0; + int c; + char *p = NULL, *q, buf[BUFSIZ]; + + if (!data->type || data->type == XPMBUFFER) { + if (data->cptr) { + char *start = data->cptr; + while ((c = *data->cptr) && c != data->Eos) + data->cptr++; + n = data->cptr - start + 1; + p = (char *) XpmMalloc(n); + if (!p) + return (XpmNoMemory); + strncpy(p, start, n); + if (data->type) /* XPMBUFFER */ + p[n - 1] = '\0'; + } + } else { + FILE *file = data->stream.file; + + if ((c = Getc(data, file)) == EOF) + return (XpmFileInvalid); + + i = 0; + q = buf; + p = (char *) XpmMalloc(1); + while (c != data->Eos && c != EOF) { + if (i == BUFSIZ) { + /* get to the end of the buffer */ + /* malloc needed memory */ + q = (char *) XpmRealloc(p, n + i); + if (!q) { + XpmFree(p); + return (XpmNoMemory); + } + p = q; + q += n; + /* and copy what we already have */ + strncpy(q, buf, i); + n += i; + i = 0; + q = buf; + } + *q++ = c; + i++; + c = Getc(data, file); + } + if (c == EOF) { + XpmFree(p); + return (XpmFileInvalid); + } + if (n + i != 0) { + /* malloc needed memory */ + q = (char *) XpmRealloc(p, n + i + 1); + if (!q) { + XpmFree(p); + return (XpmNoMemory); + } + p = q; + q += n; + /* and copy the buffer */ + strncpy(q, buf, i); + n += i; + p[n++] = '\0'; + } else { + *p = '\0'; + n = 1; + } + Ungetc(data, c, file); + } + *sptr = p; + *l = n; + return (XpmSuccess); +} + +/* + * get the current comment line + */ +int +xpmGetCmt( + xpmData *data, + char **cmt) +{ + if (!data->type) + *cmt = NULL; + else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) { + if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL) + return XpmNoMemory; + strncpy(*cmt, data->Comment, data->CommentLength); + (*cmt)[data->CommentLength] = '\0'; + data->CommentLength = 0; + } else + *cmt = NULL; + return 0; +} + +xpmDataType xpmDataTypes[] = +{ + {"", "!", "\n", '\0', '\n', "", "", "", ""}, /* Natural type */ + {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"}, + {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"}, + {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL} +}; + +/* + * parse xpm header + */ +int +xpmParseHeader(xpmData *data) +{ + char buf[BUFSIZ+1] = {0}; + int l, n = 0; + + if (data->type) { + data->Bos = '\0'; + data->Eos = '\n'; + data->Bcmt = data->Ecmt = NULL; + l = xpmNextWord(data, buf, BUFSIZ); + if (l == 7 && !strncmp("#define", buf, 7)) { + /* this maybe an XPM 1 file */ + char *ptr; + + l = xpmNextWord(data, buf, BUFSIZ); + if (!l) + return (XpmFileInvalid); + buf[l] = '\0'; + ptr = strrchr(buf, '_'); + if (!ptr || strncmp("_format", ptr, l - (ptr - buf))) + return XpmFileInvalid; + /* this is definitely an XPM 1 file */ + data->format = 1; + n = 1; /* handle XPM1 as mainly XPM2 C */ + } else { + + /* + * skip the first word, get the second one, and see if this is + * XPM 2 or 3 + */ + l = xpmNextWord(data, buf, BUFSIZ); + if ((l == 3 && !strncmp("XPM", buf, 3)) || + (l == 4 && !strncmp("XPM2", buf, 4))) { + if (l == 3) + n = 1; /* handle XPM as XPM2 C */ + else { + /* get the type key word */ + l = xpmNextWord(data, buf, BUFSIZ); + + /* + * get infos about this type + */ + while (xpmDataTypes[n].type + && strncmp(xpmDataTypes[n].type, buf, l)) + n++; + } + data->format = 0; + } else + /* nope this is not an XPM file */ + return XpmFileInvalid; + } + if (xpmDataTypes[n].type) { + if (n == 0) { /* natural type */ + data->Bcmt = xpmDataTypes[n].Bcmt; + data->Ecmt = xpmDataTypes[n].Ecmt; + xpmNextString(data); /* skip the end of the headerline */ + data->Bos = xpmDataTypes[n].Bos; + data->Eos = xpmDataTypes[n].Eos; + } else { + data->Bcmt = xpmDataTypes[n].Bcmt; + data->Ecmt = xpmDataTypes[n].Ecmt; + if (!data->format) { /* XPM 2 or 3 */ + data->Bos = xpmDataTypes[n].Bos; + data->Eos = '\0'; + /* get to the beginning of the first string */ + xpmNextString(data); + data->Eos = xpmDataTypes[n].Eos; + } else /* XPM 1 skip end of line */ + xpmNextString(data); + } + } else + /* we don't know about that type of XPM file... */ + return XpmFileInvalid; + } + return XpmSuccess; +} |