Beispiel #1
0
/* Result is pool'd*/
char*
prefixtostring(List* prefix, char* separator)
{
    int slen=0;
    int plen;
    int i;
    char* result;
    if(prefix == NULL) return pooldup("");
    plen = prefixlen(prefix);
    if(plen == 0) { /* root prefix*/
	slen=0;
        /* slen += strlen(separator);*/
        slen++; /* for null terminator*/
        result = poolalloc(slen);
        result[0] = '\0';
	/*strcat(result,separator);*/
    } else {
        for(i=0;i<plen;i++) {
	    Symbol* sym = (Symbol*)listget(prefix,i);
            slen += (strlen(separator)+strlen(sym->name));
	}
        slen++; /* for null terminator*/
        result = poolalloc(slen);
        result[0] = '\0';
        for(i=0;i<plen;i++) {
	    Symbol* sym = (Symbol*)listget(prefix,i);
            strcat(result,separator);
	    strcat(result,sym->name); /* append "/<prefix[i]>"*/
	}
    }    
    return result;
}
Beispiel #2
0
static void
processattributes(void)
{
    int i,j;
    /* process global attributes*/
    for(i=0;i<listlength(gattdefs);i++) {
	Symbol* asym = (Symbol*)listget(gattdefs,i);
	/* If the attribute has a zero length, then default it */
	if(asym->data == NULL || asym->data->length == 0) {
	    asym->data = builddatalist(1);
	    emptystringconst(asym->lineno,&asym->data->data[asym->data->length]);
	    /* force type to be NC_CHAR */
	    asym->typ.basetype = primsymbols[NC_CHAR];
	}
	if(asym->typ.basetype == NULL) inferattributetype(asym);
        /* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
    }
    /* process per variable attributes*/
    for(i=0;i<listlength(attdefs);i++) {
	Symbol* asym = (Symbol*)listget(attdefs,i);
	/* If the attribute has a zero length, then default it */
	if(asym->data == NULL || asym->data->length == 0) {
	    asym->data = builddatalist(1);
	    emptystringconst(asym->lineno,&asym->data->data[asym->data->length]);
	    /* force type to be NC_CHAR */
	    asym->typ.basetype = primsymbols[NC_CHAR];
	}
	/* If no basetype is specified, then try to infer it;
           the exception if _Fillvalue, whose type is that of the
           containing variable.
        */
        if(strcmp(asym->name,specialname(_FILLVALUE_FLAG)) == 0) {
	    /* This is _Fillvalue */
	    asym->typ.basetype = asym->att.var->typ.basetype; /* its basetype is same as its var*/
	    /* put the datalist into the specials structure */
	    if(asym->data == NULL) {
		/* Generate a default fill value */
	        asym->data = getfiller(asym->typ.basetype);
	    }
	    asym->att.var->var.special._Fillvalue = asym->data;
	} else if(asym->typ.basetype == NULL) {
	    inferattributetype(asym);
	}
	/* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
    }
    /* collect per-variable attributes per variable*/
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* vsym = (Symbol*)listget(vardefs,i);
	List* list = listnew();
        for(j=0;j<listlength(attdefs);j++) {
	    Symbol* asym = (Symbol*)listget(attdefs,j);
	    ASSERT(asym->att.var != NULL);
	    if(asym->att.var != vsym) continue;	    
            listpush(list,(void*)asym);
	}
	vsym->var.attributes = list;
    }
}
Beispiel #3
0
static void
processenums(void)
{
    unsigned long i,j;
#if 0 /* Unused? */
    List* enumids = listnew();
#endif
    for(i=0;i<listlength(typdefs);i++) {
	Symbol* sym = (Symbol*)listget(typdefs,i);
	ASSERT(sym->objectclass == NC_TYPE);
	if(sym->subclass != NC_ENUM) continue;
	for(j=0;j<listlength(sym->subnodes);j++) {
	    Symbol* esym = (Symbol*)listget(sym->subnodes,j);
	    ASSERT(esym->subclass == NC_ECONST);
#if 0 /* Unused? */
	    listpush(enumids,(void*)esym);
#endif
	}
    }
    /* Convert enum values to match enum type*/
    for(i=0;i<listlength(typdefs);i++) {
	Symbol* tsym = (Symbol*)listget(typdefs,i);
	ASSERT(tsym->objectclass == NC_TYPE);
	if(tsym->subclass != NC_ENUM) continue;
	for(j=0;j<listlength(tsym->subnodes);j++) {
	    Symbol* esym = (Symbol*)listget(tsym->subnodes,j);
	    NCConstant* newec = nullconst();
	    ASSERT(esym->subclass == NC_ECONST);
	    newec->nctype = esym->typ.typecode;
	    convert1(esym->typ.econst,newec);
	    reclaimconstant(esym->typ.econst);
	    esym->typ.econst = newec;
	}
    }
}
Beispiel #4
0
/*
Compute the fqn for every top-level definition symbol
*/
static void
computefqns(void)
{
    unsigned long i,j;
    /* Groups first */
    for(i=0;i<listlength(grpdefs);i++) {
        Symbol* sym = (Symbol*)listget(grpdefs,i);
	topfqn(sym);
    }
    /* Dimensions */
    for(i=0;i<listlength(dimdefs);i++) {
        Symbol* sym = (Symbol*)listget(dimdefs,i);
	topfqn(sym);
    }
    /* types */
    for(i=0;i<listlength(typdefs);i++) {
        Symbol* sym = (Symbol*)listget(typdefs,i);
	topfqn(sym);
    }
    /* variables */
    for(i=0;i<listlength(vardefs);i++) {
        Symbol* sym = (Symbol*)listget(vardefs,i);
	topfqn(sym);
    }
    /* fill in the fqn names of econsts */
    for(i=0;i<listlength(typdefs);i++) {
        Symbol* sym = (Symbol*)listget(typdefs,i);
	if(sym->subclass == NC_ENUM) {
	    for(j=0;j<listlength(sym->subnodes);j++) {
		Symbol* econ = (Symbol*)listget(sym->subnodes,j);
		nestedfqn(econ);
	    }
	}
    }
    /* fill in the fqn names of fields */
    for(i=0;i<listlength(typdefs);i++) {
        Symbol* sym = (Symbol*)listget(typdefs,i);
	if(sym->subclass == NC_COMPOUND) {
	    for(j=0;j<listlength(sym->subnodes);j++) {
		Symbol* field = (Symbol*)listget(sym->subnodes,j);
		nestedfqn(field);
	    }
	}
    }
    /* fill in the fqn names of attributes */
    for(i=0;i<listlength(gattdefs);i++) {
        Symbol* sym = (Symbol*)listget(gattdefs,i);
        attfqn(sym);
    }
    for(i=0;i<listlength(attdefs);i++) {
        Symbol* sym = (Symbol*)listget(attdefs,i);
        attfqn(sym);
    }
}
Beispiel #5
0
static void
processtypesizes(void)
{
    int i;
    /* use touch flag to avoid circularity*/
    for(i=0;i<listlength(typdefs);i++) {
	Symbol* tsym = (Symbol*)listget(typdefs,i);
	tsym->touched = 0;
    }
    for(i=0;i<listlength(typdefs);i++) {
	Symbol* tsym = (Symbol*)listget(typdefs,i);
	computesize(tsym); /* this will recurse*/
    }
}
Beispiel #6
0
void
processvars(void)
{
    int i,j;
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* vsym = (Symbol*)listget(vardefs,i);
	Symbol* basetype = vsym->typ.basetype;
        /* If we are in classic mode, then convert long -> int32 */
	if(usingclassic) {
	    if(basetype->typ.typecode == NC_LONG || basetype->typ.typecode == NC_INT64) {
	        vsym->typ.basetype = primsymbols[NC_INT];
		basetype = vsym->typ.basetype;
	    }
        }
	/* fill in the typecode*/
	vsym->typ.typecode = basetype->typ.typecode;
	/* validate uses of NIL */
        validateNIL(vsym);
	for(j=0;j<vsym->typ.dimset.ndims;j++) {
	    /* validate the dimensions*/
            /* UNLIMITED must only be in first place if using classic */
	    if(vsym->typ.dimset.dimsyms[j]->dim.declsize == NC_UNLIMITED) {
	        if(usingclassic && j != 0)
		    semerror(vsym->lineno,"Variable: %s: UNLIMITED must be in first dimension only",fullname(vsym));
	    }
	}
    }
}
Beispiel #7
0
void
dumpgroup(Symbol* g)
{
    if(debug <= 1) return; 
    fdebug("group %s {\n",(g==NULL?"null":g->name));
    if(g != NULL && g->subnodes != NULL) {    
	int i;
	for(i=0;i<listlength(g->subnodes);i++) {
	    Symbol* sym = (Symbol*)listget(g->subnodes,i);
	    char* tname;
	    if(sym->objectclass == NC_PRIM
	       || sym->objectclass == NC_TYPE) {
		tname = nctypename(sym->subclass);
	    } else
		tname = nctypename(sym->objectclass);
	    fdebug("    %3d:  %s\t%s\t%s\n",
		i,
		sym->name,
		tname,
		(sym->ref.is_ref?"ref":"")
		);
	}
    }
    fdebug("}\n");
}
static void
fill(Symbol* tvsym, Datalist* filler)
{
    int i;
    Constant con;
    Datalist* sublist;
    /* NC_TYPE case*/
    switch (tvsym->subclass) {
    case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
        con.nctype = tvsym->typ.typecode;
        nc_getfill(&con);
	break;
    case NC_COMPOUND:
	sublist = builddatalist(listlength(tvsym->subnodes));
        for(i=0;i<listlength(tvsym->subnodes);i++) {
	    Symbol* field = (Symbol*)listget(tvsym->subnodes,i);
	    if(field->typ.dimset.ndims > 0) {	
                fillarray(field->typ.basetype,&field->typ.dimset,0,filler);
	    } else
		filllist(field->typ.basetype,sublist);
        }	  
	con = builddatasublist(sublist);
	break;
    case NC_VLEN:
	sublist = builddatalist(0);
	filllist(tvsym->typ.basetype,sublist); /* generate a single instance*/
	con = builddatasublist(sublist);
	break;
    default: PANIC1("fill: unexpected subclass %d",tvsym->subclass);
    }
    dlappend(filler,&con);
}
Beispiel #9
0
static int
bin_reclaim_compound(Symbol* tsym, Reclaim* reclaimer)
{
    int stat = NC_NOERR;
    int nfields;
    size_t fid, i, arraycount;
    ptrdiff_t saveoffset;

    reclaimer->offset = read_alignment(reclaimer->offset,tsym->typ.cmpdalign);
    saveoffset = reclaimer->offset;

    /* Get info about each field in turn and reclaim it */
    nfields = listlength(tsym->subnodes);
    for(fid=0;fid<nfields;fid++) {
	Symbol* field = listget(tsym->subnodes,fid);
	int ndims = field->typ.dimset.ndims;
	/* compute the total number of elements in the field array */
	for(i=0;i<ndims;i++) arraycount *= field->typ.dimset.dimsyms[i]->dim.declsize;
	reclaimer->offset = read_alignment(reclaimer->offset,field->typ.alignment);
	for(i=0;i<arraycount;i++) {
	    if((stat = bin_reclaim_datar(field->typ.basetype, reclaimer))) goto done;
	}		
    }
    reclaimer->offset = saveoffset;
    reclaimer->offset += tsym->typ.size;
done:
    return stat;
}
Beispiel #10
0
/*
Locate enums whose name is a prefix of ident
and contains the suffix as an enum const
and capture that enum constant.
*/
static List*
findecmatches(char* ident)
{
    List* matches = listnew();
    int i;

    for(i=0;i<listlength(typdefs);i++) {
	int len;
	Symbol* ec;
	Symbol* en = (Symbol*)listget(typdefs,i);
	if(en->subclass != NC_ENUM)
	    continue;
        /* First, assume that the ident is the econst name only */
	ec = checkeconst(en,ident);
	if(ec != NULL)
	    listpush(matches,ec);
	/* Second, do the prefix check */
	len = strlen(en->name);
	if(strncmp(ident,en->name,len) == 0) {
		Symbol *ec;
		/* Find the matching ec constant, if any */
	    if(*(ident+len) != '.') continue;
	    ec = checkeconst(en,ident+len+1); /* +1 for the dot */
	    if(ec != NULL)
		listpush(matches,ec);
	}
    }
    if(listlength(matches) == 0) {
	listfree(matches);
        matches = NULL;
    }
    return matches;
}
Beispiel #11
0
static void
filllist(Symbol* tsym, Datalist* dl)
{
    int i;
    Datalist* sublist;
    NCConstant con;
    con.filled = 0;

    ASSERT(tsym->objectclass == NC_TYPE);
    switch (tsym->subclass) {
    case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
        con.nctype = tsym->typ.typecode;
        nc_getfill(&con);
	dlappend(dl,&con);
	break;
    case NC_COMPOUND:
	sublist = builddatalist(listlength(tsym->subnodes));
        for(i=0;i<listlength(tsym->subnodes);i++) {
	    Symbol* field = (Symbol*)listget(tsym->subnodes,i);
	    filllist(field->typ.basetype,sublist);
        }	  
	con = builddatasublist(sublist);
	dlappend(dl,&con);
	break;
    case NC_VLEN:
	sublist = builddatalist(0);
	filllist(tsym->typ.basetype,sublist); /* generate a single instance*/
	con = builddatasublist(sublist);
	dlappend(dl,&con);
	break;
    default: PANIC1("fill: unexpected subclass %d",tsym->subclass);
    }
}
Beispiel #12
0
static void
processunlimiteddims(void)
{
    int i;
    /* Set all unlimited dims to size 0; */
    for(i=0;i<listlength(dimdefs);i++) {
	Symbol* dim = (Symbol*)listget(dimdefs,i);
	if(dim->dim.isunlimited)
	    dim->dim.declsize = 0;
    }
    /* Walk all variables */
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* var = (Symbol*)listget(vardefs,i);
	int first,ischar;
	Dimset* dimset = &var->typ.dimset;
	if(dimset->ndims == 0) continue; /* ignore scalars */
	if(var->data == NULL) continue; /* no data list to walk */
	ischar = (var->typ.basetype->typ.typecode == NC_CHAR);
	first = findunlimited(dimset,0);
	if(first == dimset->ndims) continue; /* no unlimited dims */
	if(first == 0) {
	    computeunlimitedsizes(dimset,first,var->data,ischar);
	} else {
	    int j;
	    for(j=0;j<var->data->length;j++) {
	        NCConstant* con = var->data->data[j];
	        if(con->nctype != NC_COMPOUND)
		    semerror(con->lineno,"UNLIMITED dimension (other than first) must be enclosed in {}");
		else
	            computeunlimitedsizes(dimset,first,con->value.compoundv,ischar);
	    }
	}
    }
