earlybrowserreborn - Rev 1

Subversion Repositories:
Rev:
/* Copyright 1990,91 GROUPE BULL -- See licence conditions in file COPYRIGHT */
/*****************************************************************************\
* data.c:                                                                     *
*                                                                             *
*  XPM library                                                                *
*  IO utilities                                                               *
*                                                                             *
*  Developed by Arnaud Le Hors                                                *
\*****************************************************************************/


/* Official version number */
static char *RCS_Version = "$XpmVersion: 3.0 $";

/* Internal version number */
static char *RCS_Id = "$Id: xpm.shar,v 3.0 1991/10/04 10:38:20 lehors Exp $";

#include "xpmP.h"
#ifdef VMS
#include "sys$library:stat.h"
#include "sys$library:ctype.h"
#else
#include <sys/stat.h>
#include <ctype.h>
#endif

LFUNC(atoui, unsigned int, (char *p, unsigned int l, unsigned int *ui_return));

static unsigned int
atoui(p, l, ui_return)
    register char *p;
    unsigned int l;
    unsigned int *ui_return;
{
    register int n, i;

    n = 0;
    for (i = 0; i < l; i++)
        if (*p >= '0' && *p <= '9')
            n = n * 10 + *p++ - '0';
        else
            break;

    if (i != 0 && i == l) {
        *ui_return = n;
        return 1;
    } else
        return 0;
}

/*
 * skip to the end of the current string and the beginning of the next one
 */

xpmNextString(mdata)
    xpmData *mdata;
{
    int c;

    switch (mdata->type) {
    case XPMARRAY:
        mdata->cptr = (mdata->stream.data)[++mdata->line];
        break;
    case XPMFILE:
    case XPMPIPE:
        if (mdata->Eos)
            while ((c = xpmGetC(mdata)) != mdata->Eos && c != EOF);
        if (mdata->Bos)                 /* if not natural XPM2 */
            while ((c = xpmGetC(mdata)) != mdata->Bos && c != EOF);
        break;
    }
}

/*
 * skip whitespace and compute the following unsigned int,
 * returns 1 if one is found and 0 if not
 */

int
xpmNextUI(mdata, ui_return)
    xpmData *mdata;
    unsigned int *ui_return;
{
    char buf[BUFSIZ];
    int l;

    l = xpmNextWord(mdata, buf);
    return atoui(buf, l, ui_return);
}

/*
 * return the current character, skipping comments
 */

xpmGetC(mdata)
    xpmData *mdata;
{
    int c;
    register unsigned int n = 0, a;
    unsigned int notend;

    switch (mdata->type) {
    case XPMARRAY:
        return (*mdata->cptr++);
    case XPMFILE:
    case XPMPIPE:
        c = getc(mdata->stream.file);

        if (mdata->Bos && mdata->Eos
            && (c == mdata->Bos || c == mdata->Eos)) {
            /* if not natural XPM2 */
            mdata->InsideString = !mdata->InsideString;
            return (c);
        }
        if (!mdata->InsideString && mdata->Bcmt && c == mdata->Bcmt[0]) {
            mdata->Comment[0] = c;

            /*
             * skip the string begining comment
             */

            do {
                c = getc(mdata->stream.file);
                mdata->Comment[++n] = c;
            } while (c == mdata->Bcmt[n] && mdata->Bcmt[n] != '\0'
                     && c != EOF);

            if (mdata->Bcmt[n] != '\0') {
                /* this wasn't the begining of a comment */
                /* put characters back in the order that we got them */
                for (a = n; a > 0; a--)
                    xpmUngetC(mdata->Comment[a], mdata);
                return (mdata->Comment[0]);
            }

            /*
             * store comment
             */

            mdata->Comment[0] = mdata->Comment[n];
            notend = 1;
            n = 0;
            while (notend) {
                while (mdata->Comment[n] != mdata->Ecmt[0] && c != EOF) {
                    c = getc(mdata->stream.file);
                    mdata->Comment[++n] = c;
                }
                mdata->CommentLength = n;
                a = 0;
                do {
                    c = getc(mdata->stream.file);
                    n++;
                    a++;
                    mdata->Comment[n] = c;
                } while (c == mdata->Ecmt[a] && mdata->Ecmt[a] != '\0'
                         && c != EOF);
                if (mdata->Ecmt[a] == '\0') {
                    /* this is the end of the comment */
                    notend = 0;
                    xpmUngetC(mdata->Comment[n], mdata);
                }
            }
            c = xpmGetC(mdata);
        }
        return (c);
    }
}

/*
 * push the given character back
 */

xpmUngetC(c, mdata)
    int c;
    xpmData *mdata;
{
    switch (mdata->type) {
    case XPMARRAY:
        return (*--mdata->cptr = c);
    case XPMFILE:
    case XPMPIPE:
        if (mdata->Bos && (c == mdata->Bos || c == mdata->Eos))
            /* if not natural XPM2 */
            mdata->InsideString = !mdata->InsideString;
        return (ungetc(c, mdata->stream.file));
    }
}

