Example #1
0
File: tok.c Project: BPaden/garglk
/* add a symbol to the #define symbol table */
void tok_add_define(tokcxdef *ctx, char *sym, int len,
                    char *expan, int explen)
{
    int       hsh;
    tokdfdef *df;

    /* if it's already defined, ignore it */
    if (tok_find_define(ctx, sym, len))
        return;

    /* find the appropriate entry in the hash table */
    hsh = tokdfhsh(sym, len);

    /* allocate space for the symbol */
    df = (tokdfdef *)mchalo(ctx->tokcxerr,
                            (sizeof(tokdfdef) + len + explen - 1),
                            "tok_add_define");

    /* set up the new symbol */
    df->nm = df->expan + explen;
    df->len = len;
    df->explen = explen;
    memcpy(df->expan, expan, explen);
    memcpy(df->nm, sym, len);

    /* link it into the hash chain */
    df->nxt = ctx->tokcxdf[hsh];
    ctx->tokcxdf[hsh] = df;
}
Example #2
0
File: tok.c Project: BPaden/garglk
/*
 *   Read preprocessor state from a file 
 */
void tok_read_defines(tokcxdef *ctx, osfildef *fp, errcxdef *ec)
{
    int        i;
    tokdfdef **dfp;
    tokdfdef  *df;
    char       buf[4];

    /* write each element of the hash chains */
    for (i = TOKDFHSHSIZ, dfp = ctx->tokcxdf ; i ; ++dfp, --i)
    {
        /* read this hash chain */
        for (;;)
        {
            /* read the next entry's header, and stop if this is the end */
            if (osfrb(fp, buf, 4)) errsig(ec, ERR_RDGAM);
            if (osrp2(buf) == 0) break;

            /* set up a new symbol of the appropriate size */
            df = (tokdfdef *)mchalo(ec,
                                    (sizeof(tokdfdef) + osrp2(buf)
                                     + osrp2(buf+2) - 1),
                                    "tok_read_defines");
            df->explen = osrp2(buf+2);
            df->nm = df->expan + df->explen;
            df->len = osrp2(buf);

            /* read the rest of the symbol */
            if (osfrb(fp, df->nm, df->len)
                || (df->explen != 0 && osfrb(fp, df->expan, df->explen)))
                errsig(ec, ERR_RDGAM);

            /*
             *   If a symbol with this name already exists in the table,
             *   discard the new one -- the symbols defined by -D and the
             *   current set of built-in symbols takes precedence over the
             *   set loaded from the file.  
             */
            if (tok_find_define(ctx, df->nm, df->len))
            {
                /* simply discard this symbol */
                mchfre(df);
            }
            else
            {
                /* link it into this hash chain */
                df->nxt = *dfp;
                *dfp = df;
            }
        }
    }
}
Example #3
0
File: tok.c Project: BPaden/garglk
tokcxdef *tokcxini(errcxdef *errctx, mcmcxdef *mcmctx, tokldef *sctab)
{
    int       i;
    int       cnt;
    tokldef  *p;
    uchar     c;
    uchar     index[256];
    tokcxdef *ret;
    tokscdef *sc;
    ushort    siz;
    
    /* set up index table: finds tokcxsc entry from character value */
    memset(index, 0, (size_t)sizeof(index));
    for (i = cnt = 0, p = sctab ; (c = p->toklstr[0]) != 0 ; ++cnt, ++p)
        if (!index[c]) index[c] = ++i;
    
    /* allocate memory for table plus the tokscdef's */
    siz = sizeof(tokcxdef) + (i * sizeof(tokscdef *))
          + ((cnt + 1) * sizeof(tokscdef));
    ret = (tokcxdef *)mchalo(errctx, siz, "tokcxini");
    memset(ret, 0, (size_t)siz);
    
    /* copy the index, set up fixed part */
    memcpy(ret->tokcxinx, index, sizeof(ret->tokcxinx));
    ret->tokcxerr = errctx;
    ret->tokcxmem = mcmctx;

    /* start out without an #if */
    ret->tokcxifcur = TOKIF_IF_YES;
    
    /* force the first toknext() to read a line */
    ret->tokcxptr = "\000";
    
    /* figure where the tokscdef's go (right after sc pointer array) */
    sc = (tokscdef *)&ret->tokcxsc[i+1];
    
    /* set up the individual tokscdef entries, and link into lists */
    for (p = sctab ; (c = p->toklstr[0]) != 0 ; ++p, ++sc)
    {
        size_t len;
        
        sc->toksctyp = p->tokltyp;
        len = sc->toksclen = strlen(p->toklstr);
        memcpy(sc->tokscstr, p->toklstr, len);
        sc->tokscnxt = ret->tokcxsc[index[c]];
        ret->tokcxsc[index[c]] = sc;
    }
    
    return(ret);
}
Example #4
0
File: tok.c Project: BPaden/garglk
/* add an include path to a tokdef */
void tokaddinc(tokcxdef *ctx, char *path, int pathlen)
{
    tokpdef *newpath;
    tokpdef *last;
    
    /* find the tail of the include path list, if any */
    for (last = ctx->tokcxinc ; last && last->tokpnxt ;
         last = last->tokpnxt) ;
    
    /* allocate storage for and set up a new path structure */
    newpath = (tokpdef *)mchalo(ctx->tokcxerr,
                                (sizeof(tokpdef) + pathlen - 1),
                                "tokaddinc");
    newpath->tokplen = pathlen;
    newpath->tokpnxt = (tokpdef *)0;
    memcpy(newpath->tokpdir, path, (size_t)pathlen);
    
    /* link in at end of list (if no list yet, newpath becomes first entry) */
    if (last)
        last->tokpnxt = newpath;
    else
        ctx->tokcxinc = newpath;
}
Example #5
0
/* set up contents property for load-on-demand */
void supcont(void *ctx0, objnum obj, prpnum prp)
{
    supcxdef  *ctx = (supcxdef *)ctx0;
    vocidef ***vpg;
    vocidef  **v;
    voccxdef  *voc = ctx->supcxvoc;
    int        i;
    int        j;
    int        len = 2;
    objnum     chi;
    objnum     loc;

    /* be sure the buffer is allocated */
    if (!ctx->supcxbuf)
    {
        ctx->supcxlen = 512;
        ctx->supcxbuf = mchalo(ctx->supcxerr, ctx->supcxlen,
                               "supcont");
    }

    assert(prp == PRP_CONTENTS);         /* the only thing that makes sense */
    for (vpg = voc->voccxinh, i = 0 ; i < VOCINHMAX ; ++vpg, ++i)
    {
        if (!*vpg) continue;                     /* no entries on this page */
        for (v = *vpg, chi = (i << 8), j = 0 ; j < 256 ; ++v, ++chi, ++j)
        {
            /* if there's no record at this location, skip it */
            if (!*v) continue;

            /* inherit the location if it hasn't been set to any value */
            if ((*v)->vociloc == MCMONINV
                && !((*v)->vociflg & VOCIFLOCNIL))
                loc = (*v)->vociilc;
            else
                loc = (*v)->vociloc;

            /* if this object is in the indicated location, add it */
            if (loc == obj && !((*v)->vociflg & VOCIFCLASS))
            {
                /* see if we have room in list buffer; expand buffer if not */
                if (len + 3 > ctx->supcxlen)
                {
                    uchar *newbuf;

                    /* allocate a new buffer */
                    newbuf = mchalo(ctx->supcxerr,
                                    (len + 512), "supcont");

                    /* copy the old buffer's contents into the new buffer */
                    memcpy(newbuf, ctx->supcxbuf, ctx->supcxlen);

                    /* remember the new buffer length */
                    ctx->supcxlen = len + 512;

                    /* free the old buffer */
                    mchfre(ctx->supcxbuf);

                    /* remember the new buffer */
                    ctx->supcxbuf = newbuf;

                    /* sanity check for integer overflow */
                    if (len + 3 > ctx->supcxlen)
                        errsig(ctx->supcxmem->mcmcxgl->mcmcxerr, ERR_SUPOVF);
                }
                ctx->supcxbuf[len] = DAT_OBJECT;
                oswp2(ctx->supcxbuf + len + 1, chi);
                len += 3;
            }
        }
    }

    oswp2(ctx->supcxbuf, len);
    objsetp(ctx->supcxmem, obj, prp, DAT_LIST, ctx->supcxbuf,
            ctx->supcxrun->runcxundo);
}
Example #6
0
File: tok.c Project: BPaden/garglk
/* get a new line from line source, processing '#' directives */
static int tokgetlin(tokcxdef *ctx, int dopound)
{
    for (;;)
    {
        if (linget(ctx->tokcxlin))
        {
            /* at eof in current source; resume parent if there is one */
            if (ctx->tokcxlin->linpar)
            {
                lindef *parent;
                
                parent = ctx->tokcxlin->linpar;          /* remember parent */
                lincls(ctx->tokcxlin);               /* close included file */
                if (!ctx->tokcxdbg)               /* if no debug context... */
                    mchfre(ctx->tokcxlin);              /* free line source */
                ctx->tokcxlin = parent;      /* reset to parent line source */
                if (parent->linflg & LINFCMODE)
                    ctx->tokcxflg |= TOKCXFCMODE;
                else
                    ctx->tokcxflg &= ~TOKCXFCMODE;
                continue;                       /* back for another attempt */
            }
            else
            {
                /* check for outstanding #if/#ifdef */
                if (ctx->tokcxifcnt)
                    errlog(ctx->tokcxerr, ERR_NOENDIF);

                /* return end-of-file indication */
                return TRUE;
            }
        }
        
        /* if this is a multi-segment line, copy it into our own buffer */
        if (ctx->tokcxlin->linflg & LINFMORE)
        {
            char *p;
            uint  rem;
            int   done;
            
            if (!ctx->tokcxbuf)
            {
                /* allocate 1k as a default buffer */
                ctx->tokcxbuf = (char *)mchalo(ctx->tokcxerr, 1024,
                                               "tok");
                ctx->tokcxbsz = 1024;
            }
            ctx->tokcxlen = 0;
            
            for (done = FALSE, p = ctx->tokcxbuf, rem = ctx->tokcxbsz ;
                 !done ; )
            {
                size_t len = ctx->tokcxlin->linlen;

                /* add the current segment's length into line length */
                ctx->tokcxlen += len;
                
                /* we're done after this piece if the last fetch was all */
                done = !(ctx->tokcxlin->linflg & LINFMORE);
                if (len + 1 > rem)
                {
                    char *newp;

                    /* increase the size of the buffer */
                    if (ctx->tokcxbsz > (unsigned)0x8000)
                        errsig(ctx->tokcxerr, ERR_LONGLIN);
                    rem += 4096;
                    ctx->tokcxbsz += 4096;
                    
                    /* allocate a new buffer and copy line into it */
                    newp = (char *)mchalo(ctx->tokcxerr, ctx->tokcxbsz, "tok");
                    memcpy(newp, ctx->tokcxbuf, (size_t)(p - ctx->tokcxbuf));
                    
                    /* free the original buffer, and use the new one */
                    p = (p - ctx->tokcxbuf) + newp;
                    mchfre(ctx->tokcxbuf);
                    ctx->tokcxbuf = newp;
                }
                
                /* add the line to the buffer */
                memcpy(p, ctx->tokcxlin->linbuf, len);
                p += len;
                rem -= len;
                
                /* get the next piece of the line if there is one */
                if (!done)
                {
                    if (linget(ctx->tokcxlin)) break;
                }
            }
            
            /* null-terminate the buffer, and use it for input */
            *p = '\0';
            ctx->tokcxptr = ctx->tokcxbuf;
        }
        else
        {
            ctx->tokcxptr = ctx->tokcxlin->linbuf;
            ctx->tokcxlen = ctx->tokcxlin->linlen;
        }
        
        /* check for preprocessor directives */
        if (dopound && ctx->tokcxlen != 0 && ctx->tokcxptr[0] == '#'
            && !(ctx->tokcxlin->linflg & LINFNOINC))
        {
            char   *p;
            int     len;
            static  struct
            {
                char  *nm;
                int    len;
                int    ok_in_if;
                void (*fn)(tokcxdef *, char *, int);
            }
            *dirp, dir[] =
            {
                { "include", 7, FALSE, tokinclude },
                { "pragma",  6, FALSE, tokpragma },
                { "define",  6, FALSE, tokdefine },
                { "ifdef",   5, TRUE, tokifdef },
                { "ifndef",  6, TRUE, tokifndef },
                { "if",      2, TRUE, tokif },
                { "else",    4, TRUE, tokelse },
                { "elif",    4, TRUE, tokelif },
                { "endif",   5, TRUE, tokendif },
                { "undef",   5, FALSE, tokundef },
                { "error",   5, FALSE, tok_p_error }
            };
            int  i;

            /* scan off spaces between '#' and directive */
            for (len = ctx->tokcxlen - 1, p = &ctx->tokcxptr[1] ;
                 len && t_isspace(*p) ; --len, ++p) ;

            /* find and process the directive */
            for (dirp = dir, i = sizeof(dir)/sizeof(dir[0]) ; i ; --i, ++dirp)
            {
                /* compare this directive; if it wins, call its function */
                if (len >= dirp->len && !memcmp(p, dirp->nm, (size_t)dirp->len)
                    && (len == dirp->len || t_isspace(*(p + dirp->len))))
                {
                    int cnt;
                    int stat;
                    
                    /*
                     *   if we're not in a #if's false part, or if the
                     *   directive is processed even in #if false parts,
                     *   process the line, otherwise skip it 
                     */
                    cnt = ctx->tokcxifcnt;
                    if (dirp->ok_in_if || cnt == 0
                        || ((stat = ctx->tokcxifcur) == TOKIF_IF_YES
                            || stat == TOKIF_ELSE_YES))
                    {
                        /* skip whitespace following the directive */
                        for (p += dirp->len, len -= dirp->len ;
                             len && t_isspace(*p) ;
                             --len, ++p) ;

                        /* invoke the function to process this directive */
                        (*dirp->fn)(ctx, p, len);
                    }

                    /* there's no need to look at more directives */
                    break;
                }
            }

            /* if we didn't find anything, flag the error */
            if (i == 0)
                errlog(ctx->tokcxerr, ERR_PRPDIR);

            /* ignore this line */
            continue;
        }
        else
        {
            /*
             *   Check the #if level.  If we're in an #if, and we're to
             *   ignore lines (because of a false condition or an #else
             *   part for a true condition), skip this line. 
             */
            if (ctx->tokcxifcnt != 0)
            {
                switch(ctx->tokcxifcur)
                {
                case TOKIF_IF_NO:
                case TOKIF_ELSE_NO:
                    /* ignore this line */
                    continue;

                default:
                    /* we're in a true part - keep the line */
                    break;
                }
            }
            
            ctx->tokcxlin->linflg &= ~LINFDBG;       /* no debug record yet */
            return(FALSE);                      /* return the line we found */
        }
    }
}