#ifdef GENDEBUG1
    /* print unlimited dim size */
    if(listlength(dimdefs) == 0)
        fprintf(stderr,"unlimited: no unlimited dimensions\n");
    else for(i=0;i<listlength(dimdefs);i++) {
	Symbol* dim = (Symbol*)listget(dimdefs,i);
	if(dim->dim.isunlimited)
	    fprintf(stderr,"unlimited: %s = %lu\n",
		    dim->name,
	            (unsigned long)dim->dim.declsize);
    }
#endif
}
Beispiel #13
0
static int
checkfill(Symbol* tsym, Datasrc* src)
{
    int i,iscmpd,result;
    Constant* con;
    Symbol* original = tsym;

    result = 1;
    switch (tsym->subclass) {
    case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
	con = srcnext(src);
	if(src == NULL) {
	    semerror(srcline(src),"%s: malformed _FillValue",original->name);
	    result = 0;
	} else if(con->nctype != tsym->typ.typecode) result = 0; /* wrong type*/
	break;

    case NC_COMPOUND:
        if(!issublist(src)) {/* fail on no compound*/
           semerror(srcline(src),"Compound constants must be enclosed in {..}");
        }
	srcpush(src);
        for(i=0;i<listlength(tsym->subnodes);i++) {
	    Symbol* field = (Symbol*)listget(tsym->subnodes,i);
	    result = checkfill(field,src,original);
	    if(!result) break;
        }	  
	srcpop(src);
	break;

    case NC_VLEN:
	if(!issublist(src)) {
	    semerror(srcline(src),"%s: vlen instances in _FillValue must be enclosed in {...}",original->name);
	    result = 0;
	} else {
	    srcpush(src);
            while(srcmore(src)) {
		result = checkfill(tsym->typ.basetype,src,original);
		if(!result) break;
	    }
	    srcpop(src);
	}
	break;

    case NC_FIELD:
	/* Braces are optional */
	if((iscmpd=issublist(src))) srcpush(src);
	if(tsym->typ.dimset.ndims > 0) {
            result = checkarray(tsym->typ.basetype,&tsym->typ.dimset,0,src,original,!TOPLEVEL);
	} else
	    result = checkfill(tsym->typ.basetype,src,original);
	if(iscmpd) srcpop(src);
	break;

    default: PANIC1("checkfillvalue: unexpected subclass %d",tsym->subclass);
    }
    return result;
}
Beispiel #14
0
static void
processspecials(void)
{
    int i;
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* vsym = (Symbol*)listget(vardefs,i);
	processspecial1(vsym);
    }
}
Beispiel #15
0
int
listcontains(List* l, void* elem)
{
    unsigned long i;
    for(i=0;i<listlength(l);i++) {
	if(elem == listget(l,i)) return 1;
    }
    return 0;
}
Beispiel #16
0
/* Make sure all typecodes are set if basetype is set*/
static void
filltypecodes(void)
{
    int i;
    for(i=0;i<listlength(symlist);i++) {
        Symbol* sym = listget(symlist,i);
	if(sym->typ.basetype != NULL && sym->typ.typecode == NC_NAT)
	    sym->typ.typecode = sym->typ.basetype->typ.typecode;
    }
}
Beispiel #17
0
static void
validate(void)
{
    int i;
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* sym = (Symbol*)listget(vardefs,i);
	if(sym->var.special._Fillvalue != NULL) {
	}
    }
}
Beispiel #18
0
static Symbol*
checkeconst(Symbol* en, const char* refname)
{
    int i;
    for(i=0;i<listlength(en->subnodes);i++) {
	Symbol* ec = (Symbol*)listget(en->subnodes,i);
	if(strcmp(ec->name,refname) == 0)
	    return ec;
    }
    return NULL;
}
Beispiel #19
0
static void
setconstlist(NCConstant* con, Datalist* dl)
{
#ifdef VERIFY
    int pos = verify(alldatalists,dl);
    if(pos >= 0) {
        dumpdatalist(listget(alldatalists,pos),"XXX");
    }
#endif
    con->value.compoundv = dl;
}
Beispiel #20
0
/* index of match */
static int
verify(List* all, Datalist* dl)
{
    int i;
    for(i=0;i<listlength(all);i++) {
	void* pi = listget(all,i);
	if(pi == dl)
	    return i;
    }
    return -1;
}
Beispiel #21
0
bool_t
varchunkspec_exists(int igrpid, int ivarid)
{
    int i;
    for(i=0;i<listlength(varchunkspecs);i++) {
	struct VarChunkSpec* spec = listget(varchunkspecs,i);
	if(spec->igrpid == igrpid && spec->ivarid == ivarid)
	    return true;
    }
    return false;
}
Beispiel #22
0
bool_t
varchunkspec_omit(int igrpid, int ivarid)
{
    int i;
    for(i=0;i<listlength(varchunkspecs);i++) {
	struct VarChunkSpec* spec = listget(varchunkspecs,i);
	if(spec->igrpid == igrpid && spec->ivarid == ivarid)
	    return spec->omit;
    }
    return dimchunkspecs.omit;
}
Beispiel #23
0
size_t*
varchunkspec_chunksizes(int igrpid, int ivarid)
{
    int i;
    for(i=0;i<listlength(varchunkspecs);i++) {
	struct VarChunkSpec* spec = listget(varchunkspecs,i);
	if(spec->igrpid == igrpid && spec->ivarid == ivarid)
	    return spec->chunksizes;
    }
    return NULL;
}
Beispiel #24
0
size_t
varchunkspec_rank(int igrpid, int ivarid)
{
    int i;
    for(i=0;i<listlength(varchunkspecs);i++) {
	struct VarChunkSpec* spec = listget(varchunkspecs,i);
	if(spec->igrpid == igrpid && spec->ivarid == ivarid)
	    return spec->rank;
    }
    return 0;
}
Beispiel #25
0
List*
prefixdup(List* prefix)
{
    List* dupseq;
    int i;
    if(prefix == NULL) return listnew();
    dupseq = listnew();
    listsetalloc(dupseq,listlength(prefix));
    for(i=0;i<listlength(prefix);i++) listpush(dupseq,listget(prefix,i));
    return dupseq;    
}
Beispiel #26
0
static int
sqContains(List* seq, Symbol* sym)
{
    int i;
    if(seq == NULL) return 0;
    for(i=0;i<listlength(seq);i++) {
        Symbol* sub = (Symbol*)listget(seq,i);
	if(sub == sym) return 1;
    }
    return 0;
}
Beispiel #27
0
int
listfreeall(List* l)
{
  if(l) {
    int i;
    for(i=0;i<listlength(l);i++) {
	void* elem = listget(l,i);
	if(elem != NULL) free(elem);
    }
  }
  return listfree(l);
}
Beispiel #28
0
static List*
ecsearchgrp(Symbol* grp, List* candidates)
{
    List* matches = listnew();
    int i,j;
    /* do the intersection of grp subnodes and candidates */
    for(i=0;i<listlength(grp->subnodes);i++) {
	Symbol* sub= (Symbol*)listget(grp->subnodes,i);
	if(sub->subclass != NC_ENUM)
	    continue;
	for(j=0;j<listlength(candidates);j++) {
	    Symbol* ec = (Symbol*)listget(candidates,j);
	    if(ec->container == sub)
		listpush(matches,ec);
	}
    }
    if(listlength(matches) == 0) {
        listfree(matches);
	matches = NULL;
    }
    return matches;
}
Beispiel #29
0
/* Walk all data lists looking for econst refs
   and convert to point to actual definition
*/
static void
processeconstrefs(void)
{
    unsigned long i;
    /* locate all the datalist and walk them recursively */
    for(i=0;i<listlength(gattdefs);i++) {
	Symbol* att = (Symbol*)listget(gattdefs,i);
	if(att->data != NULL && listlength(att->data) > 0)
	    processeconstrefsR(att,att->data);
    }
    for(i=0;i<listlength(attdefs);i++) {
	Symbol* att = (Symbol*)listget(attdefs,i);
	if(att->data != NULL && listlength(att->data) > 0)
	    processeconstrefsR(att,att->data);
    }
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* var = (Symbol*)listget(vardefs,i);
	if(var->data != NULL && listlength(var->data) > 0)
	    processeconstrefsR(var,var->data);
	if(var->var.special->_Fillvalue != NULL)
	    processeconstrefsR(var,var->var.special->_Fillvalue);
    }
}
Beispiel #30
0
static void
checkconsistency(void)
{
    int i;
    for(i=0;i<listlength(grpdefs);i++) {
	Symbol* sym = (Symbol*)listget(grpdefs,i);
	if(sym == rootgroup) {
	    if(sym->container != NULL)
	        PANIC("rootgroup has a container");
	} else if(sym->container == NULL && sym != rootgroup)
	    PANIC1("symbol with no container: %s",sym->name);
	else if(sym->container->ref.is_ref != 0)
	    PANIC1("group with reference container: %s",sym->name);
	else if(sym != rootgroup && !sqContains(sym->container->subnodes,sym))
	    PANIC1("group not in container: %s",sym->name);
	if(sym->subnodes == NULL)
	    PANIC1("group with null subnodes: %s",sym->name);
    }
    for(i=0;i<listlength(typdefs);i++) {
	Symbol* sym = (Symbol*)listget(typdefs,i);
        if(!sqContains(sym->container->subnodes,sym))
	    PANIC1("type not in container: %s",sym->name);
    }
    for(i=0;i<listlength(dimdefs);i++) {
	Symbol* sym = (Symbol*)listget(dimdefs,i);
        if(!sqContains(sym->container->subnodes,sym))
	    PANIC1("dimension not in container: %s",sym->name);
    }
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* sym = (Symbol*)listget(vardefs,i);
        if(!sqContains(sym->container->subnodes,sym))
	    PANIC1("variable not in container: %s",sym->name);
	if(!(isprimplus(sym->typ.typecode)
	     || sqContains(typdefs,sym->typ.basetype)))
	    PANIC1("variable with undefined type: %s",sym->name);
    }
}