Blame lib/Xm/Xpmdata.c

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