예제 #1
0
value_t *
eppic_exevar(void *arg)
{
vnode_t *vn = arg;
value_t *nv;
var_t*curv;
srcpos_t pos;

    eppic_curpos(&vn->n->pos, &pos);

    if(!(curv=eppic_getvarbyname(vn->name, 0, 0))) {

        eppic_error("Oops! Var ref1.[%s]", vn->name);

    }
    if(!curv->ini && !insizeof && !vlev) {

        eppic_error("Variable [%s] used before being initialized", curv->name);

    }

    nv=eppic_newval();
    eppic_dupval(nv,curv->v);
    nv->set=1;
    nv->setval=curv->v;
    nv->setfct=eppic_setfct;

    eppic_curpos(&pos, 0);

    return nv;
}
예제 #2
0
/*
    This function is called to validate variable declaration.
    No array decalration for variables (this can only be checked in 
    eppic_stat_decl() and eppic_file_decl() usingthe idx field ofthe var struct.
    Same comment for nbits. Only in struct declarations.
*/
void
eppic_validate_vars(var_t*svs)
{
var_t*v, *next;

    if(!svs) return;

    for(v=svs->next; v!=svs; v=next) {

        next=v->next;

        /* just remove extern variables */
        if(eppic_isxtern(v->v->type.typattr)) {

            eppic_dequeue(v);
            eppic_freevar(v);

        } else {

            if(v->dv->idx) {

                eppic_freesvs(svs);
                eppic_error("Array instanciations not supported.");

            } 
            if(v->dv->nbits) {

                eppic_freesvs(svs);
                eppic_error("Syntax error. Bit field unexpected.");
            }
        }
    }
}
예제 #3
0
node_t*
eppic_newstr()
{
int maxl=S_MAXSTRLEN;
char *buf=eppic_alloc(maxl);
int iline=eppic_line(0);
int i, c;

    /* let the input function knwo we want averyting from the 
       input stream. Comments and all... */
    eppic_rawinput(1);

    for(i=0;i<maxl;i++) {
        c=eppic_input();
        switch(c) {
        case '\\': /* escape sequence */
            switch(c=eppic_input()) {
            case 'x': /* hexa value_t */
                buf[i]=eppic_getnum(16);
            break;
            case '0': /* octal value_t */
                buf[i]=eppic_getnum(8);
            break;
            default : 
                if(isdigit(c))
                {
                    eppic_unput(c);
                    buf[i]=eppic_getnum(10);
                }
                else
                {
                    buf[i]=eppic_getseq(c); 
                }
            break;

            }
        break;
        case '"': /* we're finished */
        {
            buf[i]='\0';
            eppic_rawinput(0);
            return eppic_allocstr(buf);

        }
        case (-1):
            eppic_error("Unterminated string at line %d", iline);
        break;
        default:
            buf[i]=c;
        break;

        }
    }
    eppic_error("String too long at %d", iline);
    return NULLNODE;
}
예제 #4
0
/*
    Print a struct/union type or value
*/
static void
eppic_print_ctype(type_t *t, value_t *v, int level, int indent, char *name, int ref, int justv)
{
stinfo_t *st=eppic_getstbyindex(t->idx, t->type);
stmember_t *m;
char buf[100];

    if(!st) eppic_error("Oops eppic_print_ctype!");

    if(!st->all) {

        eppic_fillst(st);
        if(!st->all) eppic_error("Reference to a incomplete type");
    }

    eppic_indent(level, indent);

    if(!justv) {
        snprintf(buf, sizeof(buf)-1, "%s %s", eppic_ctypename(t->type), st->name?st->name:"");
        eppic_msg("%-*s ", SPACER, buf);

        /* is this is a pointer, bail out */
    }
    if(ref) return;

    if(v && !justv) eppic_msg(" = ");

    eppic_msg("{\n");

    for(m=st->stm; m; m=m->next) {

        value_t *vm=0;

        eppic_indent(level+1, 1);
        if(v) {
            vm=eppic_newval();
            eppic_duptype(&vm->type, &m->type);
            eppic_exememlocal(v, m, vm);
            eppic_ptype2(&vm->type, vm, level+1, 0, m->m.name, 0, 0);

        } else eppic_ptype2(&m->type, vm, level+1, 0, m->m.name, 0, 0);
        eppic_msg(";\n");
        if(vm) eppic_freeval(vm);
    }

    eppic_indent(level, 1);
    eppic_msg("}");
    if(name) eppic_msg(" %s", name);
    
}
예제 #5
0
void
eppic_popjmp(int type)
{
    if(!njmps) {

        eppic_error("Pop underflow!");
    }
    njmps--;
    if(jmps[njmps].type != type) {

        eppic_error("Wrong pop! %d vs %d", jmps[njmps].type, type);
    }
    eppic_setsvlev(jmps[njmps].svlev);
}
예제 #6
0
int
eppic_addsvs(int type, var_t*sv)
{
int curlev=svlev;

    if(svlev==S_MAXDEEP) {

        eppic_error("Svars stack overflow");

    } else {

        svs[svlev].type=type;
        svs[svlev].svs=sv;
        eppic_setsvlev(eppic_getsvlev()+1);

        /* perform automatic initializations */
        eppic_inivars(sv, type==S_PARSE);
        
        /* if S_FILE then we are entering a function so start a newset of
           stack variables */
        if(type == S_FILE ) {

            (void)eppic_addsvs(S_AUTO, (var_t*)eppic_newvlist());

        }
    }
    return curlev;
}
예제 #7
0
static void
eppic_free_bl(blist *bl, void *ra)
{
    bl->freer=ra;
    bl->prev->next=bl->next;
    bl->next->prev=bl->prev;

#ifdef MEMDEBUG

    if(memdebug) {

        /* help out dbx/gdb when they're watching the allocated area
           by writing over it */
        {
        int i, ni=bl->size/sizeof(void*);
        char *p=(char*)bl;
        unsigned long up;

            for(i=0;i<ni;i++) ((char **)p)[i]=ra;
            up=(unsigned long)p;
            if(*((int*)(up-4)) != MAGIC) eppic_error("Oops eppic_free");
            up=up ^ (up & (PAGESIZE-1));
            mprotect((void*)up, PAGESIZE, PROT_READ);
        }

    } else {

        free(bl);
    }

#else
    free(bl);
#endif

}
예제 #8
0
파일: eppic_var.c 프로젝트: daveyoung/eppic
eppic_vpop()
{
    if(vlev) {
        eppic_setsvlev(sidx[--vlev]);
    }
    else eppic_error("Too many parse var pops!");
}
예제 #9
0
/* scan the current array for a specific index and return value_t 
   XXX should use some hashing tables here for speed and scalability */