/*
 * skip whitespace and return the following word
 */

unsigned int
xpmNextWord(mdata, buf)
    xpmData *mdata;
    char *buf;
{
    register unsigned int n = 0;
    int c;

    switch (mdata->type) {
    case XPMARRAY:
        while (isspace(c = *mdata->cptr) && c != mdata->Eos)
            mdata->cptr++;
        do {
            c = *mdata->cptr++;
            buf[n++] = c;
        } while (!isspace(c) && c != mdata->Eos && c != '\0');
        n--;
        mdata->cptr--;
        break;
    case XPMFILE:
    case XPMPIPE:
        while (isspace(c = xpmGetC(mdata)) && c != mdata->Eos);
        while (!isspace(c) && c != mdata->Eos && c != EOF) {
            buf[n++] = c;
            c = xpmGetC(mdata);
        }
        xpmUngetC(c, mdata);
        break;
    }
    return (n);
}

/*
 * get the current comment line
 */

xpmGetCmt(mdata, cmt)
    xpmData *mdata;
    char **cmt;
{
    switch (mdata->type) {
    case XPMARRAY:
        *cmt = NULL;
        break;
    case XPMFILE:
    case XPMPIPE:
        if (mdata->CommentLength) {
            *cmt = (char *) malloc(mdata->CommentLength + 1);
            strncpy(*cmt, mdata->Comment, mdata->CommentLength);
            (*cmt)[mdata->CommentLength] = '\0';
            mdata->CommentLength = 0;
        } else
            *cmt = NULL;
        break;
    }
}

/*
 * open the given file to be read as an xpmData which is returned.
 */

int
xpmReadFile(filename, mdata)
    char *filename;
    xpmData *mdata;
{
    char *compressfile, buf[BUFSIZ];
    struct stat status;

    if (!filename) {
        mdata->stream.file = (stdin);
        mdata->type = XPMFILE;
    } else {
#ifdef ZPIPE
        if ((strlen(filename) > 2) &&
            !strcmp(".Z", filename + (strlen(filename) - 2))) {
            mdata->type = XPMPIPE;
            sprintf(buf, "uncompress -c %s", filename);
            if (!(mdata->stream.file = popen(buf, "r")))
                return (XpmOpenFailed);

        } else {
            if (!(compressfile = (char *) malloc(strlen(filename) + 3)))
                return (XpmNoMemory);

            strcpy(compressfile, filename);
            strcat(compressfile, ".Z");
            if (!stat(compressfile, &status)) {
                sprintf(buf, "uncompress -c %s", compressfile);
                if (!(mdata->stream.file = popen(buf, "r"))) {
                    free(compressfile);
                    return (XpmOpenFailed);
                }
                mdata->type = XPMPIPE;
            } else {
#endif
                if (!(mdata->stream.file = fopen(filename, "r"))) {
#ifdef ZPIPE
                    free(compressfile);
#endif
                    return (XpmOpenFailed);
                }
                mdata->type = XPMFILE;
#ifdef ZPIPE
            }
            free(compressfile);
        }
#endif
    }
    mdata->CommentLength = 0;
    mdata->InsideString = 0;
    return (XpmSuccess);
}

/*
 * open the given file to be written as an xpmData which is returned
 */

int
xpmWriteFile(filename, mdata)
    char *filename;
    xpmData *mdata;
{
    char buf[BUFSIZ];

    if (!filename) {
        mdata->stream.file = (stdout);
        mdata->type = XPMFILE;
    } else {
#ifdef ZPIPE
        if (strlen(filename) > 2
            && !strcmp(".Z", filename + (strlen(filename) - 2))) {
            sprintf(buf, "compress > %s", filename);
            if (!(mdata->stream.file = popen(buf, "w")))
                return (XpmOpenFailed);

            mdata->type = XPMPIPE;
        } else {
#endif
            if (!(mdata->stream.file = fopen(filename, "w")))
                return (XpmOpenFailed);

            mdata->type = XPMFILE;
#ifdef ZPIPE
        }
#endif
    }
    return (XpmSuccess);
}

/*
 * open the given array to be read or written as an xpmData which is returned
 */

int
xpmOpenArray(data, mdata)
    char **data;
    xpmData *mdata;
{
    mdata->type = XPMARRAY;
    mdata->stream.data = data;
    mdata->cptr = *data;
    mdata->line = 0;
    mdata->CommentLength = 0;
    mdata->Bcmt = mdata->Ecmt = NULL;
    mdata->Bos = mdata->Eos = '\0';
    mdata->InsideString = 0;
    return (XpmSuccess);
}

/*
 * close the file related to the xpmData if any
 */

XpmDataClose(mdata)
    xpmData *mdata;
{
    switch (mdata->type) {
    case XPMARRAY:
        break;
    case XPMFILE:
        if (mdata->stream.file != (stdout) && mdata->stream.file != (stdin))
            fclose(mdata->stream.file);
        break;
    case XPMPIPE:
        pclose(mdata->stream.file);
    }
}