Beispiel #1
0
void
generate_vardata(Symbol* vsym, Generator* generator, Writer writer, Bytebuffer* code)
{
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    Symbol* basetype = vsym->typ.basetype;
    Datalist* filler = getfiller(vsym);
    const size_t* start;
    const size_t* count;
    Odometer* odom;

    if(vsym->data == NULL) return;

    /* give the buffer a running start to be large enough*/
    if(!bbSetalloc(code, nciterbuffersize))
      return;

    if(rank == 0) {/*scalar case*/
        NCConstant* c0 = datalistith(vsym->data,0);
        generate_basetype(basetype,c0,code,filler,generator);
        writer(generator,vsym,code,0,NULL,NULL);
    } else {/*rank > 0*/
        /* First, create an odometer using all of the dimensions */
        odom = newodometer(dimset,NULL,NULL);
	start = odometerstartvector(odom);
	count = odometercountvector(odom);
	generate_array(vsym,code,filler,generator,writer);
    }
}
static void
f77data_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* codebuf, Datalist* fillsrc)
{
    Constant* prim;
    Constant target;

    prim = srcnext(src);
    if(prim == NULL) prim = &fillconstant;

    ASSERT(prim->nctype != NC_COMPOUND);

    if(prim->nctype == NC_FILLVALUE) {
	Datalist* filler = getfiller(basetype,fillsrc);
	ASSERT(filler->length == 1);
	srcpushlist(src,filler);
	bbAppend(codebuf,' ');
        f77data_primdata(basetype,src,codebuf,NULL);
	srcpop(src);
	goto done;
    }

    target.nctype = basetype->typ.typecode;

    convert1(prim,&target);
    bbCat(codebuf,f77data_const(&target));
    
done:
    return;
}
Beispiel #3
0
static void
generate_primdata(Symbol* basetype, Constant* prim, Bytebuffer* codebuf,
		  Datalist* filler, Generator* generator)
{
    Constant target;

    if(prim == NULL || isfillconst(prim)) {
	Datalist* fill = (filler==NULL?getfiller(basetype):filler);
	ASSERT(fill->length == 1);
	prim = datalistith(fill,0);
    }

    ASSERT(prim->nctype != NC_COMPOUND);

    target.nctype = basetype->typ.typecode;

    if(target.nctype != NC_ECONST) {
	convert1(prim,&target);
    }

    switch (target.nctype) {
    case NC_ECONST:
        if(basetype->subclass != NC_ENUM) {
	    semerror(constline(prim),"Conversion to enum not supported (yet)");
	} break;
     case NC_OPAQUE:
	setprimlength(&target,basetype->typ.size*2);
	break;
    default:
	break;
    }
    generator->constant(generator,&target,codebuf);
    
    return;
}
Beispiel #4
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 #5
0
void
genbin_fillvalue(Symbol* tsym, Datalist* fillsrc, Datasrc* src,
               Bytebuffer* memory)
{
    Datalist* list = NULL;

    ASSERT(tsym->objectclass == NC_TYPE);
    list = fillsrc;
    if(list == NULL) list = getfiller(tsym);
    srcpushlist(src,list);
    genbin_data(tsym,src,NULL,memory);
    srcpop(src);
}
Beispiel #6
0
static void
cdata_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* codebuf, Datalist* fillsrc)
{
    Constant* prim;
    Constant target;

    prim = srcnext(src);
    if(prim == NULL) prim = &fillconstant;

    ASSERT(prim->nctype != NC_COMPOUND);

    if(prim->nctype == NC_FILLVALUE) {
	Datalist* filler = getfiller(basetype,fillsrc);
	ASSERT(filler->length == 1);
	srcpushlist(src,filler);
	bbAppend(codebuf,' ');
        cdata_primdata(basetype,src,codebuf,NULL);
	srcpop(src);
	goto done;
    }

    target.nctype = basetype->typ.typecode;

    if(target.nctype != NC_ECONST) {
	convert1(prim,&target);
    }

    switch (target.nctype) {
    case NC_ECONST:
        if(basetype->subclass != NC_ENUM) {
	    semerror(prim->lineno,"Conversion to enum not supported (yet)");
	} else {
	    Datalist* econ = builddatalist(1);
	    Symbol* enumv = prim->value.enumv;
	    srcpushlist(src,econ);
	    dlappend(econ,&enumv->typ.econst);
	    cdata_primdata(enumv->typ.basetype,src,codebuf,fillsrc);
	    srcpop(src);
	 } break;
     case NC_OPAQUE: {
	    setprimlength(&target,basetype->typ.size*2);
	} break;
    default: break;
    }
    bbCat(codebuf,cdata_const(&target));
    
done:
    return;
}
Beispiel #7
0
static void
fixeconstref(Symbol* avsym, NCConstant* con)
{
    Symbol* basetype = NULL;
    Symbol* refsym = con->value.enumv;
    Symbol* varsym = NULL;
    int i;

    /* Figure out the proper type associated with avsym */
    ASSERT(avsym->objectclass == NC_VAR || avsym->objectclass == NC_ATT);

    if(avsym->objectclass == NC_VAR) {
        basetype = avsym->typ.basetype;
	varsym = avsym;
    } else { /*(avsym->objectclass == NC_ATT)*/ 
        basetype = avsym->typ.basetype;
	varsym = avsym->container;
	if(varsym->objectclass == NC_GRP)
	    varsym = NULL;
    }
    
    if(basetype->objectclass != NC_TYPE && basetype->subclass != NC_ENUM)
        semerror(con->lineno,"Enumconstant associated with a non-econst type");

    if(con->nctype == NC_FILLVALUE) {
	Datalist* filllist = NULL;
	NCConstant* filler = NULL;
	filllist = getfiller(varsym == NULL?basetype:varsym);
	if(filllist == NULL)
	    semerror(con->lineno, "Cannot determine enum constant fillvalue");
	filler = datalistith(filllist,0);
	con->value.enumv = filler->value.enumv;
	return;
    }

    for(i=0;i<listlength(basetype->subnodes);i++) {
	Symbol* econst = listget(basetype->subnodes,i);
	ASSERT(econst->subclass == NC_ECONST);
	if(strcmp(econst->name,refsym->name)==0) {
	    con->value.enumv = econst;
	    return;
	}
    }
    semerror(con->lineno,"Undefined enum or enum constant reference: %s",refsym->name);
}
Beispiel #8
0
void
generate_vardata(Symbol* vsym, Generator* generator, Writer writer, Bytebuffer* code)
{
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    Symbol* basetype = vsym->typ.basetype;
    Datalist* filler = getfiller(vsym);

    if(vsym->data == NULL) return;

    /* give the buffer a running start to be large enough*/
    bbSetalloc(code, nciterbuffersize);

    if(rank == 0) {/*scalar case*/
	Constant* c0 = datalistith(vsym->data,0);
        generate_basetype(basetype,c0,code,filler,generator);
        writer(generator,vsym,code,0,NULL,NULL);
    } else {/*rank > 0*/
	generate_array(vsym,code,filler,generator,writer);
    }
}
Beispiel #9
0
/* Used for compound instances */
static void
genbin_compound(Symbol* tsym, Datasrc* datasrc, Datalist* fillsrc, Bytebuffer* memory)
{
    int i;
    int base = bblength(memory);
    if(!issublist(datasrc)) {
        semerror(srcline(datasrc),"Compound data must be enclosed in {..}");
    }
    /* Use this datasrc list to get values for compound fields */
    srcpush(datasrc);
    for(i=0;i<listlength(tsym->subnodes);i++) {
        Symbol* field = (Symbol*)listget(tsym->subnodes,i);
	if(!srcmore(datasrc)) { /* generate a fill value*/
	    Datalist* fillsrc = getfiller(tsym);
	    genbin_data(field,datasrc,fillsrc,memory);
	} else
	    genbin_data(field,datasrc,NULL,memory);
    }
    srcpop(datasrc);
    /* Re: github issue 323: we may need to pad the end of the structure
       to make its size be a multiple of the largest alignment.
    */
    alignto(tsym->cmpdalignment,buf,base);
}
Beispiel #10
0
static void
generate_primdata(Symbol* basetype, NCConstant* prim, Bytebuffer* codebuf,
		  Datalist* filler, Generator* generator)
{
    NCConstant target;
    int match;

    if(prim == NULL || isfillconst(prim)) {
	Datalist* fill = (filler==NULL?getfiller(basetype):filler);
	ASSERT(fill->length == 1);
	prim = datalistith(fill,0);
    }

    ASSERT(prim->nctype != NC_COMPOUND);

    /* Verify that the constant is consistent with the type */
    match = 1;
    switch (prim->nctype) {
    case NC_CHAR:
    case NC_BYTE:
    case NC_SHORT:
    case NC_INT:
    case NC_FLOAT:
    case NC_DOUBLE:
    case NC_UBYTE:
    case NC_USHORT:
    case NC_UINT:
    case NC_INT64:
    case NC_UINT64:
    case NC_STRING:
	match = (basetype->subclass == NC_PRIM ? 1 : 0);
	break;

#ifdef USE_NETCDF4
    case NC_NIL:
	match = (basetype->subclass == NC_PRIM && basetype->typ.typecode == NC_STRING ? 1 : 0);
	break;

    case NC_OPAQUE:
	/* OPAQUE is also consistent with numbers */
	match = (basetype->subclass == NC_OPAQUE
		 || basetype->subclass == NC_PRIM ? 1 : 0);
	break;
    case NC_ECONST:
	match = (basetype->subclass == NC_ENUM ? 1 : 0);
	if(match) {
	    /* Make sure this econst belongs to this enum */
	    Symbol* ec = prim->value.enumv;
	    Symbol* en = ec->container;
	    match = (en == basetype);
	}
	break;
#endif
    default:
	match = 0;
    }
    if(!match) {
        semerror(constline(prim),"Data value is not consistent with the expected type: %s",
		 basetype->name);
    }

    target.nctype = basetype->typ.typecode;

    if(target.nctype != NC_ECONST) {
	convert1(prim,&target);
    }

    switch (target.nctype) {
    case NC_ECONST:
        if(basetype->subclass != NC_ENUM) {
	    semerror(constline(prim),"Conversion to enum not supported (yet)");
	} break;
     case NC_OPAQUE:
	normalizeopaquelength(&target,basetype->typ.size);
	break;
    default:
	break;
    }
    generator->constant(generator,&target,codebuf);

    return;
}
Beispiel #11
0
/* Generate an instance of the basetype */
void
generate_basetype(Symbol* tsym, NCConstant* con, Bytebuffer* codebuf, Datalist* filler, Generator* generator)
{
    Datalist* data;

    switch (tsym->subclass) {

    case NC_ENUM:
    case NC_OPAQUE:
    case NC_PRIM:
	if(islistconst(con)) {
	    semerror(constline(con),"Expected primitive found {..}");
	}
	generate_primdata(tsym,con,codebuf,filler,generator);
	break;

    case NC_COMPOUND: {
	int i,uid, nfields, dllen;
	if(con == NULL || isfillconst(con)) {
	    Datalist* fill = (filler==NULL?getfiller(tsym):filler);
	    ASSERT(fill->length == 1);
	    con = &fill->data[0];
	    if(!islistconst(con))
	        semerror(con->lineno,"Compound data fill value is not enclosed in {..}");
	}
	if(!islistconst(con)) {/* fail on no compound*/
	    semerror(constline(con),"Compound data must be enclosed in {..}");
        }
	data = con->value.compoundv;
        nfields = listlength(tsym->subnodes);
	dllen = datalistlen(data);
	if(dllen > nfields) {
	    semerror(con->lineno,"Datalist longer than the number of compound fields");
	    break;
	}
	generator->listbegin(generator,LISTCOMPOUND,listlength(tsym->subnodes),codebuf,&uid);
        for(i=0;i<nfields;i++) {
            Symbol* field = (Symbol*)listget(tsym->subnodes,i);
	    con = datalistith(data,i);
	    generator->list(generator,LISTCOMPOUND,uid,i,codebuf);
            generate_basetype(field,con,codebuf,NULL,generator);
	}
	generator->listend(generator,LISTCOMPOUND,uid,i,codebuf);
	} break;

    case NC_VLEN: {
	Bytebuffer* vlenbuf;
        int uid;
	size_t count;

	if(con == NULL || isfillconst(con)) {
	    Datalist* fill = (filler==NULL?getfiller(tsym):filler);
	    ASSERT(fill->length == 1);
	    con = &fill->data[0];
	    if(con->nctype != NC_COMPOUND) {
	        semerror(con->lineno,"Vlen data fill value is not enclosed in {..}");
	    }
	}

	if(!islistconst(con)) {
	    semerror(constline(con),"Vlen data must be enclosed in {..}");
        }
        data = con->value.compoundv;
        /* generate the nc_vlen_t instance*/
	vlenbuf = bbNew();
	if(tsym->typ.basetype->typ.typecode == NC_CHAR) {
	    gen_charvlen(data,vlenbuf);
	    generator->vlenstring(generator,vlenbuf,&uid,&count);
	} else {
    	    generator->listbegin(generator,LISTVLEN,data->length,codebuf,&uid);
            for(count=0;count<data->length;count++) {
	      NCConstant* con;
   	        generator->list(generator,LISTVLEN,uid,count,vlenbuf);
		con = datalistith(data,count);
                generate_basetype(tsym->typ.basetype,con,vlenbuf,NULL,generator);
	    }
   	    generator->listend(generator,LISTVLEN,uid,count,codebuf,(void*)vlenbuf);
	}
	generator->vlendecl(generator,codebuf,tsym,uid,count,vlenbuf);
	bbFree(vlenbuf);
        } break;

    case NC_FIELD:
	if(tsym->typ.dimset.ndims > 0) {
	    /* Verify that we have a sublist (or fill situation) */
	    if(con != NULL && !isfillconst(con) && !islistconst(con))
		semerror(constline(con),"Dimensioned fields must be enclose in {...}");
            generate_fieldarray(tsym->typ.basetype,con,&tsym->typ.dimset,codebuf,filler,generator);
	} else {
	    generate_basetype(tsym->typ.basetype,con,codebuf,NULL,generator);
	}
	break;

    default: PANIC1("generate_basetype: unexpected subclass %d",tsym->subclass);
    }
}
Beispiel #12
0
static void
generate_arrayr(Symbol* vsym,
               Bytebuffer* code,
               Datalist* list,
	       Odometer* odom,
               int dimindex,
               Datalist* filler,
               Generator* generator
              )
{
    Symbol* basetype = vsym->typ.basetype;
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    int lastunlimited;
    int typecode = basetype->typ.typecode;

    lastunlimited = findlastunlimited(dimset);
    if(lastunlimited == rank) lastunlimited = 0;

    ASSERT(rank > 0);
    ASSERT(dimindex >= 0 && dimindex < rank);

#ifdef CHARBUG
    ASSERT(typecode != NC_CHAR);
#else /*!CHARBUG*/
    if(dimindex == lastunlimited && typecode == NC_CHAR) {
	Bytebuffer* charbuf = bbNew();
	gen_leafchararray(dimset,dimindex,list,charbuf,filler);
	generator->charconstant(generator,code,charbuf);
	bbFree(charbuf);
    } else
#endif /*!CHARBUG*/
    if(dimindex == lastunlimited) {
	int uid,i;
	Odometer* slabodom;
	/* build a special odometer to walk the last few dimensions
	   (similar to case 2 above)
	*/
        slabodom = newsubodometer(odom,dimset,dimindex,rank);
	/* compute the starting offset in our datalist
	   (Assumes that slabodom->index[i] == slabodom->start[i])
        */
        generator->listbegin(generator,LISTDATA,list->length,code,&uid);
	for(i=0;odometermore(slabodom);i++) {
	    size_t offset = odometeroffset(slabodom);
        NCConstant* con = datalistith(list,offset);
#ifdef USE_NOFILL
	    if(nofill_flag && con == NULL)
		break;
#endif
            generator->list(generator,LISTDATA,uid,i,code);
            generate_basetype(basetype,con,code,filler,generator);
	    odometerincr(slabodom);
        }
        generator->listend(generator,LISTDATA,uid,i,code);
	odometerfree(slabodom);
    } else {
        /* If we are strictly to the left of the next unlimited
           then our datalist is a list of compounds representing
           the next unlimited; so walk the subarray from this index
	   upto next unlimited.
        */
	int i;
	Odometer* slabodom;
        int nextunlimited = findunlimited(dimset,dimindex+1);
	ASSERT((dimindex < nextunlimited
                && (dimset->dimsyms[nextunlimited]->dim.isunlimited)));
	/* build a sub odometer */
        slabodom = newsubodometer(odom,dimset,dimindex,nextunlimited);
	/* compute the starting offset in our datalist
	   (Assumes that slabodom->index[i] == slabodom->start[i])
        */
	for(i=0;odometermore(slabodom);i++) {
	    size_t offset = odometeroffset(slabodom);
        NCConstant* con = datalistith(list,offset);
#ifdef USE_NOFILL
	    if(nofill_flag && con == NULL)
		break;
#endif
	    if(con == NULL || con->nctype == NC_FILL) {
		if(filler == NULL)
		    filler = getfiller(vsym);
	        generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator);

	    } else if(!islistconst(con))
	        semwarn(constline(con),"Expected {...} representing unlimited list");
	    else {
	        Datalist* sublist = con->value.compoundv;
	        generate_arrayr(vsym,code,sublist,odom,nextunlimited,filler,generator);
	    }
	    odometerincr(slabodom);
        }
	odometerfree(slabodom);
    }
    return;
}
Beispiel #13
0
/* Recursive helper that does the bulk of the work */
static int
bin_generate_data_r(NCConstant* instance, Symbol* tsym, Datalist* fillvalue, Bytebuffer* databuf)
{
    int stat = NC_NOERR;

    if(instance->nctype == NC_FILLVALUE) {
        /* replace with fillvalue for the type */
	Datalist* filllist = (fillvalue == NULL ? getfiller(tsym) : fillvalue);
	ASSERT(datalistlen(filllist)==1)
	instance = datalistith(filllist,0);
    }

    switch (tsym->subclass) {
    case NC_PRIM: {
	switch (tsym->nc_id) {
        case NC_CHAR: {
            char* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_CHAR;
            convert1(instance,tmp);
            p = &tmp->value.charv;;
            bbAppendn(databuf,p,sizeof(char));
            reclaimconstant(tmp);
            } break;
        case NC_BYTE: {
            signed char* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_BYTE;
            convert1(instance,tmp);
            p = &tmp->value.int8v;
            bbAppendn(databuf,p,sizeof(signed char));
            reclaimconstant(tmp);
            } break;
        case NC_UBYTE: {
            unsigned char* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_UBYTE;
            convert1(instance,tmp);
            p = &tmp->value.uint8v;
            bbAppendn(databuf,p,sizeof(unsigned char));
            reclaimconstant(tmp);
            } break;
        case NC_SHORT: {
            short* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_SHORT;
            convert1(instance,tmp);
            p = &tmp->value.int16v;
            bbAppendn(databuf,p,sizeof(short));
            reclaimconstant(tmp);
            } break;
        case NC_USHORT: {
            unsigned short* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_USHORT;
            convert1(instance,tmp);
            p = &tmp->value.uint16v;
            bbAppendn(databuf,p,sizeof(unsigned short));
            reclaimconstant(tmp);
            } break;
        case NC_INT: {
            int* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_INT;
            convert1(instance,tmp);
            p = &tmp->value.int32v;
            bbAppendn(databuf,p,sizeof(int));
            reclaimconstant(tmp);
            } break;
        case NC_UINT: {
            unsigned int* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_UINT;
            convert1(instance,tmp);
            p = &tmp->value.uint32v;
            bbAppendn(databuf,p,sizeof(unsigned int));
            reclaimconstant(tmp);
            } break;
        case NC_INT64: {
            long long* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_INT64;
            convert1(instance,tmp);
            p = &tmp->value.int64v;
            bbAppendn(databuf,p,sizeof(long long));
            reclaimconstant(tmp);
            } break;
        case NC_UINT64: {
            unsigned long long* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_UINT64;
            convert1(instance,tmp);
            p = &tmp->value.uint64v;
            bbAppendn(databuf,p,sizeof(unsigned long long));
            reclaimconstant(tmp);
            } break;
        case NC_FLOAT: {
            float* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_FLOAT;
            convert1(instance,tmp);
            p = &tmp->value.floatv;
            bbAppendn(databuf,p,sizeof(float));
            reclaimconstant(tmp);
            } break;
        case NC_DOUBLE: {
            double* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_DOUBLE;
            convert1(instance,tmp);
            p = &tmp->value.doublev;
            bbAppendn(databuf,p,sizeof(double));
            reclaimconstant(tmp);
            } break;
        case NC_STRING: {
            char* p = NULL;
            NCConstant* tmp = nullconst();
            tmp->nctype = NC_STRING;
            convert1(instance,tmp);
            p = emalloc(tmp->value.stringv.len+1);
	    memcpy(p,tmp->value.stringv.stringv,tmp->value.stringv.len);
	    p[tmp->value.stringv.len] = '\0';
            bbAppendn(databuf,&p,sizeof(char*));
            reclaimconstant(tmp);
            } break;
	default: stat = NC_EINTERNAL; goto done; /* Should never happen */
	} break; /*switch*/
	} break; /*NC_PRIM*/
	
    case NC_ENUM: {
	Symbol* basetype = tsym->typ.basetype;
	/* Pretend */
	stat = bin_generate_data_r(instance,basetype,fillvalue,databuf);
        } break;
    case NC_OPAQUE: {
	unsigned char* bytes = NULL;
	size_t len = 0;
	if(instance->nctype != NC_OPAQUE)
	    {stat = NC_EBADTYPE; goto done;}
	/* Assume the opaque string has been normalized */
        bytes=makebytestring(instance->value.opaquev.stringv,&len);
	if(bytes == NULL) {stat = NC_ENOMEM; goto done;}
        bbAppendn(databuf,(void*)bytes,len);
	free(bytes);
        } break;
    case NC_VLEN: {
	Datalist* sublist = NULL;
	Bytebuffer* vlendata = NULL;
	nc_vlen_t p;
	if(instance->nctype != NC_COMPOUND) {
	    nclog(NCLOGERR,"Translating vlen: expected sublist");
	    stat = NC_EBADTYPE; goto done;
	}
	sublist = instance->value.compoundv;
	vlendata = bbNew();
	if((stat = binary_generate_data(sublist,tsym->typ.basetype,NULL,vlendata))) goto done;
	p.len = datalistlen(sublist);
	p.p = bbContents(vlendata);
        bbAppendn(databuf,(char*)&p,sizeof(nc_vlen_t));
        } break;
    case NC_COMPOUND: { /* The really hard one */
	size_t nfields, fid, i;
	Datalist* cmpd = instance->value.compoundv;
        write_alignment(tsym->typ.cmpdalign,databuf);
        /* Get info about each field in turn and build it*/
        nfields = listlength(tsym->subnodes);
        for(fid=0;fid<nfields;fid++) {
	    Symbol* field = listget(tsym->subnodes,fid);
	    NCConstant* fieldinstance = datalistith(cmpd,fid);
	    int ndims = field->typ.dimset.ndims;
	    size_t arraycount;
	    if(ndims == 0) {
	        ndims=1; /* fake the scalar case */
	    }
  	    /* compute the total number of elements in the field array */
	    arraycount = 1;
	    for(i=0;i<ndims;i++) arraycount *= field->typ.dimset.dimsyms[i]->dim.declsize;
	    write_alignment(field->typ.alignment,databuf);
	    /* Write the instances */
	    for(i=0;i<arraycount;i++) {
	        if((stat = bin_generate_data_r(fieldinstance, field->typ.basetype, NULL, databuf))) goto done;
	    }
	}		
        } break;

    default: stat = NC_EINTERNAL; goto done; /* Should never happen */
    }
done:
    return stat;
}
Beispiel #14
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(asym->typ.basetype == NULL) inferattributetype(asym);
        /* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
	if(asym->data != NULL && asym->data->length == 0) {
	    NCConstant* empty = NULL;
	    /* If the attribute has a zero length, then default it;
               note that it must be of type NC_CHAR */
	    if(asym->typ.typecode != NC_CHAR)
	        semerror(asym->lineno,"Empty datalist can only be assigned to attributes of type char",fullname(asym));
	    empty = emptystringconst(asym->lineno);
	    dlappend(asym->data,empty);
	}
	validateNIL(asym);
    }
    /* process per variable attributes*/
    for(i=0;i<listlength(attdefs);i++) {
	Symbol* asym = (Symbol*)listget(attdefs,i);
	/* If no basetype is specified, then try to infer it;
           the exception is _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);
	    }
	    if(asym->att.var->var.special->_Fillvalue != NULL)
	    	reclaimdatalist(asym->att.var->var.special->_Fillvalue);
	    asym->att.var->var.special->_Fillvalue = clonedatalist(asym->data);
	} else if(asym->typ.basetype == NULL) {
	    inferattributetype(asym);
	}
	/* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
	if(asym->data->length == 0) {
	    NCConstant* empty = NULL;
	    /* If the attribute has a zero length, and is char type, then default it */
	    if(asym->typ.typecode != NC_CHAR)
	        semerror(asym->lineno,"Empty datalist can only be assigned to attributes of type char",fullname(asym));
	    empty = emptystringconst(asym->lineno);
	    dlappend(asym->data,empty);
	}
	validateNIL(asym);
    }
    /* 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);
	    if(asym->att.var == NULL)
		continue; /* ignore globals for now */
	    if(asym->att.var != vsym) continue;
            listpush(list,(void*)asym);
	}
	vsym->var.attributes = list;
    }
}
Beispiel #15
0
/**
The basic idea is to split the set of dimensions into groups
and iterate over each group.  A group is defined as the
range of indices starting at an unlimited dimension upto
(but not including) the next unlimited.  The first group
starts at index 0, even if dimension 0 is not unlimited.
The last group is everything from the last unlimited
dimension thru the last dimension (index rank-1).
*/
static void
generate_arrayr(Symbol* vsym,
               Bytebuffer* code,
               Datalist* list,
               Odometer* odom,
               int dimindex,
               Datalist* filler,
               Generator* generator
              )
{
    int uid,i;
    Symbol* basetype = vsym->typ.basetype;
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    int lastunlimited = findlastunlimited(dimset);
    int nextunlimited = findunlimited(dimset,dimindex+1);
    int typecode = basetype->typ.typecode;
    int islastgroup = (lastunlimited == rank || dimindex >= lastunlimited || dimindex == rank-1);
    Odometer* subodom = NULL;

    ASSERT(rank > 0);
    ASSERT((dimindex >= 0 && dimindex < rank));

    if(islastgroup) {
        /* Handle NC_CHAR case separately */
        if(typecode == NC_CHAR) {
            Bytebuffer* charbuf = bbNew();
            gen_chararray(dimset,dimindex,list,charbuf,filler);
	    generator->charconstant(generator,code,charbuf);
	    bbFree(charbuf);
	} else {
            /* build a special odometer to walk the last few dimensions */
            subodom = newsubodometer(odom,dimset,dimindex,rank);
            generator->listbegin(generator,LISTDATA,list->length,code,&uid);
            for(i=0;odometermore(subodom);i++) {
                size_t offset = odometeroffset(subodom);
                NCConstant* con = datalistith(list,offset);
                generator->list(generator,LISTDATA,uid,i,code);
                generate_basetype(basetype,con,code,filler,generator);
                odometerincr(subodom);
            }
            generator->listend(generator,LISTDATA,uid,i,code);
            odometerfree(subodom); subodom = NULL;
	}
    } else {/* !islastgroup */
        /* Our datalist must be a list of compounds representing
           the next unlimited; so walk the subarray from this index
           upto next unlimited.
        */
        ASSERT((dimindex < nextunlimited));
        ASSERT((isunlimited(dimset,nextunlimited)));
        /* build a sub odometer */
        subodom = newsubodometer(odom,dimset,dimindex,nextunlimited);
        for(i=0;odometermore(subodom);i++) {
            size_t offset = odometeroffset(subodom);
            NCConstant* con = datalistith(list,offset);
            if(con == NULL || con->nctype == NC_FILL) {
                if(filler == NULL)
                    filler = getfiller(vsym);
                generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator);

            } else if(islistconst(con)) {
                Datalist* sublist = compoundfor(con);
                generate_arrayr(vsym,code,sublist,odom,nextunlimited,filler,generator);
            } else {
                semerror(constline(con),"Expected {...} representing unlimited list");
                return;
            }
            odometerincr(subodom);
        }
        odometerfree(subodom); subodom = NULL;
    }
    if(subodom != NULL)
        odometerfree(subodom);
    return;
}
Beispiel #16
0
/* Generate an instance of the basetype using datasrc */
void
cdata_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* codebuf, Datalist* fillsrc)
{
    int usecmpd;

    switch (tsym->subclass) {

    case NC_ENUM:
    case NC_OPAQUE:
    case NC_PRIM:
	if(issublist(datasrc)) {
	    semerror(srcline(datasrc),"Expected primitive found {..}");
	}
	bbAppend(codebuf,' ');
	cdata_primdata(tsym,datasrc,codebuf,fillsrc);
	break;

    case NC_COMPOUND: {
	int i;
        Constant* con;
	if(!isfillvalue(datasrc) && !issublist(datasrc)) {/* fail on no compound*/
	    semerror(srcline(datasrc),"Compound data must be enclosed in {..}");
        }
        con = srcnext(datasrc);
	if(con->nctype == NC_FILLVALUE) {
	    Datalist* filler = getfiller(tsym,fillsrc);
	    ASSERT(filler->length == 1);
	    con = &filler->data[0];
	    if(con->nctype != NC_COMPOUND) {
	        semerror(con->lineno,"Compound data fill value is not enclosed in {..}");
	    }
	}
        srcpushlist(datasrc,con->value.compoundv); /* enter the sublist*/
        bbAppend(codebuf,'{');
        for(i=0;i<listlength(tsym->subnodes);i++) {
            Symbol* field = (Symbol*)listget(tsym->subnodes,i);
            bbAppend(codebuf,' ');
            cdata_basetype(field,datasrc,codebuf,NULL);
	}
        bbAppend(codebuf,'}');
        srcpop(datasrc);
	} break;

    case NC_VLEN: {
        Constant* con;
	if(!isfillvalue(datasrc) && !issublist(datasrc)) {/* fail on no compound*/
	    semerror(con->lineno,"Vlen data must be enclosed in {..}");
        }
        con = srcnext(datasrc);
	if(con->nctype == NC_FILLVALUE) {
	    Datalist* filler = getfiller(tsym,fillsrc);
	    ASSERT(filler->length == 1);
	    con = &filler->data[0];
	    if(con->nctype != NC_COMPOUND) {
	        semerror(con->lineno,"Vlen data fill value is not enclosed in {..}");
	    }
	}
        /* generate the nc_vlen_t instance*/
        bbprintf0(stmt,"{%u (void*)vlen_%u}",
	         con->value.compoundv->vlen.count,
    		 con->value.compoundv->vlen.uid);
        bbCatbuf(codebuf,stmt);
        } break;

    case NC_FIELD:
	/* enclose in braces if and only if field is an array */
	usecmpd = (issublist(datasrc) && tsym->typ.dimset.ndims > 0);
	if(usecmpd) srcpush(datasrc);
	if(tsym->typ.dimset.ndims > 0) {
	    Odometer* fullodom = newodometer(&tsym->typ.dimset,NULL,NULL);
            cdata_fieldarray(tsym->typ.basetype,datasrc,fullodom,0,codebuf);
	    odometerfree(fullodom);
	} else {
	    cdata_basetype(tsym->typ.basetype,datasrc,codebuf,NULL);
	}
	if(usecmpd) srcpop(datasrc);
	break;

    default: PANIC1("cdata_basetype: unexpected subclass %d",tsym->subclass);
    }
}