array_t*
eppic_getarrval(array_t**app, value_t *idx)
{
array_t*ap, *apr;

    /* eppic_setarray(app); AAA comment out */
    apr=*app;

    for(ap=apr->next; ap != apr; ap=ap->next) {

        if(ap->idx->type.type == idx->type.type) {

        int b=0;

            switch(idx->type.type) {
            case V_STRING: b=(!strcmp(ap->idx->v.data, idx->v.data));
            break;
            case V_BASE: b=(unival(ap->idx)==unival(idx));
            break;
            case V_REF: 
                if(eppic_defbsize()==4) 
                    b=(ap->idx->v.ul==idx->v.ul);
                else
                    b=(ap->idx->v.ull==idx->v.ull);
            break;
            default:
                eppic_error("Invalid index type %d", idx->type.type);
            }

            if(b) {

                return ap;

            }
        }
    }

    /* we have not found this index, create one */
    ap=(array_t*)eppic_calloc(sizeof(array_t));
    ap->idx=eppic_makebtype(0);
    eppic_dupval(ap->idx, idx);

    /* just give it a int value_t of 0 for now */
    ap->val=eppic_makebtype(0);

    /* we must set the same refenrence number as the
       upper level array_t*/
    ap->val->arr->ref=apr->ref;

    /* link it in */
    ap->prev=apr->prev;
    ap->next=apr;
    apr->prev->next=ap;
    apr->prev=ap;
    ap->ref=0;
    return ap;
}
예제 #10
0
파일: eppic_op.c 프로젝트: lucchouina/eppic
/* mult is a special case since the parse always return a PTR token 
   for the '*' signed. The PTR token value_t is the number of '* found.
*/
node_t*
eppic_newmult(node_t*n1, node_t*n2, int n)
{
    if(n>1) {

        eppic_error("Syntax error");
    }
    return eppic_newop(MUL, 2, n1, n2);
}
예제 #11
0
idx_t *
eppic_addidx(idx_t *idx, node_t*n)
{
    if(idx->nidx==MAXIDX) {

        eppic_error("Maximum number of dimension is %d", MAXIDX);
    }
    idx->idxs[idx->nidx++]=n;
    return idx;
}
예제 #12
0
파일: eppic_var.c 프로젝트: daveyoung/eppic
eppic_vpush()
{
    if(vlev==S_MAXSDEEP) {

        eppic_error("Too many nested compound statements!");

    } else {

        sidx[vlev]=svlev;
        vlev++;
    }
}
예제 #13
0
파일: eppic_op.c 프로젝트: lucchouina/eppic
ul
eppic_bool(value_t *v)
{
    switch(v->type.type) {

    case V_BASE:
        switch(v->type.size) {
            case 1: return !(!(v->v.uc));
            case 2: return !(!(v->v.us));
            case 4: return !(!(v->v.ul));
            case 8: return !(!(v->v.ull));
            default: eppic_error("Oops eppic_bool()[%d]", v->type.size); break;
        }
    case V_STRING :     return !(!(*((char*)(v->v.data))));
    case V_REF:     return eppic_defbsize()==8?(!(!(v->v.ull))):(!(!(v->v.ul)));
    default :

        eppic_error("Invalid operand for boolean expression");
        return 0;
    }
}
예제 #14
0
/*
    This is where we implement the variable scoping.
*/
var_t*
eppic_getvarbyname(char *name, int silent, int local)
{
var_t*vp;
int i, aidx=0;
ull apiv, mem;

    for(i=svlev-1; i>=0; i--) {

        if((vp=eppic_inlist(name, svs[i].svs))) {

            return vp;
        }
        if(svs[i].type==S_AUTO && !aidx) aidx=i;

        /* when we get to the function we're finished */
        if(svs[i].type==S_FILE) break;
    }

    /* have'nt found any variable named like this one */
    /* first check the globals */
    if(!(vp=eppic_inglobs(name))) {

        int off=0;

        /* check the API for a corresponding symbol */
        /* Jump over possible leading "IMG_" prefix */
        if(!strncmp(name, "IMG_", 4)) off=4;
        if(!local) {
            vp=eppic_newvar(name);
            if(API_GETVAL(name+off, &apiv, eppic_legacy?0:vp->v)) {
                vp->ini=1;
                if(eppic_legacy) {
                    eppic_defbtype(vp->v, apiv);
                    vp->v->mem=apiv;
                }
                /* put this on the global list */
                eppic_enqueue(apiglobs, vp);
            }
            else {
                eppic_freevar(vp);
                vp=0;
            }
        }
        else {

            if(silent) return 0;
            eppic_error("Unknown variable [%s]", name);
        }
    }
    return vp;
}
예제 #15
0
idx_t *
eppic_newidx(node_t*n)
{
idx_t *idx;

    if(!instruct) {

        eppic_error("Array supported only in struct/union declarations");
    }
    idx=eppic_alloc(sizeof(idx_t));
    idx->nidx=1;
    idx->idxs[0]=n;
    return idx;
}
예제 #16
0
void
eppic_addtolist(var_t*vl, var_t*v)
{
    if(!v->name[0] || !eppic_inlist(v->name, vl)) {

        eppic_enqueue(vl, v);

    } else {

        /* if this is a prototype declaration then skip it */
        if(v->dv && v->dv->fct) return;

        eppic_error("Duplicate declaration of variable %s", v->name);
    }
}
예제 #17
0
void
eppic_pushjmp(int type, void *venv, void *val)
{
jmp_buf *env=(jmp_buf *)venv;

    if(njmps<MAXJMPS) {

        jmps[njmps].type=type;
        jmps[njmps].val=(value_t**)val;
        jmps[njmps].env=env;
        jmps[njmps++].svlev=eppic_getsvlev();

    } else {

        eppic_error("Jump Stack overflow");

    }
}
예제 #18
0
void
eppic_valindex(value_t *var, value_t *idx, value_t *ret)
{
    if(is_ctype(idx->type.type)) {

        eppic_error("Invalid indexing type");

    } else {

        array_t*a;

        a=eppic_getarrval(&var->arr, idx);

        /* this is the first level of indexing through a variable */
        eppic_dupval(ret, a->val);
        ret->set=1;
        ret->setval=a->val;
    }
}
예제 #19
0
/* get the name of a function through a variable */
char *
eppic_vartofunc(node_t*name)
{
char *vname=NODE_NAME(name);
value_t *val;

    /* if the nore is a general expression, then vname is 0 */
    if(!vname) {

        val=eppic_exenode(name);

    } else  {

        var_t*v;
        
        v=eppic_getvarbyname(vname, 1, 1);
        if(!v) return vname;
        val=v->v;
    }

    switch(val->type.type)
    {
        case V_STRING:
        {
        char *p=eppic_alloc(val->type.size+1);
            /* return the value_t of that string variable */
            strcpy(p, val->v.data);
            eppic_free(vname);
            return p;
        }
        default:
            /* return the name of the variable itself */
            eppic_error("Invalid type for function pointer, expected 'string'.");
            return vname;
    }
}
예제 #20
0
파일: eppic_op.c 프로젝트: lucchouina/eppic
void
eppic_do_deref(int n, value_t *v, value_t *ref)
{
ull madr, new_madr;

    if(n > ref->type.ref) {

        eppic_error("Too many levels of dereference");

    }else {
    

        if(eppic_defbsize()==4) madr=(ull)ref->v.ul;
        else madr=ref->v.ull;

        /* copy the target type to the returned value_t's type_t*/
        eppic_duptype(&v->type, &ref->type);

        /* do a number of deferences according to PTR value_t */
        while(n--) {

            eppic_popref(&v->type, 1);

            if(!v->type.ref) {

                /* make sure the pointer is pointing into the vmcore */
                if(is_ctype(v->type.type)) {

                    v->v.data=eppic_alloc(v->type.size);
                    eppic_getmem(madr, v->v.data, v->type.size);

                } else {

                    /* get the data from the system image */
                    switch(TYPE_SIZE(&v->type)) {

                        case 1: eppic_getmem(madr, &v->v.uc, 1); 
                            break;
                        case 2: eppic_getmem(madr, &v->v.us, 2); 
                            break;
                        case 4: eppic_getmem(madr, &v->v.ul, 4);
                            break;
                        case 8: eppic_getmem(madr, &v->v.ull, 8); 
                            break;

                    }
                }
            }
            else {
        
                /* get the pointer at this address */
                if(eppic_defbsize()==4) {

                    eppic_getmem(madr, &v->v.ul, 4);
                    new_madr=v->v.ul;

                } else {

                    eppic_getmem(madr, &v->v.ull, 8);
                    new_madr=v->v.ull;
                }
            }

            /* remember this address. For the '&' operator */
            v->mem=madr;
            madr=new_madr;
        }
    }

    /* we can always assign to a reference */
    v->set=1;
    v->setval=v;
    v->setfct=eppic_setderef;
}
예제 #21
0
파일: eppic_op.c 프로젝트: lucchouina/eppic
static value_t *
eppic_exeop(oper *o)
{
value_t *v=0, *v1=0, *v2=0, *v3=0, *v4=0;
int top;
srcpos_t p;

    eppic_curpos(&o->pos, &p);

    /* if ME (op on myself) operator, translate to normal operator
       we will re-assign onto self when done */

    top=getop(o->op);

    if(top == ASSIGN) {

        goto doop;

    } else if(top == IN) {

        /* the val in array[] test is valid for anything but struct/union */
        v=eppic_makebtype((ull)eppic_lookuparray(P1,P2));

    }
    else if(is_cond(top)) {

        /* the operands are eithr BASE (integer) or REF (pointer) */ 
        /* all conditional operators accept a mixture of pointers and integer */
        /* set the return as a basetype even if bool */

        switch(top) {

            case CEXPR: {   /* conditional expression expr ? : stmt : stmt */

                if(eppic_bool(V1)) {

                    v=eppic_cloneval(V2);

                } else {

                    v=eppic_cloneval(V3);

                }

            }
            break;
            case BOR: { /* a || b */

                v=eppic_makebtype((ull)(eppic_bool(V1) || eppic_bool(V2)));

            }
            break;
            case BAND: {    /* a && b */

                v=eppic_makebtype((ull)(eppic_bool(V1) && eppic_bool(V2)));

            }
            break;
            case NOT: { /* ! expr */

                v=eppic_makebtype((ull)(! eppic_bool(V1)));

            }
            break;
            default: {

                v=eppic_docomp(top, V1, V2);

            }
        }

    } else if(anyop(V_STRING)) {

        if(top == ADD) 
        {
        char *buf;

            if(V1->type.type != V_STRING || V2->type.type != V_STRING) {

                eppic_rerror(&P1->pos, "String concatenation needs two strings!");

            }
            buf=eppic_alloc(strlen(S1)+strlen(S2)+1);
            strcpy(buf, S1);
            strcat(buf, S2);
            v=eppic_makestr(buf);
            eppic_free(buf);
        }
        else {

            eppic_rerror(&P1->pos, "Invalid string operator");

        }
    }
    /* arithmetic operator */
    else if(anyop(V_REF)) { 

        int size;
        value_t *vt;

        /* make sure we have the base type second */
        if(V1->type.type != V_REF) { vt=V1; v1=V2; v2=vt; }


        if(V1->type.type == V_BASE) {
inval:
            eppic_error("Invalid operand on pointer operation");
        }

        /* get the size of whas we reference */
        size=V1->type.size;
    
        switch(top) {
            case ADD: { /* expr + expr */
                /* adding two pointers ? */
                if(V2->type.type == V_REF) goto inval;

                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) + L2 * size);
            }
            break;
            case SUB: { /* expr - expr */
                /* different results if mixed types.
                   if both are pointers then result is a V_BASE */
                if(V2->type.type == V_REF)
                    v=eppic_makebtype(L1 - L2);

                else {
                    V1;
                    eppic_transfer(v=eppic_newval(), v1,
                              unival(v1) - L2 * size);
                }
            }
            break;
            case PREDECR: { /* pre is easy */
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) - size);
                eppic_setval(v1, v);
            }
            break;
            case PREINCR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) + size);
                eppic_setval(v1, v);
            }
            break;
            case POSTINCR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) + size);
                eppic_setval(v1, v);
                eppic_transfer(v, v1, unival(v1));
            }
            break;
            case POSTDECR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) - size);
                eppic_setval(v1, v);
                eppic_transfer(v, v1, unival(v1));
            }
            break;
            default:
                eppic_error("Invalid operation on pointer [%d]",top);
        }
    }
    else {

        /* both operands are V_BASE */
        switch(top) {

            /* for mod and div, we check for divide by zero */
            case MOD: case DIV:
                if(!L2) {
                    eppic_rerror(&P1->pos, "Mod by zero");
                }
            case ADD: case SUB: case MUL: case XOR: 
            case OR: case AND: case SHL: case SHR:
            {
                eppic_baseop(top, V1, V2, v=eppic_newval());
            }
            break;
            case UMINUS: {

                value_t *v0=eppic_newval();
                eppic_defbtype(v0, (ull)0);
                /* keep original type of v1 */
                v=eppic_newval();
                eppic_duptype(&v0->type, &V1->type);
                eppic_duptype(&v->type, &V1->type);
                eppic_baseop(SUB, v0, V1, v);
                eppic_freeval(v0);
                /* must make result signed */
                eppic_mkvsigned(v);
            }
            break;
            case FLIP: {

                value_t *v0=eppic_newval();
                eppic_defbtype(v0, (ull)0xffffffffffffffffll);
                /* keep original type of v1 */
                eppic_duptype(&v0->type, &V1->type);
                eppic_baseop(XOR, v0, V1, v=eppic_newval());
                eppic_freeval(v0);
            }
            break;
            case PREDECR: { /* pre is easy */
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) - 1);
                eppic_setval(v1, v);
            }
            break;
            case PREINCR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) + 1);
                eppic_setval(v1, v);
            }
            break;
            case POSTINCR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) + 1);
                eppic_setval(v1, v);
                eppic_transfer(v, v1, unival(v1));
            }
            break;
            case POSTDECR: {
                V1;
                eppic_transfer(v=eppic_newval(), v1,
                          unival(v1) - 1);
                eppic_setval(v1, v);
                eppic_transfer(v, v1, unival(v1));
            }
            break;
            default: eppic_rerror(&P1->pos, "Oops ops ! [%d]", top);
        }
    }
doop:
    /* need to assign the value_t back to P1 */
    if(top != o->op || top==ASSIGN) {

        /* in the case the Lvalue_t is a variable , bypass execution and set ini */
        if(P1->exe == eppic_exevar) {

            char *name=NODE_NAME(P1);
            var_t*va=eppic_getvarbyname(name, 0, 0);
            value_t *vp;

            eppic_free(name);

            if(top != o->op) vp=v;
            else vp=V2;

            eppic_chkandconvert(va->v, vp);

            eppic_freeval(v);
            v=eppic_cloneval(va->v);
            va->ini=1;

        } else {

            if(!(V1->set)) {

                eppic_rerror(&P1->pos, "Not Lvalue_t on assignment");

            }
            else {

                /* if it's a Me-op then v is already set */
                V1;
                if(top != o->op) {
                    eppic_setval(v1, v);
                } else {
                    eppic_setval(v1, V2);
                    v=eppic_cloneval(V2);
                }

            }
        }
        /* the result of a assignment if not an Lvalue_t */
        v->set=0;
    }
    eppic_freeval(v1);
    eppic_freeval(v2);
    eppic_freeval(v3);
    eppic_freeval(v4);
    eppic_setpos(&p);
    return v;
}
예제 #22
0
파일: eppic_op.c 프로젝트: lucchouina/eppic
static value_t*
eppic_docomp(int op, value_t *v1, value_t *v2)
{

    /* if one parameter is string then both must be */
    if(v1->type.type == V_STRING || v2->type.type == V_STRING) {

        if(v1->type.type != V_STRING || v2->type.type != V_STRING) {

            eppic_error("Invalid condition arguments");
        }
        else {

            switch(op) {

                case EQ: {  /* expr == expr */

                    return eppic_makebtype(!strcmp(v1->v.data, v2->v.data));

                }
                case GT: case GE: { /* expr > expr */

                    return eppic_makebtype(strcmp(v1->v.data, v2->v.data) > 0);

                }
                case LE: case LT: { /* expr <= expr */

                    return eppic_makebtype(strcmp(v1->v.data, v2->v.data) < 0);

                }
                case NE: {  /* expr != expr */

                    return eppic_makebtype(strcmp(v1->v.data, v2->v.data));

                }
                default: {

                    eppic_error("Oops conditional unknown 1");

                }
            }
        }

    }
    else {

        int idx1, idx2;
        value_t *v=eppic_newval();

        /* make sure pointers are forced to proper basetype
           before calling eppic_baseop()*/
        idx1=eppic_reftobase(v1);
        idx2=eppic_reftobase(v2);
        

        switch(op) {

            case EQ:
            case GT:
            case GE: 
            case LE:
            case LT:
            case NE:
                eppic_baseop(op, v1, v2, v);
            break;
            default: {

                eppic_error("Oops conditional unknown 2");

            }
        }
        v1->type.idx=idx1;
        v2->type.idx=idx2;
        return v;
    }
    return 0;
}
예제 #23
0
/*
    this is the main variable declaration function.
    We support the global scope attribute that make the declared
    variable accessible to all function from all scripts.

    By default the scope of a variable either the statement block
    where it was declared (or first used):
    {
    int var;
     ...
    }
    Then it's scope is the block itself.

    Or the file, if it was declared outside of a function.

    Storage is by default 'automatic' and can be made permanent
    by using the 'static' keywork in the declaration.
    'Volatile' and 'register' storage classes are supported but 
    have no effect.
*/
var_t*
eppic_vardecl(dvar_t*dv, type_t*t)
{
var_t*vlist=eppic_newvlist();
var_t*var;

    /* type *and* dv can have ref counts. First comes from typedef parsing
       second comes from the declaration itself */
    dv->ref += t->ref;
    
    /* add one level of ref for arrays */
    if(dv->idx) dv->ref++;

    /* reset ref level for tests below */
    eppic_popref(t, t->ref);

    TAG(vlist);

    if(!t->type) {

        int sto=eppic_isstor(t->typattr);

        eppic_freetype(t);
        t=eppic_newbtype(0);
        t->typattr |= sto;
    }
    else if(t->type==V_BASE && !dv->ref) {

        eppic_chksign(t);
        eppic_chksize(t);
    }

    /* is this a new typedef declaration ? */
    /* typedef is considered just like any other storage class */
    if(eppic_istdef(t->typattr)) {

        eppic_tdef_decl(dv, t);
        return 0;
    }

    while(dv) {
        
        /* disalow var names that match against already defined vars */
        if(dv->name[0]) {
            type_t *t=eppic_getctype(V_TYPEDEF, dv->name, 1);
            if(t) {

                eppic_freetype(t);
                eppic_warning("Variable '%s' already defined as typedef.\n");
            }
        }

        /* 
           some sanity checks here that apply to both var and struct 
           declarations 
        */
        if(is_ctype(t->type) && !dv->ref) {

            if(dv->name[0]) {

                if(!instruct) {

                    if(!eppic_isxtern(t->typattr)) {

                        eppic_freesvs(vlist);
                        eppic_error("struct/union instances not supported, please use pointers");
                    }

                } else if(eppic_ispartial(t)) {

                    eppic_freesvs(vlist);
                    eppic_error("Reference to incomplete type");
                }
            }
        }
        if(dv->nbits) { 

            if(t->type != V_BASE) {

                eppic_freesvs(vlist);
                eppic_error("Bit fields can only be of integer type");

            }
            if(dv->idx) {

                eppic_freesvs(vlist);
                eppic_error("An array of bits ? Come on...");
            }
        }

        var=eppic_newvar(dv->name);

        t->fct=dv->fct;
        eppic_duptype(&var->v->type, t);
        eppic_pushref(&var->v->type, dv->ref);

        var->dv=dv;

        TAG(var);

        if(t->type == V_STRING) {

            eppic_setstrval(var->v, "");

        } 

        eppic_setpos(&dv->pos);

        /* toff */
        /* add to parsing list */  
        if(var->name[0]) {
           var_t *plist=eppic_newvlist();
           eppic_enqueue(plist, var);
           eppic_addsvs(S_PARSE, eppic_dupvlist(plist));
        }
        eppic_enqueue(vlist, var);
next:
        dv=dv->next;
    }
    eppic_free(t);
    TAG(vlist);
    return vlist;
}