mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-04-06 18:00:24 +08:00
Resolve Lynton's vlen problems (partially) re: jira NCF-145
This commit is contained in:
parent
513b094561
commit
ea1af11655
1
cf
1
cf
@ -100,6 +100,7 @@ FLAGS="$FLAGS --disable-pnetcdf"
|
||||
#FLAGS="$FLAGS --with-libcf"
|
||||
#FLAGS="$FLAGS --enable-benchmarks"
|
||||
#FLAGS="$FLAGS --enable-extra-tests"
|
||||
FLAGS="$FLAGS --enable-logging"
|
||||
|
||||
FLAGS="$FLAGS --disable-shared"
|
||||
#FLAGS="$FLAGS --enable-shared"
|
||||
|
@ -5,12 +5,12 @@ PARMS="[log]"
|
||||
#PARMS="${PARMS}[netcdf3]"
|
||||
PARMS="${PARMS}[fetch=memory]"
|
||||
PARMS="${PARMS}[cache]"
|
||||
PARMS="${PARMS}[prefetch]"
|
||||
#PARMS="${PARMS}[prefetch]"
|
||||
#PARMS="${PARMS}[nocache]"
|
||||
#PARMS="${PARMS}[noprefetch]"
|
||||
PARMS="${PARMS}[show=fetch]"
|
||||
|
||||
F="file://${TOPDIR}/ncdap_test/testdata3/synth2"
|
||||
F="[cache]file:///machine/netcdf/nc_test_7549/netcdf-4.2-snapshot2012021222/ncdap_test/testdata3/1998-6-avhrr.dat"
|
||||
|
||||
PROG="./ncd"
|
||||
#PROG="../ncdump/ncdump"
|
||||
@ -66,3 +66,4 @@ CON="ens,time,lat,lon,prmslmsl[0:1:0][0:1:64][0:1:10][0:1:10]"
|
||||
F="http://motherlode.ucar.edu:8080/thredds/dodsC/station/metar/Surface_METAR_20111122_0000.nc"
|
||||
CON="weather[0:10]"
|
||||
fi
|
||||
|
||||
|
@ -15,13 +15,10 @@ ref_tst_enum_data.cdl ref_tst_group_data.cdl \
|
||||
ref_tst_nans.cdl ref_tst_opaque_data.cdl ref_tst_small.cdl \
|
||||
ref_tst_solar_1.cdl ref_tst_solar_2.cdl ref_tst_special_atts.cdl \
|
||||
ref_tst_string_data.cdl ref_tst_unicode.cdl ref_tst_utf8.cdl \
|
||||
ref_tst_vlen_data.cdl ref_typescope.cdl sfc_pres_temp.cdl \
|
||||
ref_typescope.cdl sfc_pres_temp.cdl \
|
||||
simple_xy.cdl small.cdl small2.cdl test0.cdl tst_ncml.cdl \
|
||||
bigf1.cdl bigf2.cdl bigf3.cdl bigr1.cdl bigr2.cdl bigr3.cdl \
|
||||
n3time.cdl ref_tst_special_atts3.cdl ref_tst_unlim2.cdl ref_tst_chardata.cdl \
|
||||
ref_solar.cdl unlimtest1.cdl unlimtest2.cdl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ref_solar.cdl unlimtest1.cdl unlimtest2.cdl \
|
||||
ref_tst_opaque_data.cdl \
|
||||
ref_tst_vlen_data.cdl ref_tst_vlen_data2.cdl
|
||||
|
129
ncdump/cdl4/ref_tst_vlen_data2.cdl
Normal file
129
ncdump/cdl4/ref_tst_vlen_data2.cdl
Normal file
@ -0,0 +1,129 @@
|
||||
netcdf secondFile {
|
||||
|
||||
group: pfSystem {
|
||||
types:
|
||||
|
||||
byte enum daysofWeekType { Monday = 3, Tuesday = 1, Wednesday = 7, Thursday= 9, Friday = 2 } ;
|
||||
compound pfCoilType {
|
||||
string name ;
|
||||
string turns ;
|
||||
string polarity ;
|
||||
}; // pfCoilType
|
||||
pfCoilType(*) vlen_t ;
|
||||
compound pfCircuitType {
|
||||
int id ;
|
||||
string name ;
|
||||
string description ;
|
||||
vlen_t pfCoils ;
|
||||
}; // pfCircuitType
|
||||
int(*) vlen_int ;
|
||||
vlen_int(*) vlen_int_vec
|
||||
string(*) vlen_string ;
|
||||
vlen_string(*) vlen_string_vec ;
|
||||
|
||||
compound singleCompoundType {
|
||||
int scalarAtomicInt ;
|
||||
int fixedLengthVectorAtomicInt(5) ;
|
||||
string scalarString ;
|
||||
string fixedLengthVectorString(5) ;
|
||||
vlen_int vlenScalarInt ;
|
||||
vlen_int vlenInt ;
|
||||
vlen_int fixedLengthVectorVlenInt(3) ;
|
||||
vlen_int_vec vlenVlenInt ;
|
||||
vlen_string vlenScalarString ;
|
||||
vlen_string vlenString ;
|
||||
vlen_string fixedLengthVectorVlenString(3) ;
|
||||
vlen_string_vec vlenVlenString ;
|
||||
daysofWeekType daysOfWeek(10) ;
|
||||
};
|
||||
|
||||
singleCompoundType(*) vlen_CompoundType;
|
||||
|
||||
dimensions:
|
||||
pfCircuitCount = 10 ;
|
||||
vlenDim = 3 ;
|
||||
dayCount = 10 ;
|
||||
variables:
|
||||
daysofWeekType daysOfWeek(dayCount) ;
|
||||
int scalarAtomicInt;
|
||||
double scalarAtomicDouble;
|
||||
int fixedLengthVectorAtomicInt(pfCircuitCount) ;
|
||||
double fixedLengthVectorAtomicDouble(pfCircuitCount) ;
|
||||
string scalarString ;
|
||||
string fixedLengthVectorString(pfCircuitCount);
|
||||
vlen_int vlenInt, vlenScalarInt, fixedLengthVectorVlenInt(vlenDim) ;
|
||||
vlen_int_vec vlenVlenInt ;
|
||||
vlen_string vlenString,vlenScalarString, fixedLengthVectorVlenString(vlenDim) ;
|
||||
vlen_string_vec vlenVlenString ;
|
||||
// singleCompoundType singleCompound ;
|
||||
// vlen_CompoundType vlenCompound ;
|
||||
data:
|
||||
|
||||
daysOfWeek = Monday, Thursday, Friday, Monday, Monday, Friday, Thursday, Thursday, Thursday, Tuesday ;
|
||||
scalarAtomicInt = 10 ;
|
||||
scalarAtomicDouble = 10.234 ;
|
||||
fixedLengthVectorAtomicInt = -1,2,-3,4,-5,6,-7,8,-9,10;
|
||||
fixedLengthVectorAtomicDouble = 1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1;
|
||||
scalarString = "This is some data" ;
|
||||
fixedLengthVectorString = "data1","data22","data333","data4444","data5","data6","data7","data8","data9","data10" ;
|
||||
vlenInt = {9,2,4,6,8,0,-3};
|
||||
vlenString = {"One", "Two", "Three", "Four", "Five", "Six", "Seven"};
|
||||
vlenScalarInt = {3967};
|
||||
vlenScalarString = {"Twenty"};
|
||||
fixedLengthVectorVlenInt = {20,3,4,6}, {120,103,104}, {220,203};
|
||||
vlenVlenInt = {{20,3,4,6}, {120,103,104}, {220,203}};
|
||||
fixedLengthVectorVlenString = {"One","Two","Three","Four"},{"2One","2Two"},{"4One","4Two","4Three","4Four","4Five"};
|
||||
vlenVlenString = {{"One","Two","Three","Four"},{"2One","2Two"},{"4One","4Two","4Three","4Four","4Five"}};
|
||||
|
||||
// singleCompound =
|
||||
// {13,
|
||||
// {1,2,3,4,5},
|
||||
// "OHME",
|
||||
// {"One","Two","Three","Four","Five"},
|
||||
// {11},
|
||||
// {21,22,23},
|
||||
// {{111,112,113,114}, {121,122}, {131,132,133,134,135}},
|
||||
// {{211,212,213,214}, {221,222}, {231,232,233,234,235},{241,242,243,244,245,246,247}},
|
||||
// {"11s"},
|
||||
// {"21s","22s","23s"},
|
||||
// {{"111s","112s","113s"},{"121s","122s"},{"131s","132s","133s","134s","135s"}},
|
||||
// {{"211s","212s","213s"},{"221s","222s"},{"231s","232s","233s","234s","235s"},{"241s","242s","243s","244s","245s","246s","247s"}},
|
||||
// {Monday, Thursday, Friday, Monday, Monday, Friday, Thursday, Thursday, Thursday, Tuesday}
|
||||
// };
|
||||
|
||||
|
||||
// vlenCompound =
|
||||
// {
|
||||
// {13,
|
||||
// {1,2,3,4,5},
|
||||
// "OHME",
|
||||
// {"One","Two","Three","Four","Five"},
|
||||
// {11},
|
||||
// {21,22,23},
|
||||
// {{111,112,113,114}, {121,122}, {131,132,133,134,135}},
|
||||
// {{211,212,213,214}, {221,222}, {231,232,233,234,235},{241,242,243,244,245,246,247}},
|
||||
// {"11s"},
|
||||
// {"21s","22s","23s"},
|
||||
// {{"111s","112s","113s"},{"121s","122s"},{"131s","232s","133s","134s","135s"}},
|
||||
// {{"211s","212s","213s"},{"221s","222s"},{"231s","232s","233s","234s","235s"},{"241s","242s","243s","244s","245s","246s","247s"}},
|
||||
// {Monday, Thursday, Friday, Monday, Monday, Friday, Thursday, Thursday, Thursday, Tuesday}
|
||||
// },
|
||||
// {10,
|
||||
// {10,20,30,40,50},
|
||||
// "OHME2",
|
||||
// {"One","Two","Three","Four","Five"},
|
||||
// {110},
|
||||
// {210,220,230},
|
||||
// {{1110,1120,1130,1140}, {1210,1220}, {1310,1320,1330,1340,1350}},
|
||||
// {{211,212,213,214}, {221,222}, {231,232,233,234,235},{241,242,243,244,245,246,247}},
|
||||
// {"110s"},
|
||||
// {"210s","220s","230s"},
|
||||
// {{"1110s","1120s","1130s"},{"1210s","1220s"},{"1310s","1320s","1330s","1340s","1350s"}},
|
||||
// {{"2110s","2120s","2130s"},{"2210s","2220s"},{"2310s","2320s","2330s","2340s","2350s"},{"2410s","2420s","2430s","2440s","2450s","2460s","2470s"}},
|
||||
// {Monday, Thursday, Friday, Monday, Monday, Friday, Thursday, Thursday, Thursday, Tuesday}
|
||||
// }
|
||||
// };
|
||||
//
|
||||
} // group pfSystem
|
||||
|
||||
}
|
@ -19,7 +19,10 @@ variables:
|
||||
crop_harvest:long_name = "crop harvest attributes by\ncounty ID, year and practice" ;
|
||||
data:
|
||||
crop_harvest =
|
||||
{111, 2011, 13,
|
||||
{
|
||||
111,
|
||||
2011,
|
||||
13,
|
||||
{1, 2, 3},
|
||||
{101, 102, 103},
|
||||
{1.5, 2.5, 3.5},
|
||||
|
@ -15,10 +15,11 @@ ref_tst_enum_data.dmp ref_tst_group_data.dmp \
|
||||
ref_tst_nans.dmp ref_tst_opaque_data.dmp ref_tst_small.dmp \
|
||||
ref_tst_solar_1.dmp ref_tst_solar_2.dmp ref_tst_special_atts.dmp \
|
||||
ref_tst_string_data.dmp ref_tst_unicode.dmp ref_tst_utf8.dmp \
|
||||
ref_tst_vlen_data.dmp ref_typescope.dmp sfc_pres_temp.dmp \
|
||||
ref_typescope.dmp sfc_pres_temp.dmp \
|
||||
simple_xy.dmp small.dmp small2.dmp test0.dmp tst_ncml.dmp \
|
||||
n3time.dmp ref_tst_special_atts3.dmp ref_tst_chardata.dmp ref_tst_unlim2.dmp \
|
||||
ref_solar.dmp unlimtest1.dmp unlimtest2.dmp
|
||||
ref_solar.dmp unlimtest1.dmp unlimtest2.dmp \
|
||||
ref_tst_vlen_data.dmp ref_tst_vlen_data2.dmp
|
||||
|
||||
# These do not exist because they are not run as usual tests
|
||||
# bigf1.dmp bigf2.dmp bigf3.dmp bigr1.dmp bigr2.dmp bigr3.dmp gfs1.dmp
|
||||
|
96
ncdump/expected4/ref_tst_vlen_data2.dmp
Normal file
96
ncdump/expected4/ref_tst_vlen_data2.dmp
Normal file
@ -0,0 +1,96 @@
|
||||
netcdf ref_tst_vlen_data2 {
|
||||
|
||||
group: pfSystem {
|
||||
types:
|
||||
byte enum daysofWeekType {Monday = 3, Tuesday = 1, Wednesday = 7,
|
||||
Thursday = 9, Friday = 2} ;
|
||||
compound pfCoilType {
|
||||
string name ;
|
||||
string turns ;
|
||||
string polarity ;
|
||||
}; // pfCoilType
|
||||
int(*) vlen_int ;
|
||||
string(*) vlen_string ;
|
||||
pfCoilType(*) vlen_t ;
|
||||
compound pfCircuitType {
|
||||
int id ;
|
||||
string name ;
|
||||
string description ;
|
||||
vlen_t pfCoils ;
|
||||
}; // pfCircuitType
|
||||
vlen_int(*) vlen_int_vec ;
|
||||
vlen_string(*) vlen_string_vec ;
|
||||
compound singleCompoundType {
|
||||
int scalarAtomicInt ;
|
||||
int fixedLengthVectorAtomicInt(5) ;
|
||||
string scalarString ;
|
||||
string fixedLengthVectorString(5) ;
|
||||
vlen_int vlenScalarInt ;
|
||||
vlen_int vlenInt ;
|
||||
vlen_int fixedLengthVectorVlenInt(3) ;
|
||||
vlen_int_vec vlenVlenInt ;
|
||||
vlen_string vlenScalarString ;
|
||||
vlen_string vlenString ;
|
||||
vlen_string fixedLengthVectorVlenString(3) ;
|
||||
vlen_string_vec vlenVlenString ;
|
||||
daysofWeekType daysOfWeek(10) ;
|
||||
}; // singleCompoundType
|
||||
singleCompoundType(*) vlen_CompoundType ;
|
||||
dimensions:
|
||||
pfCircuitCount = 10 ;
|
||||
vlenDim = 3 ;
|
||||
dayCount = 10 ;
|
||||
variables:
|
||||
daysofWeekType daysOfWeek(dayCount) ;
|
||||
int scalarAtomicInt ;
|
||||
double scalarAtomicDouble ;
|
||||
int fixedLengthVectorAtomicInt(pfCircuitCount) ;
|
||||
double fixedLengthVectorAtomicDouble(pfCircuitCount) ;
|
||||
string scalarString ;
|
||||
string fixedLengthVectorString(pfCircuitCount) ;
|
||||
vlen_int vlenInt ;
|
||||
vlen_int vlenScalarInt ;
|
||||
vlen_int fixedLengthVectorVlenInt(vlenDim) ;
|
||||
vlen_int_vec vlenVlenInt ;
|
||||
vlen_string vlenString ;
|
||||
vlen_string vlenScalarString ;
|
||||
vlen_string fixedLengthVectorVlenString(vlenDim) ;
|
||||
vlen_string_vec vlenVlenString ;
|
||||
data:
|
||||
|
||||
daysOfWeek = Monday, Thursday, Friday, Monday, Monday, Friday, Thursday,
|
||||
Thursday, Thursday, Tuesday ;
|
||||
|
||||
scalarAtomicInt = 10 ;
|
||||
|
||||
scalarAtomicDouble = 10.234 ;
|
||||
|
||||
fixedLengthVectorAtomicInt = -1, 2, -3, 4, -5, 6, -7, 8, -9, 10 ;
|
||||
|
||||
fixedLengthVectorAtomicDouble = 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8,
|
||||
9.9, 10.1 ;
|
||||
|
||||
scalarString = "This is some data" ;
|
||||
|
||||
fixedLengthVectorString = "data1", "data22", "data333", "data4444",
|
||||
"data5", "data6", "data7", "data8", "data9", "data10" ;
|
||||
|
||||
vlenInt = {9, 2, 4, 6, 8, 0, -3} ;
|
||||
|
||||
vlenScalarInt = {3967} ;
|
||||
|
||||
fixedLengthVectorVlenInt = {20, 3, 4, 6}, {120, 103, 104}, {220, 203} ;
|
||||
|
||||
vlenVlenInt = {{20, 3, 4, 6}, {120, 103, 104}, {220, 203}} ;
|
||||
|
||||
vlenString = {"One", "Two", "Three", "Four", "Five", "Six", "Seven"} ;
|
||||
|
||||
vlenScalarString = {"Twenty"} ;
|
||||
|
||||
fixedLengthVectorVlenString = {"One", "Two", "Three", "Four"},
|
||||
{"2One", "2Two"}, {"4One", "4Two", "4Three", "4Four", "4Five"} ;
|
||||
|
||||
vlenVlenString =
|
||||
{{"One", "Two", "Three", "Four"}, {"2One", "2Two"}, {"4One", "4Two", "4Three", "4Four", "4Five"}} ;
|
||||
} // group pfSystem
|
||||
}
|
@ -69,14 +69,17 @@ ref_tst_comp2 \
|
||||
ref_tst_comp3 \
|
||||
ref_tst_group_data \
|
||||
ref_tst_opaque_data \
|
||||
ref_tst_vlen_data \
|
||||
ref_tst_solar_1 \
|
||||
ref_tst_solar_2 \
|
||||
ref_tst_enum_data \
|
||||
ref_tst_special_atts \
|
||||
ref_tst_nans \
|
||||
ref_solar \
|
||||
unlimtest2"
|
||||
unlimtest2 \
|
||||
ref_tst_vlen_data \
|
||||
ref_tst_vlen_data \
|
||||
ref_tst_vlen_data2 \
|
||||
"
|
||||
|
||||
SPECIALTESTS3="ref_tst_special_atts3"
|
||||
|
||||
|
@ -9,7 +9,7 @@ LDADD = ${top_builddir}/liblib/libnetcdf.la
|
||||
# Build ncgen from the listed sources.
|
||||
bin_PROGRAMS = ncgen
|
||||
|
||||
ncgen_SOURCES=main.c cdata.c bindata.c genchar.c cvt.c data.c debug.c \
|
||||
ncgen_SOURCES=generate.c main.c cdata.c bindata.c genchar.c cvt.c data.c debug.c \
|
||||
escapes.c genc.c genbin.c generr.c genlib.c getfill.c odom.c offsets.c \
|
||||
semantics.c ncgentab.c dump.c util.c bytebuffer.c list.c data.h \
|
||||
debug.h generr.h genlib.h includes.h ncgen.h odom.h offsets.h dump.h \
|
||||
@ -46,3 +46,37 @@ makeparser::
|
||||
bison -pncg -t ncgen.y
|
||||
rm -f ncgentab.c
|
||||
mv ncgen.tab.c ncgentab.c
|
||||
|
||||
# Test c output
|
||||
CTEST=test
|
||||
|
||||
btest::
|
||||
./ncgen -k3 -lb ${CTEST}.cdl -o ${CTEST}.nc
|
||||
../ncdump/ncdump ./${CTEST}.nc >${CTEST}.dmp
|
||||
diff -wBb ${CTEST}.cdl ${CTEST}.dmp
|
||||
|
||||
|
||||
ctest::
|
||||
./ncgen -k3 -lc ${CTEST}.cdl >${CTEST}.c
|
||||
CFLAGS=`../nc-config --cflags` \
|
||||
LDFLAGS=`../nc-config --libs` \
|
||||
gcc -o ${CTEST} -I../include ${CFLAGS} ${CTEST}.c ../liblib/.libs/libnetcdf.a ${LDFLAGS} -lm
|
||||
./${CTEST}
|
||||
../ncdump/ncdump ./${CTEST}.nc >${CTEST}.dmp
|
||||
diff -wBb ${CTEST}.cdl ${CTEST}.dmp
|
||||
|
||||
ct::
|
||||
CFLAGS=`../nc-config --cflags` \
|
||||
LDFLAGS=`../nc-config --libs` \
|
||||
gcc -o t -I../include ${CFLAGS} t.c ../liblib/.libs/libnetcdf.a ${LDFLAGS} -lm
|
||||
./t
|
||||
|
||||
|
||||
CLASSPATH=".:ncCore-4.2.jar"
|
||||
jtest::
|
||||
./ncgen -lj ${CTEST}.cdl >Main.java
|
||||
javac -d . -classpath "${CLASSPATH}" Main.java
|
||||
|
||||
# java -cp ${CPATH} ./${CTEST}
|
||||
# ../ncdump/ncdump ./${CTEST}.nc >${CTEST}.dmp
|
||||
# diff -wBb ${CTEST}.cdl ${CTEST}.dmp
|
||||
|
464
ncgen/bindata.c
464
ncgen/bindata.c
@ -2,378 +2,154 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: bindata.c,v 1.3 2010/05/24 19:59:56 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/bindata.c,v 1.3 2010/05/24 19:59:56 dmh Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
#include "nciter.h"
|
||||
|
||||
#ifdef ENABLE_BINARY
|
||||
|
||||
/**************************************************/
|
||||
/* Code for generating binary data lists*/
|
||||
/**************************************************/
|
||||
/* For datalist constant rules: see the rules on the man page */
|
||||
static int bin_uid = 0;
|
||||
|
||||
/* Forward */
|
||||
static void bindata_primdata(Symbol*,Datasrc*,Bytebuffer*,Datalist*);
|
||||
static void bindata_fieldarray(Symbol*, Datasrc*, Odometer*, Bytebuffer*, Datalist* fillsrc);
|
||||
static void bindata_fieldarrayr(Symbol*,Datasrc*,Odometer*,int,Bytebuffer*,Datalist*);
|
||||
|
||||
/* Specialty wrappers for attributes and variables */
|
||||
void
|
||||
bindata_attrdata(Symbol* asym, Bytebuffer* memory)
|
||||
static int
|
||||
bin_charconstant(Generator* generator, Bytebuffer* buf, ...)
|
||||
{
|
||||
Datasrc* src;
|
||||
int typecode = asym->typ.basetype->typ.typecode;
|
||||
|
||||
if(asym->data == NULL) return;
|
||||
if(typecode == NC_CHAR) {
|
||||
gen_charattr(asym,memory);
|
||||
} else {
|
||||
src = datalist2src(asym->data);
|
||||
while(srcmore(src)) {
|
||||
bindata_basetype(asym->typ.basetype,src,memory,NULL);
|
||||
}
|
||||
}
|
||||
/* Just transfer charbuf to codebuf */
|
||||
Bytebuffer* charbuf;
|
||||
va_list ap;
|
||||
vastart(ap,buf);
|
||||
charbuf = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
bbNull(charbuf);
|
||||
bbCatbuf(buf,charbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
bindata_array(Symbol* vsym,
|
||||
Bytebuffer* memory,
|
||||
Datasrc* src,
|
||||
Odometer* odom,
|
||||
int index,
|
||||
Datalist* fillsrc)
|
||||
static int
|
||||
bin_constant(Generator* generator, Constant* con, Bytebuffer* buf,...)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
int firstdim = (index == 0); /* first dimension*/
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
size_t count;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
int isunlimited = (odom->declsize[index] == 0);
|
||||
int pushed = 0;
|
||||
|
||||
ASSERT(index >= 0 && index < rank);
|
||||
|
||||
/* Assume that src is already at the index of
|
||||
everything read up to now */
|
||||
|
||||
count = odom->count[index];
|
||||
|
||||
/* Unpack the nested unlimited (unless first dimension)*/
|
||||
if(!firstdim && isunlimited && issublist(src)) {
|
||||
srcpush(src);
|
||||
pushed = 1;
|
||||
if(con->nctype != NC_ECONST) {
|
||||
alignbuffer(con,buf);
|
||||
}
|
||||
|
||||
if(lastdim) {
|
||||
for(i=0;i<count;i++) {
|
||||
bindata_basetype(basetype,src,memory,fillsrc);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* walk count elements and generate recursively */
|
||||
for(i=0;i<count;i++) {
|
||||
bindata_array(vsym,memory,src,odom,index+1,fillsrc);
|
||||
}
|
||||
}
|
||||
|
||||
if(isunlimited && pushed) srcpop(src);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate an instance of the basetype using datasrc */
|
||||
void
|
||||
bindata_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* memory, 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 {..}");
|
||||
}
|
||||
bindata_primdata(tsym,datasrc,memory,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 == NULL || 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*/
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* field = (Symbol*)listget(tsym->subnodes,i);
|
||||
bindata_basetype(field,datasrc,memory,NULL);
|
||||
}
|
||||
srcpop(datasrc);
|
||||
} break;
|
||||
|
||||
case NC_VLEN: {
|
||||
Constant* con;
|
||||
nc_vlen_t ptr;
|
||||
Bytebuffer* vlenmem;
|
||||
int count;
|
||||
int pushed = 0;
|
||||
Datasrc* olddatasrc = NULL;
|
||||
|
||||
if(isfillvalue(datasrc)) {
|
||||
con = srcnext(datasrc);
|
||||
if(con == NULL || 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 {..}");
|
||||
} else {
|
||||
olddatasrc = datasrc;
|
||||
datasrc = const2src(con);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!issublist(datasrc)) {
|
||||
semerror(srcline(datasrc),"Vlen data must be enclosed in {..}");
|
||||
} else {
|
||||
SRCPUSH(pushed,datasrc);
|
||||
}
|
||||
|
||||
/* collect the nc_vlen_t instance*/
|
||||
vlenmem = bbNew();
|
||||
for(count=0;srcmore(datasrc);count++) {
|
||||
bindata_basetype(tsym->typ.basetype,datasrc,vlenmem,NULL);
|
||||
}
|
||||
ptr.len = count;
|
||||
ptr.p = bbDup(vlenmem);
|
||||
bbFree(vlenmem);
|
||||
bbAppendn(memory,(char*)&ptr,sizeof(ptr));
|
||||
if(pushed) srcpop(datasrc);
|
||||
if(olddatasrc) datasrc = olddatasrc;
|
||||
switch (con->nctype) {
|
||||
case NC_OPAQUE: {
|
||||
unsigned char* bytes;
|
||||
size_t len;
|
||||
bytes=makebytestring(con->value.opaquev.stringv,&len);
|
||||
bbAppendn(buf,(void*)bytes,len);
|
||||
} break;
|
||||
case NC_CHAR:
|
||||
bbAppendn(buf,&con->value.charv,sizeof(con->value.charv));
|
||||
break;
|
||||
case NC_BYTE:
|
||||
bbAppendn(buf,(void*)&con->value.int8v,sizeof(con->value.int8v));
|
||||
break;
|
||||
case NC_SHORT:
|
||||
bbAppendn(buf,(void*)&con->value.int16v,sizeof(con->value.int16v));
|
||||
break;
|
||||
case NC_INT:
|
||||
bbAppendn(buf,(void*)&con->value.int32v,sizeof(con->value.int32v));
|
||||
break;
|
||||
case NC_FLOAT:
|
||||
bbAppendn(buf,(void*)&con->value.floatv,sizeof(con->value.floatv));
|
||||
break;
|
||||
case NC_DOUBLE:
|
||||
bbAppendn(buf,(void*)&con->value.doublev,sizeof(con->value.doublev));
|
||||
break;
|
||||
case NC_UBYTE:
|
||||
bbAppendn(buf,(void*)&con->value.uint8v,sizeof(con->value.uint8v));
|
||||
break;
|
||||
case NC_USHORT:
|
||||
bbAppendn(buf,(void*)&con->value.uint16v,sizeof(con->value.uint16v));
|
||||
break;
|
||||
case NC_UINT:
|
||||
bbAppendn(buf,(void*)&con->value.uint32v,sizeof(con->value.uint32v));
|
||||
break;
|
||||
case NC_INT64: {
|
||||
union SI64 { char ch[8]; long long i64;} si64;
|
||||
si64.i64 = con->value.int64v;
|
||||
bbAppendn(buf,(void*)si64.ch,sizeof(si64.ch));
|
||||
} break;
|
||||
case NC_UINT64: {
|
||||
union SU64 { char ch[8]; unsigned long long i64;} su64;
|
||||
su64.i64 = con->value.uint64v;
|
||||
bbAppendn(buf,(void*)su64.ch,sizeof(su64.ch));
|
||||
} break;
|
||||
case NC_STRING: {
|
||||
char* ptr;
|
||||
int len = (size_t)con->value.stringv.len;
|
||||
ptr = (char*)malloc(len+1);
|
||||
memcpy(ptr,con->value.stringv.stringv,len);
|
||||
ptr[len] = '\0';
|
||||
bbAppendn(buf,(void*)&ptr,sizeof(ptr));
|
||||
} 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);
|
||||
bindata_fieldarray(tsym->typ.basetype,datasrc,fullodom,memory,fillsrc);
|
||||
} else {
|
||||
bindata_basetype(tsym->typ.basetype,datasrc,memory,NULL);
|
||||
}
|
||||
if(usecmpd) srcpop(datasrc);
|
||||
break;
|
||||
|
||||
default: PANIC1("bindata_basetype: unexpected subclass %d",tsym->subclass);
|
||||
default: PANIC1("bin_constant: unexpected type: %d",con->nctype);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Used only for structure field arrays*/
|
||||
static void
|
||||
bindata_fieldarrayr(Symbol* basetype, Datasrc* src, Odometer* odom, int index,
|
||||
Bytebuffer* memory, Datalist* fillsrc)
|
||||
static int
|
||||
bin_listbegin(Generator* generator, ListClass lc, size_t size, Bytebuffer* buf, int* uidp, ...)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
unsigned int size = odom->declsize[index];
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
|
||||
ASSERT(size != 0);
|
||||
for(i=0;i<size;i++) {
|
||||
if(lastdim) {
|
||||
bindata_basetype(basetype,src,memory,fillsrc);
|
||||
} else { /* !lastdim*/
|
||||
bindata_fieldarrayr(basetype,src,odom,index+1,memory,fillsrc);
|
||||
}
|
||||
}
|
||||
if(uidp) *uidp = ++bin_uid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
bindata_fieldarray(Symbol* basetype, Datasrc* src, Odometer* odom,
|
||||
Bytebuffer* memory, Datalist* fillsrc)
|
||||
static int
|
||||
bin_list(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...)
|
||||
{
|
||||
if(basetype->typ.typecode == NC_CHAR) {
|
||||
/* Collect the char field in a separate buffer */
|
||||
Bytebuffer* fieldbuf = bbNew();
|
||||
gen_charfield(src,odom,fieldbuf);
|
||||
bbAppendn(memory,bbContents(fieldbuf),bbLength(fieldbuf));
|
||||
bbFree(fieldbuf);
|
||||
} else {
|
||||
bindata_fieldarrayr(basetype,src,odom,0,memory,fillsrc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
bindata_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* memory, Datalist* fillsrc)
|
||||
static int
|
||||
bin_listend(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...)
|
||||
{
|
||||
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);
|
||||
bindata_primdata(basetype,src,memory,NULL);
|
||||
srcpop(src);
|
||||
goto done;
|
||||
}
|
||||
|
||||
target.nctype = basetype->typ.typecode;
|
||||
|
||||
if(target.nctype != NC_ECONST) {
|
||||
convert1(prim,&target);
|
||||
alignbuffer(&target,memory);
|
||||
}
|
||||
|
||||
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);
|
||||
srcpushlist(src,econ);
|
||||
dlappend(econ,&prim->value.enumv->typ.econst);
|
||||
bindata_primdata(prim->value.enumv->typ.basetype,src,memory,fillsrc);
|
||||
srcpop(src);
|
||||
}
|
||||
break;
|
||||
case NC_OPAQUE: {
|
||||
unsigned char* bytes;
|
||||
size_t len;
|
||||
setprimlength(&target,basetype->typ.size*2);
|
||||
bytes=makebytestring(target.value.opaquev.stringv,&len);
|
||||
bbAppendn(memory,(void*)bytes,len);
|
||||
} break;
|
||||
|
||||
case NC_CHAR:
|
||||
bbAppendn(memory,&target.value.charv,sizeof(target.value.charv));
|
||||
break;
|
||||
case NC_BYTE:
|
||||
bbAppendn(memory,(void*)&target.value.int8v,sizeof(target.value.int8v));
|
||||
break;
|
||||
case NC_SHORT:
|
||||
bbAppendn(memory,(void*)&target.value.int16v,sizeof(target.value.int16v));
|
||||
break;
|
||||
case NC_INT:
|
||||
bbAppendn(memory,(void*)&target.value.int32v,sizeof(target.value.int32v));
|
||||
break;
|
||||
case NC_FLOAT:
|
||||
bbAppendn(memory,(void*)&target.value.floatv,sizeof(target.value.floatv));
|
||||
break;
|
||||
case NC_DOUBLE:
|
||||
bbAppendn(memory,(void*)&target.value.doublev,sizeof(target.value.doublev));
|
||||
break;
|
||||
case NC_UBYTE:
|
||||
bbAppendn(memory,(void*)&target.value.uint8v,sizeof(target.value.uint8v));
|
||||
break;
|
||||
case NC_USHORT:
|
||||
bbAppendn(memory,(void*)&target.value.uint16v,sizeof(target.value.uint16v));
|
||||
break;
|
||||
case NC_UINT:
|
||||
bbAppendn(memory,(void*)&target.value.uint32v,sizeof(target.value.uint32v));
|
||||
break;
|
||||
case NC_INT64: {
|
||||
union SI64 { char ch[8]; long long i64;} si64;
|
||||
si64.i64 = target.value.int64v;
|
||||
bbAppendn(memory,(void*)si64.ch,sizeof(si64.ch));
|
||||
} break;
|
||||
case NC_UINT64: {
|
||||
union SU64 { char ch[8]; unsigned long long i64;} su64;
|
||||
su64.i64 = target.value.uint64v;
|
||||
bbAppendn(memory,(void*)su64.ch,sizeof(su64.ch));
|
||||
} break;
|
||||
case NC_STRING: {
|
||||
if(usingclassic) {
|
||||
bbAppendn(memory,target.value.stringv.stringv,target.value.stringv.len);
|
||||
} else if(target.nctype == NC_CHAR) {
|
||||
bbAppendn(memory,target.value.stringv.stringv,target.value.stringv.len);
|
||||
} else {
|
||||
char* ptr;
|
||||
int len = (size_t)target.value.stringv.len;
|
||||
ptr = poolalloc(len+1); /* CAREFUL: this has short lifetime*/
|
||||
memcpy(ptr,target.value.stringv.stringv,len);
|
||||
ptr[len] = '\0';
|
||||
bbAppendn(memory,(void*)&ptr,sizeof(ptr));
|
||||
}
|
||||
} break;
|
||||
|
||||
default: PANIC1("bindata_primdata: unexpected type: %d",target.nctype);
|
||||
}
|
||||
done:
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGNORE
|
||||
/*
|
||||
This walk of the data lists collects
|
||||
vlen sublists and constructs separate C constants
|
||||
for each of them. The "id" of each list is then
|
||||
recorded in the containing datalist.
|
||||
*/
|
||||
void
|
||||
bindata_vlenconstants(List* vlenconstants)
|
||||
static int
|
||||
bin_vlendecl(Generator* generator, Bytebuffer* buf, Symbol* tsym, int uid, size_t count,...)
|
||||
{
|
||||
int i,nvlen;
|
||||
Datasrc* vlensrc;
|
||||
Bytebuffer* memory = bbNew();
|
||||
|
||||
/* Prepare a place to store vlen constants */
|
||||
nvlen = listlength(vlenconstants);
|
||||
if(nvlen == 0) return;
|
||||
vlendata = (struct Vlendata*)emalloc(sizeof(struct Vlendata)*nvlen+1);
|
||||
memset((void*)vlendata,0,sizeof(struct Vlendata)*nvlen+1);
|
||||
|
||||
for(i=0;i<nvlen;i++) {
|
||||
Constant* cmpd = (Constant*)listget(vlenconstants,i);
|
||||
int chartype;
|
||||
Symbol* tsym = cmpd->value.compoundv->vlen.schema;
|
||||
unsigned long uid = cmpd->value.compoundv->vlen.uid;
|
||||
unsigned long count;
|
||||
ASSERT(tsym != NULL);
|
||||
chartype = (tsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
vlensrc = datalist2src(cmpd->value.compoundv);
|
||||
|
||||
bbClear(memory);
|
||||
count = 0;
|
||||
if(chartype) {
|
||||
/* Collect the char vlen in a separate buffer */
|
||||
gen_charvlen(vlensrc,memory);
|
||||
count = bbLength(memory);
|
||||
} else {
|
||||
while(srcmore(vlensrc)) {
|
||||
bindata_basetype(tsym->typ.basetype,vlensrc,memory,NULL);
|
||||
count++;
|
||||
}
|
||||
ASSERT(count == cmpd->value.compoundv->vlen.count);
|
||||
}
|
||||
vlendata[uid].data = bbDup(memory);
|
||||
vlendata[uid].count = count;
|
||||
}
|
||||
bbFree(memory);
|
||||
va_list ap;
|
||||
Bytebuffer* vlenmem;
|
||||
nc_vlen_t ptr;
|
||||
vastart(ap,count);
|
||||
vlenmem = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
ptr.len = count;
|
||||
ptr.p = bbDup(vlenmem);
|
||||
bbAppendn(buf,(char*)&ptr,sizeof(ptr));
|
||||
return 1;
|
||||
}
|
||||
#endif /*IGNORE*/
|
||||
|
||||
static int
|
||||
bin_vlenstring(Generator* generator, Bytebuffer* codebuf, int* uidp, size_t* sizep,...)
|
||||
{
|
||||
Bytebuffer* vlenmem;
|
||||
nc_vlen_t ptr;
|
||||
va_list ap;
|
||||
if(uidp) *uidp = ++bin_uid;
|
||||
vastart(ap,sizep);
|
||||
vlenmem = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
ptr.len = bbLength(vlenmem);
|
||||
ptr.p = bbDup(vlenmem);
|
||||
bbAppendn(codebuf,(char*)&ptr,sizeof(ptr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Define the single static bin data generator */
|
||||
static Generator bin_generator_singleton = {
|
||||
NULL,
|
||||
bin_charconstant,
|
||||
bin_constant,
|
||||
bin_listbegin,
|
||||
bin_list,
|
||||
bin_listend,
|
||||
bin_vlendecl,
|
||||
bin_vlenstring
|
||||
};
|
||||
Generator* bin_generator = &bin_generator_singleton;
|
||||
|
||||
#endif /*ENABLE_BINARY*/
|
||||
|
@ -26,9 +26,6 @@ EXTERNC int bbFill(Bytebuffer*, const char fill);
|
||||
/* Produce a duplicate of the contents*/
|
||||
EXTERNC char* bbDup(const Bytebuffer*);
|
||||
|
||||
/* pull a duplicate of the contents*/
|
||||
EXTERNC char* bbDup(const Bytebuffer*);
|
||||
|
||||
/* Return the ith char; -1 if no such char */
|
||||
EXTERNC int bbGet(Bytebuffer*,unsigned int);
|
||||
|
||||
|
517
ncgen/cdata.c
517
ncgen/cdata.c
@ -2,424 +2,205 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: cdata.c,v 1.5 2010/05/24 19:59:56 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/cdata.c,v 1.5 2010/05/24 19:59:56 dmh Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
#include "nciter.h"
|
||||
|
||||
#ifdef ENABLE_C
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
|
||||
static int c_uid = 0;
|
||||
|
||||
/**************************************************/
|
||||
/* Code for generating C language data lists*/
|
||||
/**************************************************/
|
||||
/* For datalist constant rules: see the rules on the man page */
|
||||
|
||||
/* Forward*/
|
||||
static void cdata_primdata(Symbol*, Datasrc*, Bytebuffer*, Datalist*);
|
||||
static void cdata_fieldarray(Symbol*, Datasrc*, Odometer*, int, Bytebuffer*, Datalist* fillsrc);
|
||||
|
||||
/* vlen uid generator */
|
||||
static int uid = 0;
|
||||
|
||||
/* Specialty wrappers for cdata_data */
|
||||
void
|
||||
cdata_attrdata(Symbol* asym, Bytebuffer* codebuf)
|
||||
static int
|
||||
c_charconstant(Generator* generator, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
Datasrc* src;
|
||||
int typecode = asym->typ.basetype->typ.typecode;
|
||||
|
||||
if(asym->data == NULL) return;
|
||||
if(typecode == NC_CHAR) {
|
||||
gen_charattr(asym,codebuf);
|
||||
} else {
|
||||
src = datalist2src(asym->data);
|
||||
while(srcmore(src)) {
|
||||
bbAppend(codebuf,' ');
|
||||
cdata_basetype(asym->typ.basetype,src,codebuf,NULL);
|
||||
}
|
||||
}
|
||||
/* Escapes and quoting will be handled in genc_write */
|
||||
/* Just transfer charbuf to codebuf */
|
||||
Bytebuffer* charbuf;
|
||||
va_list ap;
|
||||
vastart(ap,codebuf);
|
||||
charbuf = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
bbNull(charbuf);
|
||||
bbCatbuf(codebuf,charbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
cdata_array(Symbol* vsym,
|
||||
Bytebuffer* codebuf,
|
||||
Datasrc* src,
|
||||
Odometer* odom,
|
||||
int index,
|
||||
Datalist* fillsrc)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
int pushed = 0;
|
||||
size_t count;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
int firstdim = (index == 0); /* first dimension*/
|
||||
int isunlimited = (odom->declsize[index] == 0);
|
||||
|
||||
ASSERT(index >= 0 && index < rank);
|
||||
|
||||
count = odom->count[index];
|
||||
|
||||
if(!firstdim && isunlimited && issublist(src)) {
|
||||
srcpush(src);
|
||||
pushed = 1;
|
||||
}
|
||||
|
||||
if(lastdim) {
|
||||
for(i=0;i<count;i++) {
|
||||
cdata_basetype(basetype,src,codebuf,fillsrc);
|
||||
}
|
||||
} else {
|
||||
/* now walk count elements and generate recursively */
|
||||
for(i=0;i<count;i++) {
|
||||
cdata_array(vsym,codebuf,src,odom,index+1,fillsrc);
|
||||
}
|
||||
}
|
||||
|
||||
if(isunlimited && pushed) srcpop(src);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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 == NULL || 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;
|
||||
#ifdef NOTUSED
|
||||
nc_vlen_t ptr;
|
||||
#endif
|
||||
Bytebuffer* vlenmem;
|
||||
int count;
|
||||
int pushed = 0;
|
||||
Datasrc* olddatasrc = NULL;
|
||||
if(isfillvalue(datasrc)) {
|
||||
con = srcnext(datasrc);
|
||||
if(con == NULL || 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 {..}");
|
||||
} else {
|
||||
olddatasrc = datasrc;
|
||||
datasrc = const2src(con);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!issublist(datasrc)) {
|
||||
semerror(srcline(datasrc),"Vlen data must be enclosed in {..}");
|
||||
} else {
|
||||
SRCPUSH(pushed,datasrc);
|
||||
}
|
||||
|
||||
/* generate the nc_vlen_t instance*/
|
||||
vlenmem = bbNew();
|
||||
for(count=0;srcmore(datasrc);count++) {
|
||||
cdata_basetype(tsym->typ.basetype,datasrc,vlenmem,NULL);
|
||||
}
|
||||
|
||||
/* generate the nc_vlen_t instance*/
|
||||
bbprintf0(stmt,"{%u (void*)vlen_%u}",count,++uid);
|
||||
bbCatbuf(codebuf,stmt);
|
||||
|
||||
#ifdef NOTUSED
|
||||
ptr.len = count;
|
||||
ptr.p = bbDup(vlenmem);
|
||||
#endif
|
||||
bbFree(vlenmem);
|
||||
if(pushed) srcpop(datasrc);
|
||||
if(olddatasrc) datasrc = olddatasrc;
|
||||
|
||||
} 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,fillsrc);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Used only for structure field arrays*/
|
||||
static void
|
||||
cdata_fieldarray(Symbol* basetype, Datasrc* src, Odometer* odom, int index,
|
||||
Bytebuffer* codebuf, Datalist* fillsrc)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
unsigned int size = odom->declsize[index];
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
int chartype = (basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
if(chartype) {
|
||||
/* Collect the char field in a separate buffer */
|
||||
Bytebuffer* fieldbuf = bbNew();
|
||||
gen_charfield(src,odom,fieldbuf);
|
||||
/* Add to the existing data buf as a single constant */
|
||||
cquotestring(fieldbuf);
|
||||
bbCat(codebuf," ");
|
||||
bbCatbuf(codebuf,fieldbuf);
|
||||
bbFree(fieldbuf);
|
||||
} else {
|
||||
ASSERT(size != 0);
|
||||
for(i=0;i<size;i++) {
|
||||
if(lastdim) {
|
||||
bbAppend(codebuf,' ');
|
||||
cdata_basetype(basetype,src,codebuf,NULL);
|
||||
} else { /* !lastdim*/
|
||||
cdata_fieldarray(basetype,src,odom,index+1,codebuf,fillsrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
This walk of the data lists collects
|
||||
vlen sublists and constructs separate C constants
|
||||
for each of them. The "id" of each list is then
|
||||
recorded in the containing datalist.
|
||||
*/
|
||||
void
|
||||
cdata_vlenconstants(List* vlenconstants, Bytebuffer* codebuf)
|
||||
{
|
||||
int i,nvlen;
|
||||
Datasrc* vlensrc;
|
||||
Bytebuffer* tmp = bbNew();
|
||||
|
||||
nvlen = listlength(vlenconstants);
|
||||
for(i=0;i<nvlen;i++) {
|
||||
Constant* cmpd = (Constant*)listget(vlenconstants,i);
|
||||
int chartype;
|
||||
Symbol* tsym = cmpd->value.compoundv->vlen.schema;
|
||||
ASSERT(tsym != NULL);
|
||||
chartype = (tsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
bbprintf0(tmp,"static const %s vlen_%u[] = ",
|
||||
ctypename(tsym->typ.basetype),
|
||||
cmpd->value.compoundv->vlen.uid);
|
||||
bbCatbuf(codebuf,tmp);
|
||||
vlensrc = datalist2src(cmpd->value.compoundv);
|
||||
bbAppend(codebuf,'{');
|
||||
if(chartype) {
|
||||
/* Collect the char vlen in a separate buffer */
|
||||
Bytebuffer* vlenbuf = bbNew();
|
||||
gen_charvlen(vlensrc,vlenbuf);
|
||||
/* Add to the existing data buf as a single constant */
|
||||
cquotestring(vlenbuf);
|
||||
bbCatbuf(codebuf,vlenbuf);
|
||||
bbFree(vlenbuf);
|
||||
} else {
|
||||
size_t count = 0;
|
||||
while(srcmore(vlensrc)) {
|
||||
if(count > 0) bbCat(codebuf,", ");
|
||||
cdata_basetype(tsym->typ.basetype,vlensrc,codebuf,NULL);
|
||||
count++;
|
||||
}
|
||||
ASSERT(count == cmpd->value.compoundv->vlen.count);
|
||||
}
|
||||
bbCat(codebuf,"} ;\n");
|
||||
}
|
||||
bbFree(tmp);
|
||||
}
|
||||
|
||||
/* Result is a pool string or a constant => do not free*/
|
||||
char*
|
||||
cdata_const(Constant* ci)
|
||||
static int
|
||||
c_constant(Generator* generator, Constant* con, Bytebuffer* buf,...)
|
||||
{
|
||||
Bytebuffer* codetmp = bbNew();
|
||||
char* result;
|
||||
char* special = NULL;
|
||||
|
||||
switch (ci->nctype) {
|
||||
case NC_CHAR:
|
||||
{
|
||||
char tmp[64];
|
||||
tmp[0] = '\0';
|
||||
escapifychar(ci->value.charv,tmp,'\'');
|
||||
bbCat(codetmp,"'");
|
||||
bbCat(codetmp,tmp);
|
||||
bbCat(codetmp,"'");
|
||||
}
|
||||
break;
|
||||
switch (con->nctype) {
|
||||
case NC_BYTE:
|
||||
bbprintf(codetmp,"%hhd",ci->value.int8v);
|
||||
bbprintf(codetmp,"%hhd",con->value.int8v);
|
||||
break;
|
||||
case NC_SHORT:
|
||||
bbprintf(codetmp,"%hd",ci->value.int16v);
|
||||
bbprintf(codetmp,"%hd",con->value.int16v);
|
||||
break;
|
||||
case NC_INT:
|
||||
bbprintf(codetmp,"%d",ci->value.int32v);
|
||||
bbprintf(codetmp,"%d",con->value.int32v);
|
||||
break;
|
||||
case NC_FLOAT:
|
||||
/* Special case for nanf */
|
||||
if(isnan(ci->value.floatv))
|
||||
if(isnan(con->value.floatv))
|
||||
bbprintf(codetmp,"nanf");
|
||||
else
|
||||
bbprintf(codetmp,"%f",ci->value.floatv);
|
||||
bbprintf(codetmp,"%f",con->value.floatv);
|
||||
break;
|
||||
case NC_DOUBLE:
|
||||
/* Special case for nanf */
|
||||
if(isnan(ci->value.doublev))
|
||||
/* Special case for nan */
|
||||
if(isnan(con->value.doublev))
|
||||
bbprintf(codetmp,"nan");
|
||||
else
|
||||
bbprintf(codetmp,"%lf",ci->value.doublev);
|
||||
bbprintf(codetmp,"%lf",con->value.doublev);
|
||||
break;
|
||||
case NC_UBYTE:
|
||||
bbprintf(codetmp,"%hhu",ci->value.uint8v);
|
||||
bbprintf(codetmp,"%hhu",con->value.uint8v);
|
||||
break;
|
||||
case NC_USHORT:
|
||||
bbprintf(codetmp,"%hu",ci->value.uint16v);
|
||||
bbprintf(codetmp,"%hu",con->value.uint16v);
|
||||
break;
|
||||
case NC_UINT:
|
||||
bbprintf(codetmp,"%uU",ci->value.uint32v);
|
||||
bbprintf(codetmp,"%uU",con->value.uint32v);
|
||||
break;
|
||||
case NC_INT64:
|
||||
bbprintf(codetmp,"%lldLL",ci->value.int64v);
|
||||
bbprintf(codetmp,"%lldLL",con->value.int64v);
|
||||
break;
|
||||
case NC_UINT64:
|
||||
bbprintf(codetmp,"%lluLLU",ci->value.uint64v);
|
||||
bbprintf(codetmp,"%lluLLU",con->value.uint64v);
|
||||
break;
|
||||
case NC_ECONST:
|
||||
bbprintf(codetmp,"%s",cname(ci->value.enumv));
|
||||
break;
|
||||
case NC_STRING:
|
||||
{ /* handle separately */
|
||||
char* escaped = escapify(ci->value.stringv.stringv,
|
||||
'"',ci->value.stringv.len);
|
||||
result = poolalloc(1+2+strlen(escaped));
|
||||
strcpy(result,"\"");
|
||||
strcat(result,escaped);
|
||||
strcat(result,"\"");
|
||||
goto done;
|
||||
}
|
||||
bbprintf(codetmp,"%s",cname(con->value.enumv));
|
||||
break;
|
||||
case NC_STRING: { /* handle separately */
|
||||
char* escaped = escapify(con->value.stringv.stringv,
|
||||
'"',con->value.stringv.len);
|
||||
special = poolalloc(1+2+strlen(escaped));
|
||||
strcpy(special,"\"");
|
||||
strcat(special,escaped);
|
||||
strcat(special,"\"");
|
||||
} break;
|
||||
case NC_OPAQUE: {
|
||||
char* p;
|
||||
int bslen;
|
||||
bslen=(4*ci->value.opaquev.len);
|
||||
result = poolalloc(bslen+2+1);
|
||||
strcpy(result,"\"");
|
||||
p = ci->value.opaquev.stringv;
|
||||
bslen=(4*con->value.opaquev.len);
|
||||
special = poolalloc(bslen+2+1);
|
||||
strcpy(special,"\"");
|
||||
p = con->value.opaquev.stringv;
|
||||
while(*p) {
|
||||
strcat(result,"\\x");
|
||||
strncat(result,p,2);
|
||||
strcat(special,"\\x");
|
||||
strncat(special,p,2);
|
||||
p += 2;
|
||||
}
|
||||
strcat(result,"\"");
|
||||
goto done;
|
||||
strcat(special,"\"");
|
||||
} break;
|
||||
|
||||
default: PANIC1("ncstype: bad type code: %d",ci->nctype);
|
||||
default: PANIC1("ncstype: bad type code: %d",con->nctype);
|
||||
|
||||
}
|
||||
result = pooldup(bbContents(codetmp)); /*except for NC_STRING and NC_OPAQUE*/
|
||||
if(special == NULL)
|
||||
bbCatbuf(buf,codetmp);
|
||||
else
|
||||
bbCat(buf,special);
|
||||
bbFree(codetmp);
|
||||
done:
|
||||
return result;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
c_listbegin(Generator* generator, ListClass lc, size_t size, Bytebuffer* codebuf, int* uidp, ...)
|
||||
{
|
||||
if(uidp) *uidp = ++c_uid;
|
||||
switch (lc) {
|
||||
case LISTVLEN:
|
||||
case LISTATTR:
|
||||
case LISTDATA:
|
||||
break;
|
||||
case LISTFIELDARRAY:
|
||||
case LISTCOMPOUND:
|
||||
bbAppend(codebuf,'{');
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
c_list(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
switch (lc) {
|
||||
case LISTVLEN:
|
||||
case LISTATTR:
|
||||
if(count > 0) bbCat(codebuf,", ");
|
||||
break;
|
||||
case LISTDATA:
|
||||
case LISTCOMPOUND:
|
||||
case LISTFIELDARRAY:
|
||||
bbAppend(codebuf,' ');
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
c_listend(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...)
|
||||
{
|
||||
switch (lc) {
|
||||
case LISTCOMPOUND:
|
||||
case LISTFIELDARRAY:
|
||||
bbAppend(buf,'}');
|
||||
break;
|
||||
case LISTDATA:
|
||||
case LISTVLEN:
|
||||
case LISTATTR:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
c_vlendecl(Generator* generator, Bytebuffer* codebuf, Symbol* tsym, int uid, size_t count, ...)
|
||||
{
|
||||
/* Build a bytebuffer to capture the vlen decl */
|
||||
List* declstack = (List*)generator->state;
|
||||
Bytebuffer* decl = bbNew();
|
||||
Bytebuffer* vlenbuf;
|
||||
va_list ap;
|
||||
vastart(ap,count);
|
||||
vlenbuf = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
bbprintf0(decl,"static const %s vlen_%u[] = {",
|
||||
ctypename(tsym->typ.basetype),
|
||||
uid);
|
||||
commify(vlenbuf);
|
||||
bbCatbuf(decl,vlenbuf);
|
||||
bbCat(decl,"} ;");
|
||||
listpush(declstack,(elem_t)decl);
|
||||
/* Now generate the reference to buffer */
|
||||
bbprintf(codebuf,"{%u,(void*)vlen_%u}",count,uid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
c_vlenstring(Generator* generator, Bytebuffer* vlenmem, int* uidp, size_t* countp,...)
|
||||
{
|
||||
if(uidp) *uidp = ++c_uid;
|
||||
if(countp) *countp = bbLength(vlenmem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Define the single static bin data generator */
|
||||
static Generator c_generator_singleton = {
|
||||
NULL,
|
||||
c_charconstant,
|
||||
c_constant,
|
||||
c_listbegin,
|
||||
c_list,
|
||||
c_listend,
|
||||
c_vlendecl,
|
||||
c_vlenstring
|
||||
};
|
||||
Generator* c_generator = &c_generator_singleton;
|
||||
|
||||
#endif /*ENABLE_C*/
|
||||
|
@ -18,6 +18,8 @@ convert1(Constant* src, Constant* dst)
|
||||
unsigned char* bytes = NULL;
|
||||
size_t bytelen;
|
||||
|
||||
dst->lineno = src->lineno;
|
||||
|
||||
/* Need to translate all possible sources to all possible sinks.*/
|
||||
/* Rather than have a nested switch, combine the src and target into*/
|
||||
/* a single value so we can do a single n*n-way switch*/
|
||||
|
51
ncgen/data.c
51
ncgen/data.c
@ -221,21 +221,6 @@ srcsplice(Datasrc* ds, Datalist* list)
|
||||
ds->spliced = 1;
|
||||
}
|
||||
|
||||
void
|
||||
srcmove(Datasrc* ds, size_t delta)
|
||||
{
|
||||
srcmoveto(ds,ds->index+delta);
|
||||
}
|
||||
|
||||
void
|
||||
srcmoveto(Datasrc* ds, size_t pos)
|
||||
{
|
||||
if(pos >= ds->length)
|
||||
ds->index = ds->length;
|
||||
else
|
||||
ds->index = pos;
|
||||
}
|
||||
|
||||
void
|
||||
srcsetfill(Datasrc* ds, Datalist* list)
|
||||
{
|
||||
@ -262,13 +247,14 @@ bbFree(buf);
|
||||
void
|
||||
report0(char* lead, Datasrc* src, int index)
|
||||
{
|
||||
if(debug == 0) return;
|
||||
#ifdef IGNORE
|
||||
fprintf(stderr,"%s src ",lead);
|
||||
if(index >=0 ) fprintf(stderr,"(%d)",index);
|
||||
fprintf(stderr,":: ");
|
||||
dumpdatasrc(src);
|
||||
fprintf(stderr,"\n");
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -360,7 +346,8 @@ datalistline(Datalist* ds)
|
||||
and insert commas as needed; ideally, this
|
||||
operation should be idempotent so that
|
||||
the caller need not worry about it having already
|
||||
been applied.
|
||||
been applied. Also, handle situation where there may be missing
|
||||
matching right braces.
|
||||
*/
|
||||
|
||||
static char* commifyr(char* p, Bytebuffer* buf);
|
||||
@ -380,6 +367,9 @@ commify(Bytebuffer* buf)
|
||||
efree(list);
|
||||
}
|
||||
|
||||
/* Requires that the string be balanced
|
||||
WRT to braces
|
||||
*/
|
||||
static char*
|
||||
commifyr(char* p, Bytebuffer* buf)
|
||||
{
|
||||
@ -388,7 +378,9 @@ commifyr(char* p, Bytebuffer* buf)
|
||||
while((c=*p++)) {
|
||||
if(c == ' ') continue;
|
||||
if(c == ',') continue;
|
||||
else if(c == '}') break;
|
||||
else if(c == '}') {
|
||||
break;
|
||||
}
|
||||
if(comma) bbCat(buf,", "); else comma=1;
|
||||
if(c == '{') {
|
||||
bbAppend(buf,'{');
|
||||
@ -473,6 +465,7 @@ void
|
||||
codedump(Bytebuffer* buf)
|
||||
{
|
||||
bbCatbuf(codebuffer,buf);
|
||||
bbClear(buf);
|
||||
}
|
||||
|
||||
void
|
||||
@ -591,10 +584,10 @@ retry: switch ((c=*p++)) {
|
||||
break;
|
||||
case 'f':
|
||||
if(lcount > 0) {
|
||||
snprintf(tmp,sizeof(tmp),"%.16g",
|
||||
snprintf(tmp,sizeof(tmp),"((double)%.16g)",
|
||||
(double)va_arg(argv,double));
|
||||
} else {
|
||||
snprintf(tmp,sizeof(tmp),"%.8g",
|
||||
snprintf(tmp,sizeof(tmp),"((float)%.8g)",
|
||||
(double)va_arg(argv,double));
|
||||
}
|
||||
bbCat(buf,tmp);
|
||||
@ -658,3 +651,21 @@ emptystringconst(int lineno, Constant* c)
|
||||
c->value.stringv.stringv = NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
#define INDENTMAX 256
|
||||
static char* dent = NULL;
|
||||
|
||||
char*
|
||||
indented(int n)
|
||||
{
|
||||
char* indentation;
|
||||
if(dent == NULL) {
|
||||
dent = (char*)emalloc(INDENTMAX+1);
|
||||
memset((void*)dent,' ',INDENTMAX);
|
||||
dent[INDENTMAX] = '\0';
|
||||
}
|
||||
if(n*4 >= INDENTMAX) n = INDENTMAX/4;
|
||||
indentation = dent+(INDENTMAX - 4*n);
|
||||
return indentation;
|
||||
}
|
||||
|
||||
|
138
ncgen/data.h
138
ncgen/data.h
@ -2,15 +2,25 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: data.h,v 1.5 2010/05/24 19:59:56 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/data.h,v 1.5 2010/05/24 19:59:56 dmh Exp $ */
|
||||
|
||||
#ifndef DATA_H
|
||||
#define DATA_H 1
|
||||
|
||||
#ifndef NO_STDARG
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
/* nmemonic*/
|
||||
#define TOPLEVEL 1
|
||||
|
||||
/* Forward types */
|
||||
struct Datalist;
|
||||
struct Symbol;
|
||||
struct Dimset;
|
||||
typedef struct Generator Generator;
|
||||
|
||||
/* any one possible value*/
|
||||
typedef union Constvalue {
|
||||
struct Datalist* compoundv; /* NC_COMPOUND*/
|
||||
@ -65,7 +75,6 @@ typedef struct Datalist {
|
||||
location of current read point in the Datalist sequence
|
||||
In effect, we are parsing the data sequence.
|
||||
Push and pop of data sources is supported (see srcpush() below).*/
|
||||
|
||||
typedef struct Datasrc {
|
||||
Constant* data; /* duplicate pointer; so do not free.*/
|
||||
int index;
|
||||
@ -81,71 +90,13 @@ struct Vlendata {
|
||||
};
|
||||
extern struct Vlendata* vlendata;
|
||||
|
||||
/* Convenience*/
|
||||
|
||||
#define SRCPUSH(iscmpd,src) {if(((iscmpd)=issublist(src))) {srcpush(src);}}
|
||||
#define SRCPOP(iscmpd,src) {if((iscmpd)) {srcpop(src);}}
|
||||
|
||||
/* from: data.c */
|
||||
int issublist(Datasrc* src);
|
||||
int isstring(Datasrc* src);
|
||||
int isfillvalue(Datasrc* src);
|
||||
int istype(Datasrc* src, nc_type);
|
||||
int isstringable(nc_type nctype);
|
||||
|
||||
#ifdef ENABLE_BINARY
|
||||
/* from: cdfdata.c */
|
||||
void bindata_array(struct Symbol*,Bytebuffer*,Datasrc*,Odometer*,int,Datalist*);
|
||||
void bindata_attrdata(struct Symbol* asym, Bytebuffer*);
|
||||
void bindata_vardata(struct Symbol* vsym, Bytebuffer*);
|
||||
void bindata_basetype(struct Symbol*,struct Datasrc*,Bytebuffer*,struct Datalist*);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_C
|
||||
/* from: cdata.c */
|
||||
void cdata_attrdata(struct Symbol* asym, Bytebuffer*);
|
||||
void cdata_array(struct Symbol*,Bytebuffer*,Datasrc*,Odometer*,int,Datalist*);
|
||||
void cdata_basetype(struct Symbol*,struct Datasrc*,Bytebuffer*,struct Datalist*);
|
||||
void cdata_vlenconstants(List*,Bytebuffer*);
|
||||
char* cdata_const(Constant*);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_F77
|
||||
/* from: f77data.c */
|
||||
void f77data_attrdata(struct Symbol* asym, Bytebuffer*);
|
||||
void f77data_array(struct Symbol*,Bytebuffer*,Datasrc*,Odometer*,int,Datalist*);
|
||||
void f77data_basetype(struct Symbol*,struct Datasrc*,Bytebuffer*,struct Datalist*);
|
||||
char* f77data_const(Constant* ci);
|
||||
void f77quotestring(Bytebuffer* databuf);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CML
|
||||
/* from: cmldata.c */
|
||||
void gencml_attrdata(struct Symbol* asym, Bytebuffer*);
|
||||
void gencml_scalardata(struct Symbol* vsym, Bytebuffer*);
|
||||
void gencml_arraydata(struct Symbol* vsym, Bytebuffer*);
|
||||
void gencml_vlenconstants(List*, Bytebuffer*);
|
||||
void gencml_fillvalue(struct Symbol*, Datalist*, Datasrc*, Bytebuffer*);
|
||||
void xquotestring(Bytebuffer* databuf);
|
||||
char* xconst(Constant* ci);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_JAVA
|
||||
/* from: jdata.c */
|
||||
void jdata_array(struct Symbol*,Bytebuffer*,Datasrc*,Odometer*,int,Datalist*);
|
||||
void jdata_basetype(struct Symbol*,struct Datasrc*,Bytebuffer*,struct Datalist*);
|
||||
char* jdata_const(Constant* ci);
|
||||
void jquotestring(Bytebuffer* databuf, char);
|
||||
#endif
|
||||
|
||||
/* from: data.c */
|
||||
Constant gen_string(unsigned long, Datasrc*);
|
||||
int stringimplode(Constant* con);
|
||||
Constant cloneconstant(Constant* con); /* shallow clone*/
|
||||
Constant gen_stringall(unsigned long size, Datasrc* src, unsigned long);
|
||||
|
||||
Constant* emptycompoundconst(int,Constant*);
|
||||
Constant* emptystringconst(int,Constant*);
|
||||
|
||||
Datasrc* datalist2src(Datalist* list);
|
||||
Datasrc* const2src(Constant*);
|
||||
Constant list2const(Datalist*);
|
||||
@ -155,28 +106,29 @@ void freedatasrc(Datasrc* src);
|
||||
void srcpush(Datasrc*);
|
||||
void srcpushlist(Datasrc* src, Datalist* cmpd);
|
||||
void srcpop(Datasrc*);
|
||||
void srcmoveto(Datasrc*,size_t);
|
||||
void srcmove(Datasrc*,size_t);
|
||||
void srcsetfill(Datasrc* ds, Datalist* list);
|
||||
|
||||
Datalist* datalistclone(Datalist* dl);
|
||||
Datalist* datalistconcat(Datalist* dl1, Datalist* dl2);
|
||||
Datalist* datalistappend(Datalist* dl, Constant* con);
|
||||
Datalist* datalistreplace(Datalist* dl, unsigned int index, Constant* con);
|
||||
int datalistline(Datalist*);
|
||||
int datalistline(Datalist*);
|
||||
#define datalistith(dl,i) ((dl)==NULL?NULL:((i) >= (dl)->length?NULL:&(dl)->data[i]))
|
||||
|
||||
Constant* srcnext(Datasrc*);
|
||||
int srclast(Datasrc*); /* are we at the last entry ? */
|
||||
int srcmore(Datasrc*);
|
||||
int srcline(Datasrc* ds);
|
||||
void srcsplice(Datasrc* ds, Datalist* list);
|
||||
|
||||
#define islistconst(con) ((con)!=NULL && (con)->nctype == NC_COMPOUND)
|
||||
#define isfillconst(con) ((con)!=NULL && (con)->nctype == NC_FILLVALUE)
|
||||
#define constline(con) (con==NULL?0:(con)->lineno)
|
||||
|
||||
Constant* emptystringconst(int,Constant*);
|
||||
|
||||
Constant cloneconstant(Constant* con); /* shallow clone*/
|
||||
|
||||
void alignbuffer(struct Constant* prim, Bytebuffer* buf);
|
||||
|
||||
/* Code dump support procedures */
|
||||
void bbindent(Bytebuffer*,const int);
|
||||
void bbprintf(Bytebuffer*,const char *fmt, ...);
|
||||
void bbprintf0(Bytebuffer*,const char *fmt, ...);
|
||||
void bbprintf(Bytebuffer*,const char *fmt, ...); /* append */
|
||||
void bbprintf0(Bytebuffer*,const char *fmt, ...); /* clear, then append*/
|
||||
/* Following dump to codebuffer */
|
||||
void codeprintf(const char *fmt, ...);
|
||||
void codedump(Bytebuffer*);
|
||||
@ -206,13 +158,37 @@ extern Constant nullconstant;
|
||||
extern Constant fillconstant;
|
||||
|
||||
/* From genchar.c */
|
||||
void gen_charattr(struct Symbol* asym, Bytebuffer* databuf);
|
||||
void gen_chararray(struct Symbol* vsym, Datasrc*, Bytebuffer* databuf, Datalist* fillsrc);
|
||||
void gen_charfield(Datasrc* src, Odometer*, Bytebuffer* databuf);
|
||||
void gen_charvlen(Datasrc*, Bytebuffer*);
|
||||
int collectstring(struct Constant*, size_t, Bytebuffer*, int);
|
||||
int getfillchar(Datalist* fillsrc);
|
||||
int buildcanonicalcharlist(Datalist*, size_t, int, Constant*);
|
||||
void padstring(Constant* con, size_t desiredlength, int fillchar);
|
||||
void gen_charattr(Datalist*, Bytebuffer*);
|
||||
void gen_charvlen(Datalist*, Bytebuffer*);
|
||||
void gen_chararray(struct Dimset*, Datalist*, Bytebuffer*, Datalist* fillsrc);
|
||||
|
||||
/* Mnemonic */
|
||||
#define UNKNOWN ((size_t)0)
|
||||
|
||||
typedef enum ListClass {
|
||||
LISTDATA, LISTATTR, LISTVLEN, LISTCOMPOUND, LISTFIELDARRAY
|
||||
} ListClass;
|
||||
|
||||
struct Generator {
|
||||
void* state;
|
||||
int (*charconstant)(Generator*,Bytebuffer*,...);
|
||||
int (*constant)(Generator*,Constant*,Bytebuffer*,...);
|
||||
int (*listbegin)(Generator*,ListClass,size_t,Bytebuffer*,int*,...);
|
||||
int (*list)(Generator*,ListClass,int,size_t,Bytebuffer*,...);
|
||||
int (*listend)(Generator*,ListClass,int,size_t,Bytebuffer*,...);
|
||||
int (*vlendecl)(Generator*,Bytebuffer*,struct Symbol*,int,size_t,...);
|
||||
int (*vlenstring)(Generator*,Bytebuffer*,int*,size_t*,...);
|
||||
};
|
||||
|
||||
extern int generator_getstate(Generator*,void**);
|
||||
extern int generator_reset(Generator*,void*);
|
||||
|
||||
typedef int (*Writer)(Generator*,struct Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
|
||||
extern void generate_attrdata(struct Symbol*, Generator*, Writer writer, Bytebuffer*);
|
||||
extern void generate_vardata(struct Symbol*, Generator*, Writer writer,Bytebuffer*);
|
||||
extern void generate_basetype(struct Symbol*,Constant*,Bytebuffer*,Datalist*,Generator*);
|
||||
|
||||
|
||||
#endif /*DATA_H*/
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifndef NCGEN_DEBUG_H
|
||||
#define NCGEN_DEBUG_H
|
||||
|
||||
/*#define F*/
|
||||
|
||||
/*********************************************************************
|
||||
* Copyright 1993, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
@ -14,6 +12,26 @@
|
||||
#include "generr.h"
|
||||
#include "bytebuffer.h"
|
||||
|
||||
#if 0
|
||||
#define GENDEBUG 2
|
||||
#endif
|
||||
|
||||
#ifdef GENDEBUG
|
||||
# define DEBUG
|
||||
# if GENDEBUG > 0
|
||||
# define DEBUG1
|
||||
# endif
|
||||
# if GENDEBUG > 1
|
||||
# define DEBUG2
|
||||
# endif
|
||||
# if GENDEBUG > 2
|
||||
# define DEBUG3
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
extern int ncgdebug;
|
||||
extern int debug;
|
||||
|
||||
|
8
ncgen/env
Normal file
8
ncgen/env
Normal file
@ -0,0 +1,8 @@
|
||||
L="-lc"
|
||||
K="-k3"
|
||||
alias q0="./ncgen -d $K $L test.cdl"
|
||||
alias qq="gdb --args ./ncgen -d $K $L test.cdl"
|
||||
alias qv="valgrind --leak-check=full ./ncgen -d $K $L test.cdl"
|
||||
|
||||
|
||||
|
@ -19,56 +19,54 @@ static void initdecodify(void);
|
||||
|
||||
void
|
||||
expand_escapes(
|
||||
char *termstring, /* returned, with escapes expanded */
|
||||
Bytebuffer *s, /* fill with contents of yytext, with escapes expanded */
|
||||
char *yytext,
|
||||
int yyleng)
|
||||
{
|
||||
char *s, *t, *endp;
|
||||
|
||||
char *t, *endp;
|
||||
yytext[yyleng-1]='\0'; /* don't copy quotes */
|
||||
/* expand "\" escapes, e.g. "\t" to tab character */
|
||||
s = termstring;
|
||||
t = yytext+1;
|
||||
while(*t) {
|
||||
if (*t == '\\') {
|
||||
t++;
|
||||
switch (*t) {
|
||||
case 'a':
|
||||
*s++ = '\007'; t++; /* will use '\a' when STDC */
|
||||
bbAppend(s,'\007'); t++; /* will use '\a' when STDC */
|
||||
break;
|
||||
case 'b':
|
||||
*s++ = '\b'; t++;
|
||||
bbAppend(s,'\b'); t++;
|
||||
break;
|
||||
case 'f':
|
||||
*s++ = '\f'; t++;
|
||||
bbAppend(s,'\f'); t++;
|
||||
break;
|
||||
case 'n':
|
||||
*s++ = '\n'; t++;
|
||||
bbAppend(s,'\n'); t++;
|
||||
break;
|
||||
case 'r':
|
||||
*s++ = '\r'; t++;
|
||||
bbAppend(s,'\r'); t++;
|
||||
break;
|
||||
case 't':
|
||||
*s++ = '\t'; t++;
|
||||
bbAppend(s,'\t'); t++;
|
||||
break;
|
||||
case 'v':
|
||||
*s++ = '\v'; t++;
|
||||
bbAppend(s,'\v'); t++;
|
||||
break;
|
||||
case '\\':
|
||||
*s++ = '\\'; t++;
|
||||
bbAppend(s,'\\'); t++;
|
||||
break;
|
||||
case '?':
|
||||
*s++ = '\177'; t++;
|
||||
bbAppend(s,'\177'); t++;
|
||||
break;
|
||||
case '\'':
|
||||
*s++ = '\''; t++;
|
||||
bbAppend(s,'\''); t++;
|
||||
break;
|
||||
case '\"':
|
||||
*s++ = '\"'; t++;
|
||||
bbAppend(s,'\"'); t++;
|
||||
break;
|
||||
case 'x':
|
||||
t++; /* now t points to one or more hex digits */
|
||||
*s++ = (char) strtol(t, &endp, 16);
|
||||
bbAppend(s,(char) strtol(t, &endp, 16));
|
||||
t = endp;
|
||||
break;
|
||||
case '0':
|
||||
@ -80,18 +78,19 @@ expand_escapes(
|
||||
case '6':
|
||||
case '7':
|
||||
/* t now points to octal digits */
|
||||
*s++ = (char) strtol(t, &endp, 8);
|
||||
bbAppend(s,(char) strtol(t, &endp, 8));
|
||||
t = endp;
|
||||
break;
|
||||
default:
|
||||
*s++ = *t++;
|
||||
bbAppend(s,*t); t++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*s++ = *t++;
|
||||
bbAppend(s,*t); t++;
|
||||
}
|
||||
}
|
||||
*s = '\0';
|
||||
bbNull(s);
|
||||
bbSetlength(s,strlen(bbContents(s)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -101,7 +100,7 @@ expand_escapes(
|
||||
*/
|
||||
/* ?? This seems redundant over expand_escapes*/
|
||||
void
|
||||
deescapify(char *name)
|
||||
deescapify(char* name)
|
||||
{
|
||||
const char *cp = name;
|
||||
char *sp;
|
||||
@ -203,13 +202,13 @@ escapifyname(char* s0)
|
||||
}
|
||||
|
||||
void
|
||||
cquotestring(Bytebuffer* databuf)
|
||||
cquotestring(Bytebuffer* databuf, char quote)
|
||||
{
|
||||
char* escaped = escapify(bbContents(databuf),'"',bbLength(databuf));
|
||||
bbClear(databuf);
|
||||
bbAppend(databuf,'"');
|
||||
bbAppend(databuf,quote);
|
||||
bbCat(databuf,escaped);
|
||||
bbAppend(databuf,'"');
|
||||
bbAppend(databuf,quote);
|
||||
}
|
||||
|
||||
/*
|
||||
|
214
ncgen/f77data.c
214
ncgen/f77data.c
@ -2,143 +2,38 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: f77data.c,v 1.4 2010/05/24 19:59:57 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/f77data.c,v 1.4 2010/05/24 19:59:57 dmh Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
#include "offsets.h"
|
||||
#include "nciter.h"
|
||||
|
||||
#ifdef ENABLE_F77
|
||||
|
||||
/* Forward*/
|
||||
static void f77data_primdata(Symbol*, Datasrc*, Bytebuffer*, Datalist*);
|
||||
#include <math.h>
|
||||
|
||||
int f77_uid = 0;
|
||||
|
||||
/**************************************************/
|
||||
/* Code for generating FORTRAN 77 language data lists*/
|
||||
/**************************************************/
|
||||
/* Datalist rules: see the rules on the man page */
|
||||
|
||||
/* Specialty wrappers for f77data_data */
|
||||
void
|
||||
f77data_attrdata(Symbol* asym, Bytebuffer* databuf)
|
||||
static int
|
||||
f77_charconstant(Generator* generator, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
Datasrc* src;
|
||||
int typecode = asym->typ.basetype->typ.typecode;
|
||||
|
||||
if(asym->data == NULL) return;
|
||||
if(typecode == NC_CHAR) {
|
||||
gen_charattr(asym,databuf);
|
||||
} else {
|
||||
src = datalist2src(asym->data);
|
||||
while(srcmore(src)) {
|
||||
bbAppend(databuf,' ');
|
||||
f77data_basetype(asym->typ.basetype,src,databuf,NULL);
|
||||
}
|
||||
}
|
||||
/* Escapes and quoting will be handled in genc_write */
|
||||
/* Just transfer charbuf to codebuf */
|
||||
Bytebuffer* charbuf;
|
||||
va_list ap;
|
||||
vastart(ap,codebuf);
|
||||
charbuf = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
bbNull(charbuf);
|
||||
bbCatbuf(codebuf,charbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
f77data_array(Symbol* vsym,
|
||||
Bytebuffer* databuf,
|
||||
Datasrc* src,
|
||||
Odometer* odom,
|
||||
int index,
|
||||
Datalist* fillsrc)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
int firstdim = (index == 0); /* last dimension*/
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
size_t count;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
int isunlimited = (odom->declsize[index] == 0);
|
||||
int pushed=0;
|
||||
|
||||
ASSERT(index >= 0 && index < rank);
|
||||
|
||||
count = odom->count[index];
|
||||
|
||||
if(!firstdim && isunlimited && issublist(src)) {
|
||||
srcpush(src);
|
||||
pushed = 1;
|
||||
}
|
||||
|
||||
if(lastdim) {
|
||||
for(i=0;i<count;i++) {
|
||||
f77data_basetype(basetype,src,databuf,fillsrc);
|
||||
}
|
||||
} else {
|
||||
/* now walk count elements and generate recursively */
|
||||
for(i=0;i<count;i++) {
|
||||
f77data_array(vsym,databuf,src,odom,index+1,fillsrc);
|
||||
}
|
||||
}
|
||||
|
||||
if(isunlimited && pushed) srcpop(src);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate an instance of the basetype using datasrc */
|
||||
void
|
||||
f77data_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* codebuf, Datalist* fillsrc)
|
||||
{
|
||||
switch (tsym->subclass) {
|
||||
|
||||
case NC_PRIM:
|
||||
if(issublist(datasrc)) {
|
||||
semerror(srcline(datasrc),"Expected primitive found {..}");
|
||||
}
|
||||
bbAppend(codebuf,' ');
|
||||
f77data_primdata(tsym,datasrc,codebuf,fillsrc);
|
||||
break;
|
||||
|
||||
default: PANIC1("f77data_basetype: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Result is a pool string or a constant => do not free*/
|
||||
char*
|
||||
f77data_const(Constant* ci)
|
||||
static int
|
||||
f77_constant(Generator* generator, Constant* ci, Bytebuffer* codebuf,...)
|
||||
{
|
||||
char tmp[64];
|
||||
char* result = NULL;
|
||||
|
||||
tmp[0] = '\0';
|
||||
char* special = NULL;
|
||||
switch (ci->nctype) {
|
||||
|
||||
case NC_CHAR:
|
||||
{
|
||||
strcpy(tmp,"'");
|
||||
@ -169,17 +64,76 @@ f77data_const(Constant* ci)
|
||||
Bytebuffer* buf = bbNew();
|
||||
bbAppendn(buf,ci->value.stringv.stringv,ci->value.stringv.len);
|
||||
f77quotestring(buf);
|
||||
result = bbDup(buf);
|
||||
special = bbDup(buf);
|
||||
bbFree(buf);
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
default: PANIC1("ncstype: bad type code: %d",ci->nctype);
|
||||
default: PANIC1("f77data: bad type code: %d",ci->nctype);
|
||||
|
||||
}
|
||||
result = pooldup(tmp);
|
||||
done:
|
||||
return result; /*except for NC_STRING and NC_OPAQUE*/
|
||||
if(special != NULL)
|
||||
bbCat(codebuf,special);
|
||||
else
|
||||
bbCat(codebuf,tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
f77_listbegin(Generator* generator, ListClass lc, size_t size, Bytebuffer* codebuf, int* uidp, ...)
|
||||
{
|
||||
if(uidp) *uidp = ++f77_uid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
f77_list(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
switch (lc) {
|
||||
case LISTATTR:
|
||||
if(count > 0) bbCat(codebuf,", ");
|
||||
break;
|
||||
case LISTDATA:
|
||||
bbAppend(codebuf,' ');
|
||||
break;
|
||||
case LISTVLEN:
|
||||
case LISTCOMPOUND:
|
||||
case LISTFIELDARRAY:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
f77_listend(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
f77_vlendecl(Generator* generator, Bytebuffer* codebuf, Symbol* tsym, int uid, size_t count, ...)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
f77_vlenstring(Generator* generator, Bytebuffer* vlenmem, int* uidp, size_t* countp,...)
|
||||
{
|
||||
if(uidp) *uidp = ++f77_uid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Define the single static bin data generator */
|
||||
static Generator f77_generator_singleton = {
|
||||
NULL,
|
||||
f77_charconstant,
|
||||
f77_constant,
|
||||
f77_listbegin,
|
||||
f77_list,
|
||||
f77_listend,
|
||||
f77_vlendecl,
|
||||
f77_vlenstring
|
||||
};
|
||||
Generator* f77_generator = &f77_generator_singleton;
|
||||
|
||||
#endif /*ENABLE_F77*/
|
||||
|
55
ncgen/foo.cdl
Normal file
55
ncgen/foo.cdl
Normal file
@ -0,0 +1,55 @@
|
||||
netcdf foo { // an example netCDF specification in CDL
|
||||
|
||||
types:
|
||||
ubyte enum enum_t {Clear = 0, Cumulonimbus = 1, Stratus = 2};
|
||||
opaque(11) opaque_t;
|
||||
int(*) vlen_t;
|
||||
|
||||
dimensions:
|
||||
lat = 10 ;
|
||||
lon = 5 ;
|
||||
time = unlimited ; // (0) currently)
|
||||
|
||||
variables:
|
||||
int lat(lat) ;
|
||||
int lon(lon) ;
|
||||
int time(time) ;
|
||||
float Z(time, lat, lon) ;
|
||||
float t(time, lat, lon) ;
|
||||
double p(time,lat,lon);
|
||||
long rh(time,lat,lon);
|
||||
string country(time,lat,lon);
|
||||
ubyte tag;
|
||||
|
||||
// variable attributes
|
||||
lat:long_name = "latitude";
|
||||
lat:units = "degrees_north";
|
||||
lon:long_name = "longitude";
|
||||
lon:units = "degrees_east";
|
||||
time:units = "seconds since 1992-1-1 00:00:00";
|
||||
|
||||
// typed variable attributes
|
||||
string Z:units = "geopotential meters";
|
||||
float Z:valid_range = 0., 5000.;
|
||||
double p:_FillValue = -9999.;
|
||||
long rh:_FillValue = -1;
|
||||
vlen_t :globalatt = {17, 18, 19};
|
||||
data:
|
||||
lat = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90;
|
||||
lon = -140, -118, -96, -84, -52;
|
||||
|
||||
group: g {
|
||||
types:
|
||||
compound cmpd_t { vlen_t f1; enum_t f2;};
|
||||
} // group g
|
||||
|
||||
group: h {
|
||||
variables:
|
||||
/g/cmpd_t compoundvar;
|
||||
data:
|
||||
compoundvar = { {3,4,5}, Stratus } ;
|
||||
} // group h
|
||||
|
||||
}//foo
|
||||
|
||||
|
216
ncgen/genbin.c
216
ncgen/genbin.c
@ -6,8 +6,6 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include <ctype.h> /* for isprint() */
|
||||
#include "nciter.h"
|
||||
#include "offsets.h"
|
||||
|
||||
#ifdef ENABLE_BINARY
|
||||
|
||||
@ -18,9 +16,11 @@ extern List* vlenconstants;
|
||||
#endif
|
||||
|
||||
/* Forward*/
|
||||
static void genbin_defineattr(Symbol* asym,Bytebuffer*);
|
||||
static void genbin_defineattr(Symbol* asym);
|
||||
static void genbin_definevardata(Symbol* vsym);
|
||||
static void genbin_write(Symbol*,Bytebuffer*,Odometer*,int);
|
||||
static int genbin_write(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static int genbin_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static int genbin_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
static void genbin_deftype(Symbol* tsym);
|
||||
@ -93,7 +93,7 @@ gen_netcdf(const char *filename)
|
||||
Symbol* dsym = (Symbol*)listget(dimdefs,idim);
|
||||
stat = nc_def_dim(dsym->container->ncid,
|
||||
dsym->name,
|
||||
dsym->dim.declsize,
|
||||
(dsym->dim.isunlimited?NC_UNLIMITED:dsym->dim.declsize),
|
||||
&dsym->ncid);
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
}
|
||||
@ -145,8 +145,7 @@ gen_netcdf(const char *filename)
|
||||
if(ngatts > 0) {
|
||||
for(iatt = 0; iatt < ngatts; iatt++) {
|
||||
Symbol* gasym = (Symbol*)listget(gattdefs,iatt);
|
||||
bbClear(databuf);
|
||||
genbin_defineattr(gasym,databuf);
|
||||
genbin_defineattr(gasym);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,8 +153,7 @@ gen_netcdf(const char *filename)
|
||||
if(natts > 0) {
|
||||
for(iatt = 0; iatt < natts; iatt++) {
|
||||
Symbol* asym = (Symbol*)listget(attdefs,iatt);
|
||||
bbClear(databuf);
|
||||
genbin_defineattr(asym,databuf);
|
||||
genbin_defineattr(asym);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +260,6 @@ genbin_deftype(Symbol* tsym)
|
||||
case NC_ENUM: {
|
||||
Bytebuffer* datum;
|
||||
Datalist* ecdl;
|
||||
Datasrc* esrc;
|
||||
stat = nc_def_enum(tsym->container->ncid,
|
||||
tsym->typ.basetype->typ.typecode,
|
||||
tsym->name,
|
||||
@ -272,14 +269,12 @@ genbin_deftype(Symbol* tsym)
|
||||
ecdl = builddatalist(1);
|
||||
dlextend(ecdl); /* make room for one constant*/
|
||||
ecdl->length = 1;
|
||||
esrc = datalist2src(ecdl);
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
|
||||
ASSERT(econst->subclass == NC_ECONST);
|
||||
ecdl->data[0] = econst->typ.econst;
|
||||
esrc->index = 0;
|
||||
generator_reset(bin_generator,NULL);
|
||||
bbClear(datum);
|
||||
bindata_basetype(econst->typ.basetype,esrc,datum,NULL);
|
||||
generate_basetype(econst->typ.basetype,&econst->typ.econst,datum,NULL,bin_generator);
|
||||
stat = nc_insert_enum(tsym->container->ncid,
|
||||
tsym->ncid,
|
||||
econst->name,
|
||||
@ -287,8 +282,6 @@ genbin_deftype(Symbol* tsym)
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
}
|
||||
bbFree(datum);
|
||||
ecdl->length = 0;
|
||||
freedatasrc(esrc);
|
||||
} break;
|
||||
case NC_VLEN:
|
||||
stat = nc_def_vlen(tsym->container->ncid,
|
||||
@ -340,7 +333,74 @@ genbin_deftype(Symbol* tsym)
|
||||
#endif /*USE_NETCDF4*/
|
||||
|
||||
static void
|
||||
genbin_defineattr(Symbol* asym,Bytebuffer* databuf)
|
||||
genbin_defineattr(Symbol* asym)
|
||||
{
|
||||
Bytebuffer* databuf = bbNew();
|
||||
generator_reset(bin_generator,NULL);
|
||||
generate_attrdata(asym,bin_generator,(Writer)genbin_write,databuf);
|
||||
}
|
||||
|
||||
|
||||
/* Following is patterned after the walk functions in semantics.c */
|
||||
static void
|
||||
genbin_definevardata(Symbol* vsym)
|
||||
{
|
||||
Bytebuffer* databuf;
|
||||
if(vsym->data == NULL) return;
|
||||
databuf = bbNew();
|
||||
generator_reset(bin_generator,NULL);
|
||||
generate_vardata(vsym,bin_generator,(Writer)genbin_write,databuf);
|
||||
}
|
||||
|
||||
static int
|
||||
genbin_write(Generator* generator, Symbol* sym, Bytebuffer* memory,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
if(sym->objectclass == NC_ATT)
|
||||
return genbin_writeattr(generator,sym,memory,rank,start,count);
|
||||
else if(sym->objectclass == NC_VAR)
|
||||
return genbin_writevar(generator,sym,memory,rank,start,count);
|
||||
else
|
||||
PANIC("illegal symbol for genc_write");
|
||||
return NC_EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
genbin_writevar(Generator* generator, Symbol* vsym, Bytebuffer* memory,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
int stat = NC_NOERR;
|
||||
char* data = bbContents(memory);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr,"startset = [");
|
||||
for(i=0;i<rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)start[i]);
|
||||
fprintf(stderr,"] ");
|
||||
fprintf(stderr,"countset = [");
|
||||
for(i=0;i<rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)count[i]);
|
||||
fprintf(stderr,"]\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(rank == 0) {
|
||||
size_t count[1] = {1};
|
||||
stat = nc_put_var1(vsym->container->ncid, vsym->ncid, count, data);
|
||||
} else {
|
||||
stat = nc_put_vara(vsym->container->ncid, vsym->ncid, start, count, data);
|
||||
}
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
bbClear(memory);
|
||||
return stat;
|
||||
}
|
||||
|
||||
static int
|
||||
genbin_writeattr(Generator* generator, Symbol* asym, Bytebuffer* databuf,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
int stat;
|
||||
size_t len;
|
||||
@ -348,17 +408,13 @@ genbin_defineattr(Symbol* asym,Bytebuffer* databuf)
|
||||
int varid, grpid, typid;
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
|
||||
bbClear(databuf);
|
||||
|
||||
grpid = asym->container->ncid,
|
||||
grpid = asym->container->ncid;
|
||||
varid = (asym->att.var == NULL?NC_GLOBAL : asym->att.var->ncid);
|
||||
typid = basetype->ncid;
|
||||
|
||||
list = asym->data;
|
||||
len = list->length;
|
||||
|
||||
bindata_attrdata(asym,databuf);
|
||||
|
||||
/* Use the specialized put_att_XX routines if possible*/
|
||||
if(isprim(basetype->typ.typecode)) {
|
||||
switch (basetype->typ.typecode) {
|
||||
@ -433,120 +489,20 @@ genbin_defineattr(Symbol* asym,Bytebuffer* databuf)
|
||||
}
|
||||
} else { /* use the generic put_attribute for user defined types*/
|
||||
const char* data;
|
||||
char out[4096];
|
||||
data = (const char*)bbContents(databuf);
|
||||
stat = nc_put_att(grpid,varid,asym->name,typid,
|
||||
len,(void*)data);
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
memset(out,0x77,sizeof(out));
|
||||
stat = nc_get_att(grpid,varid,asym->name,&out);
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Following is patterned after the walk functions in semantics.c */
|
||||
static void
|
||||
genbin_definevardata(Symbol* vsym)
|
||||
{
|
||||
Bytebuffer* memory;
|
||||
nciter_t iter;
|
||||
Odometer* odom = NULL;
|
||||
size_t nelems;
|
||||
int chartype = (vsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
Datalist* fillsrc = vsym->var.special._Fillvalue;
|
||||
int isscalar = (vsym->typ.dimset.ndims == 0);
|
||||
Datasrc* src;
|
||||
|
||||
#ifdef IGNORE
|
||||
grpid = vsym->container->ncid,
|
||||
varid = vsym->ncid;
|
||||
rank = vsym->typ.dimset.ndims;
|
||||
#ifdef DEBUG
|
||||
{
|
||||
char out[4096];
|
||||
memset(out,0x77,sizeof(out));
|
||||
stat = nc_get_att(grpid,varid,asym->name,&out);
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
}
|
||||
#endif
|
||||
|
||||
memory = bbNew();
|
||||
/* give the buffer a running start to be large enough*/
|
||||
bbSetalloc(memory, nciterbuffersize);
|
||||
|
||||
if(vsym->data == NULL) return;
|
||||
|
||||
src = datalist2src(vsym->data);
|
||||
|
||||
/* Generate character constants separately */
|
||||
if(!isscalar && chartype) {
|
||||
gen_chararray(vsym,src,memory,fillsrc);
|
||||
/* generate a corresponding odometer */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
genbin_write(vsym,memory,odom,0);
|
||||
} else { /* not character constant */
|
||||
if(isscalar) { /*scalar */
|
||||
bindata_basetype(vsym->typ.basetype,src,memory,fillsrc); /*scalar*/
|
||||
if(bbLength(memory) > 0)
|
||||
genbin_write(vsym,memory,odom,1);
|
||||
} else { /* This is the heavy lifing */
|
||||
/* Create an iterator to generate blocks of data */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
/* Fill in the local odometer instance */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
for(;;) {
|
||||
nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
if(debug > 0) {/*dump the iteration info*/
|
||||
int i;
|
||||
fprintf(stderr,"iter: %s->start[",vsym->name);
|
||||
for(i=0;i<odom->rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i==0?"":","),(unsigned long)odom->start[i]);
|
||||
fprintf(stderr,"]\n %s->count[",vsym->name);
|
||||
for(i=0;i<odom->rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i==0?"":","),(unsigned long)odom->count[i]);
|
||||
fprintf(stderr,"]\n");
|
||||
}
|
||||
bindata_array(vsym,memory,src,odom,/*index=*/0,fillsrc);
|
||||
/* Dump this chunk of (non-scalar) memory */
|
||||
genbin_write(vsym,memory,odom,0);
|
||||
}
|
||||
/* Write any residual data */
|
||||
if(bbLength(memory) > 0)
|
||||
genbin_write(vsym,memory,odom,0);
|
||||
}
|
||||
}
|
||||
odometerfree(odom);
|
||||
bbFree(memory);
|
||||
/* See if we have too much data */
|
||||
if(srcmore(src)) {
|
||||
semerror(srcline(src),"Extra data found at end of datalist");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
genbin_write(Symbol* vsym, Bytebuffer* memory, Odometer* odom, int scalar)
|
||||
{
|
||||
int stat = NC_NOERR;
|
||||
|
||||
if(!scalar && debug > 0) {
|
||||
int i;
|
||||
fprintf(stderr,"startset = [");
|
||||
for(i=0;i<odom->rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)odom->start[i]);
|
||||
fprintf(stderr,"] ");
|
||||
fprintf(stderr,"countset = [");
|
||||
for(i=0;i<odom->rank;i++)
|
||||
fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)odom->count[i]);
|
||||
fprintf(stderr,"]\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if(scalar) {
|
||||
size_t count[1] = {1};
|
||||
stat = nc_put_var1(vsym->container->ncid, vsym->ncid, count,
|
||||
bbContents(memory));
|
||||
} else {
|
||||
stat = nc_put_vara(vsym->container->ncid, vsym->ncid,
|
||||
odom->start, odom->count,
|
||||
bbContents(memory));
|
||||
}
|
||||
check_err(stat,__LINE__,__FILE__);
|
||||
bbClear(memory);
|
||||
return stat;
|
||||
}
|
||||
|
||||
#endif /*ENABLE_BINARY*/
|
||||
|
441
ncgen/genc.c
441
ncgen/genc.c
@ -12,8 +12,6 @@
|
||||
|
||||
#undef TRACE
|
||||
|
||||
extern List* vlenconstants; /* List<Constant*>;*/
|
||||
|
||||
/* Forward */
|
||||
static const char* groupncid(Symbol*);
|
||||
static const char* typencid(Symbol*);
|
||||
@ -28,9 +26,10 @@ static void genc_definespecialattributes(Symbol* vsym);
|
||||
|
||||
static void genc_defineattr(Symbol* asym);
|
||||
static void genc_definevardata(Symbol*);
|
||||
static void genc_write(Symbol*,Bytebuffer*,Odometer*,int);
|
||||
|
||||
static void computemaxunlimited(void);
|
||||
static void genc_write(Generator*,Symbol* sym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count);
|
||||
static void genc_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static void genc_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
|
||||
/*
|
||||
* Generate C code for creating netCDF from in-memory structure.
|
||||
@ -90,21 +89,6 @@ gen_ncc(const char *filename)
|
||||
}
|
||||
codeflush();
|
||||
|
||||
/*
|
||||
Define vlen constants
|
||||
The idea is to walk all the data lists
|
||||
whose variable type has a vlen and collect
|
||||
the vlen data and define a constant for it.
|
||||
*/
|
||||
{
|
||||
Bytebuffer* vlencode = bbNew();
|
||||
codeflush(); /* dump code to this point*/
|
||||
cdata_vlenconstants(vlenconstants,vlencode);
|
||||
codedump(vlencode);
|
||||
codeline("");
|
||||
bbFree(vlencode);
|
||||
}
|
||||
|
||||
/* Construct the chunking constants*/
|
||||
if(!usingclassic) {
|
||||
for(ivar=0;ivar<nvars;ivar++) {
|
||||
@ -190,7 +174,7 @@ gen_ncc(const char *filename)
|
||||
codelined(1,"/* dimension lengths */");
|
||||
for(idim = 0; idim < ndims; idim++) {
|
||||
Symbol* dsym = (Symbol*)listget(dimdefs,idim);
|
||||
if(dsym->dim.declsize == NC_UNLIMITED) {
|
||||
if(dsym->dim.isunlimited) {
|
||||
bbprintf0(stmt,"%ssize_t %s_len = NC_UNLIMITED;\n",
|
||||
indented(1),cname(dsym));
|
||||
} else {
|
||||
@ -311,10 +295,24 @@ gen_ncc(const char *filename)
|
||||
codelined(1,"/* define dimensions */");
|
||||
for(idim = 0; idim < ndims; idim++) {
|
||||
Symbol* dsym = (Symbol*)listget(dimdefs,idim);
|
||||
bbprintf0(stmt,
|
||||
" stat = nc_def_dim(%s, \"%s\", %s_len, &%s);\n",
|
||||
groupncid(dsym->container),
|
||||
escapifyname(dsym->name), cname(dsym), dimncid(dsym));
|
||||
#ifdef IGNORE
|
||||
if(dsym->dim.isunlimited) {
|
||||
bbprintf0(stmt,
|
||||
" stat = nc_def_dim(%s, \"%s\", %s, &%s);\n",
|
||||
groupncid(dsym->container),
|
||||
escapifyname(dsym->name),
|
||||
"NC_UNLIMITED",
|
||||
dimncid(dsym));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bbprintf0(stmt,
|
||||
" stat = nc_def_dim(%s, \"%s\", %s_len, &%s);\n",
|
||||
groupncid(dsym->container),
|
||||
escapifyname(dsym->name),
|
||||
cname(dsym),
|
||||
dimncid(dsym));
|
||||
}
|
||||
codedump(stmt);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
}
|
||||
@ -406,8 +404,6 @@ gen_ncc(const char *filename)
|
||||
if(vsym->data != NULL) genc_definevardata(vsym);
|
||||
}
|
||||
codeline("");
|
||||
/* compute the max actual size of the unlimited dimension*/
|
||||
if(usingclassic) computemaxunlimited();
|
||||
}
|
||||
codeflush();
|
||||
}
|
||||
@ -500,23 +496,6 @@ cl_c(void)
|
||||
*/
|
||||
|
||||
|
||||
#define INDENTMAX 256
|
||||
static char* dent = NULL;
|
||||
|
||||
char*
|
||||
indented(int n)
|
||||
{
|
||||
char* indentation;
|
||||
if(dent == NULL) {
|
||||
dent = (char*)emalloc(INDENTMAX+1);
|
||||
memset((void*)dent,' ',INDENTMAX);
|
||||
dent[INDENTMAX] = '\0';
|
||||
}
|
||||
if(n*4 >= INDENTMAX) n = INDENTMAX/4;
|
||||
indentation = dent+(INDENTMAX - 4*n);
|
||||
return indentation;
|
||||
}
|
||||
|
||||
|
||||
/* return C name for netCDF type, given type code */
|
||||
const char *
|
||||
@ -713,11 +692,15 @@ definectype(Symbol* tsym)
|
||||
case NC_ENUM:
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
|
||||
Bytebuffer* econststring = bbNew();
|
||||
ASSERT(econst->subclass == NC_ECONST);
|
||||
c_generator->constant(c_generator,&econst->typ.econst,econststring);
|
||||
bbNull(econststring);
|
||||
bbprintf0(stmt,"#define %s ((%s)%s)\n",
|
||||
cname(econst),
|
||||
ctypename(econst->typ.basetype),
|
||||
cdata_const(&econst->typ.econst));
|
||||
bbContents(econststring));
|
||||
bbFree(econststring);
|
||||
codedump(stmt);
|
||||
}
|
||||
bbprintf0(stmt,"typedef %s %s;\n",
|
||||
@ -806,9 +789,13 @@ genc_deftype(Symbol* tsym)
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
|
||||
Bytebuffer* econststring = bbNew();
|
||||
ASSERT(econst->subclass == NC_ECONST);
|
||||
c_generator->constant(c_generator,&econst->typ.econst,econststring);
|
||||
bbNull(econststring);
|
||||
bbprintf0(stmt,"%seconst = %s;\n",
|
||||
indented(1),cdata_const(&econst->typ.econst));
|
||||
indented(1),bbContents(econststring));
|
||||
bbFree(econststring);
|
||||
codedump(stmt);
|
||||
bbprintf0(stmt,"%sstat = nc_insert_enum(%s, %s, \"%s\", &econst);\n",
|
||||
indented(1),
|
||||
@ -907,32 +894,201 @@ genc_deftype(Symbol* tsym)
|
||||
static void
|
||||
genc_defineattr(Symbol* asym)
|
||||
{
|
||||
unsigned long len;
|
||||
Datalist* list;
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
Bytebuffer* code = NULL; /* capture other decls*/
|
||||
/* we need to capture vlen strings for dumping */
|
||||
Bytebuffer* save = bbNew(); /* capture so we can dump
|
||||
vlens first */
|
||||
List* oldstate = NULL;
|
||||
generator_getstate(c_generator,(void*)&oldstate);
|
||||
listfree(oldstate);
|
||||
generator_reset(c_generator,(void*)listnew());
|
||||
generate_attrdata(asym,c_generator,(Writer)genc_write,save);
|
||||
bbFree(save);
|
||||
}
|
||||
|
||||
static void
|
||||
genc_definevardata(Symbol* vsym)
|
||||
{
|
||||
Bytebuffer* save; /* capture so we can dump vlens first */
|
||||
List* oldstate = NULL;
|
||||
if(vsym->data == NULL) return;
|
||||
save = bbNew();
|
||||
generator_getstate(c_generator,(void*)&oldstate);
|
||||
listfree(oldstate);
|
||||
generator_reset(c_generator,(void*)listnew());
|
||||
generate_vardata(vsym,c_generator,(Writer)genc_write,save);
|
||||
bbFree(save);
|
||||
}
|
||||
|
||||
static void
|
||||
genc_write(Generator* generator, Symbol* sym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
if(sym->objectclass == NC_ATT)
|
||||
genc_writeattr(generator,sym,code,rank,start,count);
|
||||
else if(sym->objectclass == NC_VAR)
|
||||
genc_writevar(generator,sym,code,rank,start,count);
|
||||
else
|
||||
PANIC("illegal symbol for genc_write");
|
||||
}
|
||||
|
||||
static void
|
||||
genc_writevar(Generator* generator, Symbol* vsym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
nc_type typecode = basetype->typ.typecode;
|
||||
List* vlendecls;
|
||||
|
||||
list = asym->data;
|
||||
len = list==NULL?0:list->length;
|
||||
/* define a block to avoid name clashes*/
|
||||
codeline("");
|
||||
codelined(1,"{");
|
||||
|
||||
bbprintf0(stmt,"%s{ /* %s */\n",indented(1),asym->name);
|
||||
codedump(stmt);
|
||||
/* Dump any vlen decls first */
|
||||
generator_getstate(generator,(void**)&vlendecls);
|
||||
if(vlendecls != NULL && listlength(vlendecls) > 0) {
|
||||
int i;
|
||||
for(i=0;i<listlength(vlendecls);i++) {
|
||||
Bytebuffer* decl = (Bytebuffer*)listget(vlendecls,i);
|
||||
codelined(1,bbContents(decl));
|
||||
bbFree(decl);
|
||||
}
|
||||
listfree(vlendecls);
|
||||
generator_reset(generator,NULL);
|
||||
}
|
||||
|
||||
code = bbNew();
|
||||
cdata_attrdata(asym,code);
|
||||
if(rank == 0) {
|
||||
codelined(1,"size_t zero = 0;");
|
||||
if(typecode == NC_CHAR) {
|
||||
cquotestring(code,'"');
|
||||
bbprintf0(stmt,"%sstatic char* %s_data = %s;\n",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
bbContents(code));
|
||||
} else {
|
||||
/* We make the data be an array so we do not need to
|
||||
ampersand it later => we need an outer pair of braces
|
||||
*/
|
||||
commify(code); /* insert commas at proper places */
|
||||
bbprintf0(stmt,"%sstatic %s %s_data[1] = {%s};\n",
|
||||
indented(1),
|
||||
ctypename(basetype),
|
||||
cname(vsym),
|
||||
bbContents(code));
|
||||
}
|
||||
codedump(stmt);
|
||||
bbprintf0(stmt,"%sstat = nc_put_var1(%s, %s, &zero, %s_data);\n",
|
||||
indented(1),
|
||||
groupncid(vsym->container),
|
||||
varncid(vsym),
|
||||
cname(vsym));
|
||||
codedump(stmt);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
codeflush();
|
||||
} else { /* rank > 0 */
|
||||
int i;
|
||||
size_t length = 0;
|
||||
if(typecode == NC_CHAR) {
|
||||
length = bbLength(code);
|
||||
/* generate data constant */
|
||||
bbprintf(stmt,"%schar* %s_data = ",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
(unsigned long)length);
|
||||
codedump(stmt);
|
||||
cquotestring(code,'"');
|
||||
codedump(code);
|
||||
codeline(" ;");
|
||||
} else {
|
||||
/* Compute total size */
|
||||
length = 1;
|
||||
for(i=0;i<rank;i++) length *= count[i];
|
||||
/* generate data constant */
|
||||
commify(code); /* insert commas at proper places */
|
||||
bbprintf(stmt,"%s%s %s_data[%lu] = ",
|
||||
indented(1),
|
||||
ctypename(basetype),
|
||||
cname(vsym),
|
||||
(unsigned long)length);
|
||||
codedump(stmt);
|
||||
/* C requires an outer set of braces on datalist constants */
|
||||
codepartial("{");
|
||||
codedump(code);
|
||||
codeline("} ;");
|
||||
}
|
||||
|
||||
/* generate constants for startset, countset*/
|
||||
bbprintf0(stmt,"%ssize_t %s_startset[%lu] = {",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
rank);
|
||||
for(i=0;i<rank;i++) {
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),start[i]);
|
||||
}
|
||||
codedump(stmt);
|
||||
codeline("} ;");
|
||||
|
||||
bbprintf0(stmt,"%ssize_t %s_countset[%lu] = {",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
rank);
|
||||
for(i=0;i<rank;i++) {
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),count[i]);
|
||||
}
|
||||
codedump(stmt);
|
||||
codeline("};");
|
||||
|
||||
bbprintf0(stmt,"%sstat = nc_put_vara(%s, %s, %s_startset, %s_countset, %s_data);\n",
|
||||
indented(1),
|
||||
groupncid(vsym->container), varncid(vsym),
|
||||
cname(vsym),
|
||||
cname(vsym),
|
||||
cname(vsym));
|
||||
codedump(stmt);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
|
||||
}
|
||||
/* end defined block*/
|
||||
codelined(1,"}\n");
|
||||
codeflush();
|
||||
}
|
||||
|
||||
static void
|
||||
genc_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
int typecode = basetype->typ.typecode;
|
||||
size_t len = asym->data->length; /* default assumption */
|
||||
|
||||
/* define a block to avoid name clashes*/
|
||||
codeline("");
|
||||
codelined(1,"{");
|
||||
|
||||
/* Handle NC_CHAR specially */
|
||||
if(typecode == NC_CHAR) {
|
||||
len = bbLength(code);
|
||||
len = bbLength(code); /* presumably before quoting */
|
||||
/* Revise length if length == 0 */
|
||||
if(len == 0) len++;
|
||||
cquotestring(code);
|
||||
bbNull(code);
|
||||
cquotestring(code,'"');
|
||||
} else {
|
||||
/* All other cases */
|
||||
/* Dump any vlen decls first */
|
||||
List* vlendecls;
|
||||
generator_getstate(generator,(void**)&vlendecls);
|
||||
if(vlendecls != NULL && listlength(vlendecls) > 0) {
|
||||
int i;
|
||||
for(i=0;i<listlength(vlendecls);i++) {
|
||||
Bytebuffer* decl = (Bytebuffer*)listget(vlendecls,i);
|
||||
codelined(1,bbContents(decl));
|
||||
bbFree(decl);
|
||||
}
|
||||
listfree(vlendecls);
|
||||
generator_reset(generator,NULL);
|
||||
}
|
||||
|
||||
commify(code);
|
||||
bbprintf0(stmt,"%sstatic const %s %s_att[%ld] = ",indented(1),
|
||||
bbprintf0(stmt,"%sstatic const %s %s_att[%ld] = ",
|
||||
indented(1),
|
||||
ctypename(basetype),
|
||||
cname(asym),
|
||||
asym->data->length
|
||||
@ -946,7 +1102,6 @@ genc_defineattr(Symbol* asym)
|
||||
}
|
||||
|
||||
/* Use the specialized put_att_XX routines if possible*/
|
||||
/*defatt:*/
|
||||
switch (basetype->typ.typecode) {
|
||||
case NC_BYTE:
|
||||
case NC_SHORT:
|
||||
@ -1029,7 +1184,7 @@ genc_defineattr(Symbol* asym)
|
||||
if(usingclassic && !isclassicprim(basetype->typ.typecode)) {
|
||||
verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
|
||||
}
|
||||
bbprintf0(stmt,"%sstat = nc_put_att(%s, %s, \"%s\", %s, %lu, %s_att);",
|
||||
bbprintf0(stmt,"%sstat = nc_put_att(%s, %s, \"%s\", %s, %lu, %s_att);\n",
|
||||
indented(1),
|
||||
groupncid(asym->container),
|
||||
(asym->att.var == NULL?"NC_GLOBAL"
|
||||
@ -1043,169 +1198,7 @@ genc_defineattr(Symbol* asym)
|
||||
break;
|
||||
}
|
||||
|
||||
bbFree(code);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
codelined(1,"}");
|
||||
}
|
||||
|
||||
static void
|
||||
computemaxunlimited(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long maxsize;
|
||||
Symbol* udim = rootgroup->grp.unlimiteddim;
|
||||
if(udim == NULL) return; /* there is no unlimited dimension*/
|
||||
/* Look at each variable and see what*/
|
||||
/* size it gives to the unlimited dim (if any)*/
|
||||
maxsize = 0;
|
||||
for(i=0;i<listlength(vardefs);i++) {
|
||||
Symbol* dim;
|
||||
Symbol* var = (Symbol*)listget(vardefs,i);
|
||||
if(var->typ.dimset.ndims == 0) continue; /* rank == 0*/
|
||||
dim = var->typ.dimset.dimsyms[0];
|
||||
if(dim->dim.declsize != NC_UNLIMITED) continue; /* var does not use unlimited*/
|
||||
if(var->typ.dimset.dimsyms[0]->dim.declsize > maxsize)
|
||||
maxsize = var->typ.dimset.dimsyms[0]->dim.declsize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
genc_definevardata(Symbol* vsym)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int isscalar = (dimset->ndims == 0);
|
||||
Bytebuffer* code = NULL;
|
||||
Datasrc* src = NULL;
|
||||
Datalist* fillsrc = NULL;
|
||||
nciter_t iter;
|
||||
Odometer* odom = NULL;
|
||||
size_t nelems;
|
||||
int chartype = (vsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
if(vsym->data == NULL) return;
|
||||
src = datalist2src(vsym->data);
|
||||
|
||||
code = bbNew();
|
||||
/* give the buffer a running start to be large enough*/
|
||||
bbSetalloc(code, nciterbuffersize);
|
||||
|
||||
if(!isscalar && chartype) {
|
||||
gen_chararray(vsym,src,code,fillsrc);
|
||||
/* generate a corresponding odometer */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
/* patch the odometer to use the right counts */
|
||||
genc_write(vsym,code,odom,0);
|
||||
} else { /* not character constant */
|
||||
fillsrc = vsym->var.special._Fillvalue;
|
||||
/* Handle special cases first*/
|
||||
if(isscalar) {
|
||||
cdata_basetype(vsym->typ.basetype,src,code,fillsrc);
|
||||
commify(code);
|
||||
genc_write(vsym,code,NULL,1);
|
||||
} else { /* Non-scalar*/
|
||||
/* Create an iterator to generate blocks of data */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
/* Fill in the local odometer instance */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
for(;;) {
|
||||
nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
cdata_array(vsym,code,src,odom,/*index=*/0,fillsrc);
|
||||
commify(code);
|
||||
genc_write(vsym,code,odom,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(odom != NULL) odometerfree(odom);
|
||||
bbFree(code);
|
||||
}
|
||||
|
||||
static void
|
||||
genc_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar)
|
||||
{
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
int chartype = (vsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
if(isscalar) {
|
||||
codelined(1,"{");
|
||||
codelined(1,"size_t zero = 0;");
|
||||
bbprintf0(stmt,"%sstatic %s %s_data[1] = {%s};\n",
|
||||
indented(1),
|
||||
ctypename(basetype),
|
||||
cname(vsym),
|
||||
bbContents(code));
|
||||
codedump(stmt);
|
||||
bbprintf0(stmt,"%sstat = nc_put_var1(%s, %s, &zero, %s_data);",
|
||||
indented(1),
|
||||
groupncid(vsym->container),
|
||||
varncid(vsym),
|
||||
cname(vsym));
|
||||
codedump(stmt);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
codelined(1,"}");
|
||||
} else {
|
||||
int i;
|
||||
size_t count = 0;
|
||||
if(chartype)
|
||||
count = bbLength(code);
|
||||
else
|
||||
count = odometertotal(odom,0);
|
||||
/* define a block to avoid name clashes*/
|
||||
bbprintf0(stmt,"%s{\n",indented(1));
|
||||
/* generate data constant */
|
||||
bbprintf(stmt,"%s%s %s_data[%lu] = ",
|
||||
indented(1),
|
||||
ctypename(basetype),
|
||||
cname(vsym),
|
||||
(unsigned long)count);
|
||||
codedump(stmt);
|
||||
|
||||
if(chartype) {
|
||||
cquotestring(code);
|
||||
codedump(code);
|
||||
codeline(" ;");
|
||||
} else {
|
||||
/* C requires an outer set of braces on datalist constants */
|
||||
codepartial("{");
|
||||
codedump(code);
|
||||
codeline("} ;");
|
||||
}
|
||||
|
||||
/* generate constants for startset, countset*/
|
||||
bbprintf0(stmt,"%ssize_t %s_startset[%lu] = {",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
rank);
|
||||
for(i=0;i<rank;i++) {
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),odom->start[i]);
|
||||
}
|
||||
codedump(stmt);
|
||||
codeline("} ;");
|
||||
|
||||
bbprintf0(stmt,"%ssize_t %s_countset[%lu] = {",
|
||||
indented(1),
|
||||
cname(vsym),
|
||||
rank);
|
||||
for(i=0;i<rank;i++) {
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),odom->count[i]);
|
||||
}
|
||||
codedump(stmt);
|
||||
codeline("} ;");
|
||||
|
||||
bbprintf0(stmt,"%sstat = nc_put_vara(%s, %s, %s_startset, %s_countset, %s_data);\n",
|
||||
indented(1),
|
||||
groupncid(vsym->container), varncid(vsym),
|
||||
cname(vsym),
|
||||
cname(vsym),
|
||||
cname(vsym));
|
||||
codedump(stmt);
|
||||
codelined(1,"check_err(stat,__LINE__,__FILE__);");
|
||||
|
||||
/* end defined block*/
|
||||
codelined(1,"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*ENABLE_C*/
|
||||
|
568
ncgen/genchar.c
568
ncgen/genchar.c
@ -2,8 +2,6 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: genchar.c,v 1.6 2010/05/24 19:59:57 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/genchar.c,v 1.6 2010/05/24 19:59:57 dmh Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
@ -12,6 +10,10 @@
|
||||
language independent */
|
||||
/******************************************************/
|
||||
|
||||
static size_t gen_charconstant(Constant*, Bytebuffer*, int fillchar);
|
||||
static int getfillchar(Datalist* fillsrc);
|
||||
static void gen_chararrayr(Dimset*,int,int,Bytebuffer*,Datalist*,int,int,int);
|
||||
|
||||
/*
|
||||
Matching strings to char variables, attributes, and vlen
|
||||
constants is challenging because it is desirable to mimic
|
||||
@ -19,338 +21,171 @@ the original ncgen. The "algorithms" used there have no
|
||||
simple characterization (such as "abc" == {'a','b','c'}).
|
||||
So, this rather ugly code is kept in this file
|
||||
and a variety of heuristics are used to mimic ncgen.
|
||||
|
||||
The core algorithm is as follows.
|
||||
1. Assume we have a set of dimensions D1..Dn,
|
||||
where D1 may optionally be an Unlimited dimension.
|
||||
It is assumed that the sizes of the Di are all known.
|
||||
2. Given a sequence of string or character constants
|
||||
C1..Cm, our goal is to construct a single string
|
||||
whose length is the cross product of D1 thru Dn.
|
||||
3. For purposes of this algorithm, character constants
|
||||
are treated as strings of size 1.
|
||||
4. Construct Dx = cross product of D1 thru D(n-1).
|
||||
5. For each constant Ci, add fill characters, if necessary,
|
||||
so that its length is a multiple of Dn.
|
||||
6. Concatenate the modified C1..Cm to produce string S.
|
||||
7. Add fill characters to S to make its size be a multiple of
|
||||
Dn.
|
||||
8. If S is longer than the Dx * Dn, then truncate
|
||||
and generate a warning.
|
||||
|
||||
Two other cases:
|
||||
1. character vlen: char(*) vlen_t.
|
||||
For this case, we simply concat all the elements.
|
||||
2. character attribute.
|
||||
For this case, we simply concat all the elements.
|
||||
*/
|
||||
|
||||
static void gen_chararrayr(Dimset*, Bytebuffer*, int index, Datasrc*, int fillchar, size_t);
|
||||
void
|
||||
gen_chararray(Dimset* dimset, Datalist* data, Bytebuffer* databuf, Datalist* fillsrc)
|
||||
{
|
||||
int ndims,lastunlim;
|
||||
int fillchar = getfillchar(fillsrc);
|
||||
size_t expectedsize,xproduct;
|
||||
size_t unitsize;
|
||||
|
||||
extern List* vlenconstants;
|
||||
ASSERT(bbLength(databuf) == 0);
|
||||
|
||||
ndims = dimset->ndims;
|
||||
|
||||
|
||||
/* Find the last unlimited */
|
||||
lastunlim = findlastunlimited(dimset);
|
||||
if(lastunlim < 0) lastunlim = 0; /* pretend */
|
||||
|
||||
/* Compute crossproduct upto the last dimension,
|
||||
starting at the last unlimited
|
||||
*/
|
||||
xproduct = crossproduct(dimset,lastunlim,ndims-1);
|
||||
if(ndims == 0) {
|
||||
unitsize = 1;
|
||||
} else if(lastunlim == ndims-1) {/* last dimension is unlimited */
|
||||
unitsize = 1;
|
||||
} else { /* last dim is not unlimited */
|
||||
unitsize = dimset->dimsyms[ndims-1]->dim.declsize;
|
||||
}
|
||||
|
||||
expectedsize = (xproduct * unitsize);
|
||||
|
||||
gen_chararrayr(dimset,0,lastunlim,databuf,data,fillchar,unitsize,expectedsize);
|
||||
}
|
||||
|
||||
/* Recursive helper */
|
||||
static void
|
||||
gen_chararrayr(Dimset* dimset, int dimindex, int lastunlimited,
|
||||
Bytebuffer* databuf, Datalist* data, int fillchar,
|
||||
int unitsize, int expectedsize)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(dimindex < lastunlimited) {
|
||||
/* keep recursing */
|
||||
for(i=0;i<data->length;i++) {
|
||||
Constant* c = datalistith(data,i);
|
||||
ASSERT(islistconst(c));
|
||||
gen_chararrayr(dimset,dimindex+1,lastunlimited,databuf,
|
||||
c->value.compoundv,fillchar,unitsize,expectedsize);
|
||||
}
|
||||
} else {/* we are at a list of simple constants */
|
||||
for(i=0;i<data->length;i++) {
|
||||
Constant* c = datalistith(data,i);
|
||||
ASSERT(!islistconst(c));
|
||||
if(isstringable(c->nctype)) {
|
||||
int j;
|
||||
size_t constsize;
|
||||
constsize = gen_charconstant(c,databuf,fillchar);
|
||||
if(constsize % unitsize > 0) {
|
||||
size_t padsize = unitsize - (constsize % unitsize);
|
||||
for(j=0;j<padsize;j++) bbAppend(databuf,fillchar);
|
||||
}
|
||||
} else {
|
||||
semwarn(constline(c),
|
||||
"Encountered non-string and non-char constant in datalist; ignored");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If |databuf| > expectedsize, complain: exception is zero length */
|
||||
if(bbLength(databuf) == 0 && expectedsize == 1) {
|
||||
/* this is okay */
|
||||
} else if(bbLength(databuf) > expectedsize) {
|
||||
semwarn(data->data[0].lineno,"character data list too long");
|
||||
} else {
|
||||
size_t bufsize = bbLength(databuf);
|
||||
/* Pad to size dimproduct size */
|
||||
if(bufsize % expectedsize > 0) {
|
||||
size_t padsize = expectedsize - (bufsize % expectedsize);
|
||||
for(i=0;i<padsize;i++) bbAppend(databuf,fillchar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gen_charattr(Symbol* asym, Bytebuffer* databuf)
|
||||
gen_charattr(Datalist* data, Bytebuffer* databuf)
|
||||
{
|
||||
Datasrc* src;
|
||||
Constant* con;
|
||||
gen_charvlen(data,databuf);
|
||||
}
|
||||
|
||||
if(asym->data == NULL) return;
|
||||
src = datalist2src(asym->data);
|
||||
while((con=srcnext(src))) {
|
||||
switch (con->nctype) {
|
||||
/* Following list should be consistent with isstringable */
|
||||
case NC_CHAR:
|
||||
bbAppend(databuf,con->value.charv);
|
||||
break;
|
||||
case NC_BYTE:
|
||||
bbAppend(databuf,con->value.int8v);
|
||||
break;
|
||||
case NC_UBYTE:
|
||||
bbAppend(databuf,con->value.uint8v);
|
||||
break;
|
||||
case NC_STRING:
|
||||
bbCat(databuf,con->value.stringv.stringv);
|
||||
bbNull(databuf);
|
||||
break;
|
||||
case NC_FILL:
|
||||
bbAppend(databuf,NC_FILL_CHAR);
|
||||
break;
|
||||
default:
|
||||
semerror(srcline(src),
|
||||
"Encountered non-string constant in attribute: %s",
|
||||
asym->name);
|
||||
void
|
||||
gen_charvlen(Datalist* data, Bytebuffer* databuf)
|
||||
{
|
||||
int i;
|
||||
Constant* c;
|
||||
|
||||
ASSERT(bbLength(databuf) == 0);
|
||||
|
||||
for(i=0;i<data->length;i++) {
|
||||
c = datalistith(data,i);
|
||||
if(isstringable(c->nctype)) {
|
||||
(void)gen_charconstant(c,databuf,NC_FILL_CHAR);
|
||||
} else {
|
||||
semerror(constline(c),
|
||||
"Encountered non-string and non-char constant in datalist");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGNORE
|
||||
static void
|
||||
datalistpad(Datalist* data, size_t targetlen)
|
||||
static size_t
|
||||
gen_charconstant(Constant* con, Bytebuffer* databuf, int fillchar)
|
||||
{
|
||||
int i;
|
||||
/* pad this datalist to target length */
|
||||
for(i=data->length;i<targetlen;i++) {
|
||||
Constant ccon,scon;
|
||||
Datalist* sublist;
|
||||
ccon.nctype = NC_COMPOUND;
|
||||
ccon.lineno = 0;
|
||||
ccon.filled = 0;
|
||||
ccon.value.compoundv = builddatalist(1);
|
||||
scon.value.stringv.len = 0;
|
||||
scon.value.stringv.stringv = strdup("");
|
||||
scon.nctype = NC_STRING;
|
||||
scon.lineno = 0;
|
||||
scon.filled = 0;
|
||||
sublist = ccon.value.compoundv;
|
||||
dlappend(sublist,&scon);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*Note see comment before semantics.c:walkchararray.
|
||||
This code finishes off the processing in those comments.
|
||||
In particular, at this point, the sizes of all
|
||||
unlimited is known. Assuming the same set of
|
||||
cases as in that comment, we do the additional actions.
|
||||
Cases:
|
||||
1. the variable's dimension set has no unlimiteds
|
||||
Action:
|
||||
1. do nothing
|
||||
2. the dimension set has one or more unlimiteds.
|
||||
This means that we have to recursively deal with
|
||||
nested compound instances.
|
||||
|
||||
The last (rightmost) unlimited will correspond
|
||||
to a sequence of stringables.
|
||||
This has two special subcases
|
||||
2a. the last dimension IS NOT unlimited
|
||||
Actions:
|
||||
1. pad the concat to the size of the last dimension
|
||||
2b. the last dimension IS unlimited
|
||||
Actions:
|
||||
1. pad the concata to the actual unlimited size
|
||||
|
||||
3. For each dimension to the left of the last
|
||||
unlimited, there are two cases.
|
||||
3a. dimension is NOT unlimited
|
||||
ACTION:
|
||||
1. pad
|
||||
3b. dimension IS unlimited
|
||||
ACTION:
|
||||
1. pad
|
||||
*/
|
||||
|
||||
void
|
||||
gen_chararray(Symbol* vsym, Datasrc* data, Bytebuffer* databuf, Datalist* fillsrc)
|
||||
{
|
||||
int i,fillchar = getfillchar(fillsrc);
|
||||
int lastunlimitedindex = lastunlimited(&vsym->typ.dimset);
|
||||
|
||||
/* If there is no unlimited, then treat similarly to a field array */
|
||||
if(lastunlimitedindex < 0) {
|
||||
/* Semantics.c:walkchararray will have done all the hard work */
|
||||
while(srcmore(data)) {
|
||||
Constant* con = srcnext(data);
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
bbAppendn(databuf,con->value.stringv.stringv,con->value.stringv.len);
|
||||
}
|
||||
} else {/* dimset has at least 1 unlimited */
|
||||
/* Compute sub array size for extensions */
|
||||
size_t subsize;
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
for(subsize=1,i=lastunlimitedindex+1;i<dimset->ndims;i++) {
|
||||
Symbol* dim = dimset->dimsyms[i];
|
||||
size_t declsize = dim->dim.declsize;
|
||||
subsize *= (declsize == NC_UNLIMITED ? dim->dim.unlimitedsize : declsize);
|
||||
}
|
||||
gen_chararrayr(&vsym->typ.dimset, databuf, 0, data, fillchar, subsize);
|
||||
}
|
||||
bbNull(databuf);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_chararrayr(Dimset* dimset, Bytebuffer* databuf, int index, Datasrc* data,
|
||||
int fillchar, size_t subsize)
|
||||
{
|
||||
int i;
|
||||
Symbol* dim = dimset->dimsyms[index];
|
||||
int isunlimited = dim->dim.declsize == NC_UNLIMITED;
|
||||
int lastunlimitedindex = lastunlimited(dimset);
|
||||
|
||||
/* Split on last unlimited */
|
||||
if(index == lastunlimitedindex) {
|
||||
Constant* con;
|
||||
/* pad to the unlimited size of the dimension * subsize */
|
||||
ASSERT(srcmore(data));
|
||||
con = srcnext(data);
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
padstring(con,dim->dim.unlimitedsize*subsize,fillchar);
|
||||
bbAppendn(databuf,con->value.stringv.stringv,con->value.stringv.len);
|
||||
} else {/* index < lastunlimitedindex*/
|
||||
/* data should be a set of compounds */
|
||||
size_t expected = (isunlimited ? dim->dim.unlimitedsize : dim->dim.declsize );
|
||||
for(i=0;i<expected;i++) {
|
||||
if(!srcmore(data)) { /* pad buffer */
|
||||
int j;
|
||||
for(j=0;j<subsize;j++) bbAppend(databuf,fillchar);
|
||||
} else {
|
||||
Datasrc* subdata;
|
||||
Constant* con = srcnext(data);
|
||||
if(con->nctype != NC_COMPOUND) continue;
|
||||
/* recurse */
|
||||
subdata = datalist2src(con->value.compoundv);
|
||||
gen_chararrayr(dimset,databuf,index+1,subdata,fillchar,subsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Since the field has fixed
|
||||
dimensions, we can just
|
||||
read N elements where N
|
||||
is the product of the dimensions.
|
||||
*/
|
||||
|
||||
void
|
||||
gen_charfield(Datasrc* src, Odometer* odom, Bytebuffer* fieldbuf)
|
||||
{
|
||||
Constant* con = srcnext(src);
|
||||
|
||||
/* Semantics.c:walkcharfieldarray will have done all the hard work */
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
bbAppendn(fieldbuf,con->value.stringv.stringv,con->value.stringv.len);
|
||||
}
|
||||
|
||||
void
|
||||
gen_charvlen(Datasrc* vlensrc, Bytebuffer* databuf)
|
||||
{
|
||||
Constant* con = srcnext(vlensrc);
|
||||
|
||||
/* Semantics.c:walkcharfieldarray will have done all the hard work */
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
bbAppendn(databuf,con->value.stringv.stringv,con->value.stringv.len);
|
||||
#ifdef IGNORE
|
||||
int count;
|
||||
Bytebuffer* vlenbuf = bbNew();
|
||||
Constant* con;
|
||||
|
||||
count = 0;
|
||||
while((con=srcnext(vlensrc)) != NULL) {
|
||||
if(!isstringable(con->nctype)) {
|
||||
semerror(srcline(vlensrc),
|
||||
"Encountered non-string constant in vlen constant");
|
||||
goto done;
|
||||
}
|
||||
count += collectstring(con,0,vlenbuf);
|
||||
}
|
||||
done:
|
||||
bbFree(vlenbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
|
||||
#ifdef IGNORE
|
||||
static Datalist*
|
||||
dividestringlist(char* s, size_t chunksize, int lineno)
|
||||
{
|
||||
size_t slen,div,rem;
|
||||
Datalist* charlist;
|
||||
Constant* chars;
|
||||
|
||||
if(s == NULL) s = "";
|
||||
slen = strlen(s);
|
||||
ASSERT(chunksize > 0);
|
||||
div = slen / chunksize;
|
||||
rem = slen % chunksize;
|
||||
if(rem > 0) div++;
|
||||
|
||||
charlist = builddatalist(div);
|
||||
if(!charlist) return NULL;
|
||||
charlist->readonly = 0;
|
||||
charlist->length = div;
|
||||
chars=charlist->data;
|
||||
if(slen == 0) {
|
||||
/* Special case for null string */
|
||||
charlist->length = 1;
|
||||
chars->nctype = NC_STRING;
|
||||
chars->lineno = lineno;
|
||||
chars->value.stringv.len = 0;
|
||||
chars->value.stringv.stringv = nulldup("");
|
||||
} else
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<(div-1);i++,chars++) {
|
||||
chars->nctype = NC_STRING;
|
||||
chars->lineno = lineno;
|
||||
chars->value.stringv.len = chunksize;
|
||||
chars->value.stringv.stringv = (char*)emalloc(chunksize+1);
|
||||
memcpy(chars->value.stringv.stringv,s,chunksize);
|
||||
chars->value.stringv.stringv[chunksize] = '\0';
|
||||
s += chunksize;
|
||||
}
|
||||
/* Do last chunk */
|
||||
chars->nctype = NC_STRING;
|
||||
chars->lineno = lineno;
|
||||
chars->value.stringv.len = strlen(s);
|
||||
chars->value.stringv.stringv = nulldup(s);
|
||||
}
|
||||
return charlist;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IGNORE
|
||||
static int
|
||||
stringexplode(Datasrc* src, size_t chunksize)
|
||||
{
|
||||
Constant* con;
|
||||
Datalist* charlist;
|
||||
|
||||
if(!isstring(src)) return 0;
|
||||
con = srcnext(src);
|
||||
charlist = dividestringlist(con->value.stringv.stringv,chunksize,srcline(src));
|
||||
srcpushlist(src,charlist);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IGNORE
|
||||
static Datalist*
|
||||
padstringlist(char* s, size_t chunksize, int lineno)
|
||||
{
|
||||
size_t slen;
|
||||
Datalist* charlist;
|
||||
Constant* chars;
|
||||
|
||||
if(s == NULL) s = "";
|
||||
slen = strlen(s);
|
||||
ASSERT(chunksize > 0);
|
||||
ASSERT(chunksize >= slen);
|
||||
|
||||
charlist = builddatalist(1);
|
||||
if(!charlist) return NULL;
|
||||
charlist->readonly = 0;
|
||||
charlist->length = 1;
|
||||
chars=charlist->data;
|
||||
chars->nctype = NC_STRING;
|
||||
chars->lineno = lineno;
|
||||
chars->value.stringv.len = chunksize;
|
||||
chars->value.stringv.stringv = emalloc(chunksize+1);
|
||||
if(chars->value.stringv.stringv == NULL) return NULL;
|
||||
memset((void*)chars->value.stringv.stringv,0,chunksize+1);
|
||||
strcpy(chars->value.stringv.stringv,s);
|
||||
return charlist;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IGNORE
|
||||
static int
|
||||
stringpad(Datasrc* src, size_t chunksize)
|
||||
{
|
||||
Constant* con;
|
||||
Datalist* charlist;
|
||||
|
||||
if(!isstring(src)) return 0;
|
||||
con = srcnext(src);
|
||||
charlist = padstringlist(con->value.stringv.stringv,chunksize,srcline(src));
|
||||
srcpushlist(src,charlist);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IGNORE
|
||||
/* Fill */
|
||||
static int
|
||||
fillstring(size_t declsize, int len, Bytebuffer* databuf, int fillchar)
|
||||
{
|
||||
for(;len<declsize;len++)
|
||||
/* Following cases should be consistent with isstringable */
|
||||
size_t constsize = 1;
|
||||
switch (con->nctype) {
|
||||
case NC_CHAR:
|
||||
bbAppend(databuf,con->value.charv);
|
||||
break;
|
||||
case NC_BYTE:
|
||||
bbAppend(databuf,con->value.int8v);
|
||||
break;
|
||||
case NC_UBYTE:
|
||||
bbAppend(databuf,con->value.uint8v);
|
||||
break;
|
||||
case NC_STRING:
|
||||
constsize = con->value.stringv.len;
|
||||
bbCat(databuf,con->value.stringv.stringv);
|
||||
bbNull(databuf);
|
||||
break;
|
||||
case NC_FILL:
|
||||
bbAppend(databuf,fillchar);
|
||||
return len;
|
||||
break;
|
||||
default:
|
||||
PANIC("unexpected constant type");
|
||||
}
|
||||
return constsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
static int
|
||||
getfillchar(Datalist* fillsrc)
|
||||
{
|
||||
/* Determine the fill char */
|
||||
@ -368,102 +203,3 @@ getfillchar(Datalist* fillsrc)
|
||||
if(fillchar == 0) fillchar = NC_FILL_CHAR; /* default */
|
||||
return fillchar;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Take constant, and if stringable, append to databuf as characters.
|
||||
If the constant, as a string, is not a multiple in length of dimsize,
|
||||
then pad using fillchar
|
||||
*/
|
||||
|
||||
int
|
||||
collectstring(Constant* con, size_t dimsize, Bytebuffer* databuf, int fillchar)
|
||||
{
|
||||
size_t padding = 0;
|
||||
|
||||
if(dimsize == 0) dimsize = 1;
|
||||
if(con == NULL) con = &fillconstant;
|
||||
switch (con->nctype) {
|
||||
case NC_STRING: {
|
||||
char* s = con->value.stringv.stringv;
|
||||
size_t slen = con->value.stringv.len;
|
||||
padding = (slen % dimsize == 0 ? 0 : dimsize - (slen % dimsize));
|
||||
if(slen > 0) bbAppendn(databuf,s,slen);
|
||||
} break;
|
||||
case NC_FILLVALUE:
|
||||
padding = dimsize;
|
||||
break;
|
||||
case NC_CHAR:
|
||||
case NC_BYTE:
|
||||
case NC_UBYTE:
|
||||
/* Append */
|
||||
bbAppend(databuf,con->value.charv);
|
||||
break;
|
||||
default:
|
||||
semerror(con->lineno,"Non string or character constant encountered");
|
||||
return 0;
|
||||
}
|
||||
while(padding-- > 0) bbAppend(databuf,fillchar);
|
||||
bbNull(databuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given a list of stringables (e.g. strings),
|
||||
make each be a multiple in size of size.
|
||||
Then concat them all together and create
|
||||
and return a new Constant containg that string.
|
||||
*/
|
||||
int
|
||||
buildcanonicalcharlist(Datalist* list, size_t size, int fillchar, Constant* conp)
|
||||
{
|
||||
int i;
|
||||
Bytebuffer* buf = bbNew();
|
||||
Constant* con = NULL;
|
||||
Constant newcon = nullconstant;
|
||||
|
||||
if(list->length == 0) {
|
||||
/* If an empty list, then produce a string of size size using fillchar*/
|
||||
for(i=0;i<size;i++) bbAppend(buf,fillchar);
|
||||
} else for(i=0;i<list->length;i++) {
|
||||
con = list->data+i;
|
||||
if(!collectstring(con,size,buf,fillchar)) return 0;
|
||||
}
|
||||
bbNull(buf);
|
||||
/* Construct the new string constant */
|
||||
newcon.nctype = NC_STRING;
|
||||
newcon.lineno = (list->length == 0 ? 0: list->data[0].lineno);
|
||||
newcon.value.stringv.len = bbLength(buf);
|
||||
newcon.value.stringv.stringv = bbDup(buf);
|
||||
bbFree(buf);
|
||||
if(conp) *conp = newcon;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
padstring(Constant* con, size_t desiredlength, int fillchar)
|
||||
{
|
||||
size_t len = con->value.stringv.len;
|
||||
char* s = con->value.stringv.stringv;
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
if(len > desiredlength) {
|
||||
semerror(con->lineno,"String constant too long");
|
||||
con->value.stringv.len = desiredlength;
|
||||
} else if(len < desiredlength) {
|
||||
s = realloc(s,desiredlength+1);
|
||||
memset(s+len,fillchar,(desiredlength - len));
|
||||
s[desiredlength] = '\0';
|
||||
con->value.stringv.stringv = s;
|
||||
con->value.stringv.len = desiredlength;
|
||||
}
|
||||
}
|
||||
#ifdef IGNORE
|
||||
static size_t
|
||||
padround(size_t udimsize, Constant* con)
|
||||
{
|
||||
size_t r;
|
||||
ASSERT(con->nctype == NC_STRING);
|
||||
r = (con->value.stringv.len + (udimsize-1))/udimsize;
|
||||
r = r * udimsize;
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
390
ncgen/generate.c
Normal file
390
ncgen/generate.c
Normal file
@ -0,0 +1,390 @@
|
||||
/*********************************************************************
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
|
||||
#include "includes.h"
|
||||
#include "nciter.h"
|
||||
#include "odom.h"
|
||||
#include "offsets.h"
|
||||
|
||||
/**************************************************/
|
||||
/* Code for generating data lists*/
|
||||
/**************************************************/
|
||||
/* For datalist constant rules: see the rules on the man page */
|
||||
|
||||
/* Forward*/
|
||||
static void generate_array(Symbol*,Bytebuffer*,Datalist*,Generator*,Writer);
|
||||
static void generate_arrayr(Symbol*,Bytebuffer*,Datalist*,Odometer*,int,Datalist*,Generator*);
|
||||
static void generate_primdata(Symbol*, Constant*, Bytebuffer*, Datalist* fillsrc, Generator*);
|
||||
static void generate_fieldarray(Symbol*, Constant*, Dimset*, Bytebuffer*, Datalist* fillsrc, Generator*);
|
||||
|
||||
/* Mnemonics */
|
||||
#define VLENLIST1
|
||||
#define FIELDARRAY 1
|
||||
|
||||
/**************************************************/
|
||||
/* Generator general procedures */
|
||||
|
||||
int
|
||||
generator_getstate(Generator* generator ,void** statep)
|
||||
{
|
||||
if(statep) *statep = (void*)generator->state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int generator_reset(Generator* generator, void* state)
|
||||
{
|
||||
generator->state = state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
|
||||
void
|
||||
generate_attrdata(Symbol* asym, Generator* generator, Writer writer, Bytebuffer* codebuf)
|
||||
{
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
nc_type typecode = basetype->typ.typecode;
|
||||
|
||||
if(typecode == NC_CHAR) {
|
||||
gen_charattr(asym->data,codebuf);
|
||||
} else {
|
||||
int uid;
|
||||
size_t count;
|
||||
generator->listbegin(generator,LISTATTR,asym->data->length,codebuf,&uid);
|
||||
for(count=0;count<asym->data->length;count++) {
|
||||
Constant* con = datalistith(asym->data,count);
|
||||
generator->list(generator,LISTATTR,uid,count,codebuf);
|
||||
generate_basetype(asym->typ.basetype,con,codebuf,NULL,generator);
|
||||
}
|
||||
generator->listend(generator,LISTATTR,uid,count,codebuf);
|
||||
}
|
||||
writer(generator,asym,codebuf,0,NULL,NULL);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
generate_array(Symbol* vsym,
|
||||
Bytebuffer* code,
|
||||
Datalist* filler,
|
||||
Generator* generator,
|
||||
Writer writer
|
||||
)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
nc_type typecode = basetype->typ.typecode;
|
||||
Odometer* odom;
|
||||
nciter_t iter;
|
||||
|
||||
ASSERT(rank > 0);
|
||||
|
||||
/* Start by doing the two easy cases */
|
||||
|
||||
if(typecode == NC_CHAR) { /* case 1: character typed variable, rank > 0 */
|
||||
Bytebuffer* charbuf = bbNew();
|
||||
odom = newodometer(dimset,NULL,NULL);
|
||||
gen_chararray(dimset,vsym->data,charbuf,filler);
|
||||
generator->charconstant(generator,code,charbuf);
|
||||
bbFree(charbuf);
|
||||
writer(generator,vsym,code,odom->rank,odom->start,odom->count);
|
||||
} else
|
||||
|
||||
/* Case 2: the only unlimited is dimension 0 */
|
||||
if(findunlimited(dimset,1) == rank) {
|
||||
/* Create an iterator and odometer and just walk the datalist */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
odom = newodometer(dimset,NULL,NULL);
|
||||
for(;;) {
|
||||
int i,uid;
|
||||
size_t nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
generator->listbegin(generator,LISTDATA,vsym->data->length,code,&uid);
|
||||
for(i=0;i<nelems;i++) {
|
||||
Constant* con = datalistith(vsym->data,i);
|
||||
generator->list(generator,LISTDATA,uid,i,code);
|
||||
generate_basetype(basetype,con,code,filler,generator);
|
||||
}
|
||||
generator->listend(generator,LISTDATA,uid,i,code);
|
||||
writer(generator,vsym,code,rank,odom->start,odom->count);
|
||||
}
|
||||
} else
|
||||
|
||||
{ /* Hard case: multiple unlimited dimensions */
|
||||
/* Setup iterator and odometer */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
odom = newodometer(dimset,NULL,NULL);
|
||||
for(;;) {/* iterate in nelem chunks */
|
||||
/* get nelems count and modify odometer */
|
||||
size_t nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
generate_arrayr(vsym,code,vsym->data,
|
||||
odom,
|
||||
/*dim index=*/0,
|
||||
filler,generator
|
||||
);
|
||||
writer(generator,vsym,code,odom->rank,odom->start,odom->count);
|
||||
}
|
||||
}
|
||||
odometerfree(odom);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastunlimited = findlastunlimited(dimset);
|
||||
if(lastunlimited == rank) lastunlimited = 0;
|
||||
|
||||
ASSERT(rank > 0);
|
||||
ASSERT(dimindex >= 0 && dimindex < rank);
|
||||
ASSERT(basetype->typ.typecode != NC_CHAR);
|
||||
|
||||
|
||||
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);
|
||||
Constant* con = datalistith(list,offset);
|
||||
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 < lastunlimited
|
||||
&& (dimset->dimsyms[dimindex]->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);
|
||||
Constant* con = datalistith(list,offset);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* Generate an instance of the basetype */
|
||||
void
|
||||
generate_basetype(Symbol* tsym, Constant* 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;
|
||||
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;
|
||||
generator->listbegin(generator,LISTCOMPOUND,listlength(tsym->subnodes),codebuf,&uid);
|
||||
for(i=0;i<listlength(tsym->subnodes);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++) {
|
||||
generator->list(generator,LISTVLEN,uid,count,vlenbuf);
|
||||
generate_basetype(tsym->typ.basetype,datalistith(data,count),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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Used only for structure field arrays*/
|
||||
static void
|
||||
generate_fieldarray(Symbol* basetype, Constant* con, Dimset* dimset,
|
||||
Bytebuffer* codebuf, Datalist* filler, Generator* generator)
|
||||
{
|
||||
int i;
|
||||
int chartype = (basetype->typ.typecode == NC_CHAR);
|
||||
Datalist* data;
|
||||
|
||||
ASSERT(dimset->ndims > 0);
|
||||
|
||||
if(con != NULL && !isfillconst(con))
|
||||
data = con->value.compoundv;
|
||||
else
|
||||
data = NULL;
|
||||
|
||||
if(chartype) {
|
||||
/* Collect the char field in a separate buffer */
|
||||
Bytebuffer* charbuf = bbNew();
|
||||
gen_chararray(dimset,data,charbuf,filler);
|
||||
generator->charconstant(generator,codebuf,charbuf);
|
||||
bbFree(charbuf);
|
||||
} else {
|
||||
int uid;
|
||||
size_t xproduct = crossproduct(dimset,0,0); /* compute total number of elements */
|
||||
generator->listbegin(generator,LISTFIELDARRAY,xproduct,codebuf,&uid);
|
||||
for(i=0;i<xproduct;i++) {
|
||||
con = (data == NULL ? NULL : datalistith(data,i));
|
||||
generator->list(generator,LISTFIELDARRAY,uid,i,codebuf);
|
||||
generate_basetype(basetype,con,codebuf,NULL,generator);
|
||||
}
|
||||
generator->listend(generator,LISTFIELDARRAY,uid,i,codebuf);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -64,11 +64,41 @@ verror(fmt,va_alist) const char* fmt; va_dcl
|
||||
vderror(newfmt,argv);
|
||||
}
|
||||
|
||||
#ifndef NO_STDARG
|
||||
void
|
||||
semwarn(const int lno, const char *fmt, ...)
|
||||
#else
|
||||
void
|
||||
semwarn(lno,fmt,va_alist) const int lno; const char* fmt; va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list argv;
|
||||
vastart(argv,fmt);
|
||||
(void)fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lno);
|
||||
vderror(fmt,argv);
|
||||
}
|
||||
|
||||
#ifndef NO_STDARG
|
||||
void
|
||||
semerror(const int lno, const char *fmt, ...)
|
||||
#else
|
||||
void
|
||||
semerror(lno,fmt,va_alist) const int lno; const char* fmt; va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list argv;
|
||||
vastart(argv,fmt);
|
||||
(void)fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lno);
|
||||
vderror(fmt,argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Capture potential version errors */
|
||||
static char* markcdf4_msg = NULL;
|
||||
void
|
||||
markcdf4(const char* msg)
|
||||
{
|
||||
enhanced_flag = 1;
|
||||
if(markcdf4_msg == NULL)
|
||||
markcdf4_msg = (char*)msg;
|
||||
}
|
||||
|
391
ncgen/genf77.c
391
ncgen/genf77.c
@ -14,7 +14,7 @@
|
||||
/*MNEMONIC*/
|
||||
#define USEMEMORY 1
|
||||
|
||||
extern List* vlenconstants; /* List<Constant*>;*/
|
||||
static List* f77procs = NULL; /* bodies of generated procedures */
|
||||
|
||||
/* Forward */
|
||||
static void genf77_definevardata(Symbol* vsym);
|
||||
@ -31,13 +31,15 @@ static const char* nfstype(nc_type nctype);
|
||||
static const char* ncftype(nc_type type);
|
||||
static const char* nfdtype(nc_type type);
|
||||
|
||||
|
||||
static void f77skip(void);
|
||||
static void f77comment(char* cmt);
|
||||
static void f77fold(Bytebuffer* lines);
|
||||
static void f77flush(void);
|
||||
|
||||
static void genf77_write(Symbol*, Bytebuffer*, Odometer*, int, int);
|
||||
static void genf77_write(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static void genf77_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static void genf77_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
static char* f77prefixed(List* prefix, char* suffix, char* separator);
|
||||
@ -313,6 +315,7 @@ gen_ncf77(const char *filename)
|
||||
f77comment("leave define mode");
|
||||
codeline("stat = nf_enddef(ncid);");
|
||||
codeline("call check_err(stat)");
|
||||
f77skip();
|
||||
f77flush();
|
||||
|
||||
/* Assign scalar variable data and non-unlimited arrays in-line */
|
||||
@ -331,18 +334,26 @@ gen_ncf77(const char *filename)
|
||||
|
||||
/* Invoke write procedures */
|
||||
if(nvars > 0) {
|
||||
List* calllist;
|
||||
f77skip();
|
||||
f77skip();
|
||||
f77comment("perform variable data writes");
|
||||
for(ivar = 0; ivar < nvars; ivar++) {
|
||||
int i;
|
||||
Symbol* vsym = (Symbol*)listget(vardefs,ivar);
|
||||
/* Call the procedures for writing unlimited variables */
|
||||
if(vsym->data != NULL
|
||||
&& vsym->typ.dimset.ndims > 0) {
|
||||
bbprintf0(stmt,"call write_%s(ncid,%s_id)\n",
|
||||
f77name(vsym),f77name(vsym));
|
||||
codedump(stmt);
|
||||
genf77_definevardata(vsym);
|
||||
}
|
||||
/* dump any calls */
|
||||
generator_getstate(f77_generator,(void*)&calllist);
|
||||
ASSERT(calllist != NULL);
|
||||
for(i=0;i<listlength(calllist);i++) {
|
||||
char* callstmt = (char*)listget(calllist,i);
|
||||
codeline(callstmt);
|
||||
}
|
||||
listclear(calllist);
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,14 +363,15 @@ gen_ncf77(const char *filename)
|
||||
codeline("end");
|
||||
|
||||
/* Generate the write procedures */
|
||||
if(nvars > 0) {
|
||||
if(listlength(f77procs) > 0) {
|
||||
int i;
|
||||
f77skip();
|
||||
for(ivar = 0; ivar < nvars; ivar++) {
|
||||
Symbol* vsym = (Symbol*)listget(vardefs,ivar);
|
||||
if(vsym->data == NULL) continue;
|
||||
if(vsym->typ.dimset.ndims > 0)
|
||||
genf77_definevardata(vsym);
|
||||
for(i=0;i<listlength(f77procs);i++) {
|
||||
Bytebuffer* proctext = (Bytebuffer*)listget(f77procs,i);
|
||||
codedump(proctext);
|
||||
bbFree(proctext);
|
||||
}
|
||||
listfree(f77procs); f77procs = NULL;
|
||||
f77skip();
|
||||
}
|
||||
f77flush();
|
||||
@ -464,63 +476,13 @@ f77name(Symbol* sym)
|
||||
static void
|
||||
genf77_defineattr(Symbol* asym)
|
||||
{
|
||||
unsigned long len;
|
||||
Datalist* list;
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
Bytebuffer* code = NULL; /* capture other decls*/
|
||||
|
||||
list = asym->data;
|
||||
len = list==NULL?0:list->length;
|
||||
|
||||
bbprintf0(stmt,"* define %s\n",asym->name);
|
||||
codedump(stmt);
|
||||
|
||||
code = bbNew();
|
||||
f77data_attrdata(asym,code);
|
||||
|
||||
/* Use the specialized put_att_XX routines if possible*/
|
||||
switch (basetype->typ.typecode) {
|
||||
case NC_BYTE:
|
||||
case NC_SHORT:
|
||||
case NC_INT:
|
||||
case NC_FLOAT:
|
||||
case NC_DOUBLE:
|
||||
f77attrify(asym,code);
|
||||
codedump(code);
|
||||
bbClear(code);
|
||||
bbprintf0(stmt,"stat = nf_put_att_%s(ncid, %s, %s, %s, %lu, %sval)\n",
|
||||
nfstype(basetype->typ.typecode),
|
||||
(asym->att.var == NULL?"NF_GLOBAL"
|
||||
:f77varncid(asym->att.var)),
|
||||
f77escapifyname(asym->name),
|
||||
nftype(basetype->typ.typecode),
|
||||
len,
|
||||
ncftype(basetype->typ.typecode));
|
||||
codedump(stmt);
|
||||
break;
|
||||
|
||||
case NC_CHAR:
|
||||
len = bbLength(code);
|
||||
f77quotestring(code);
|
||||
if(len==0) len++;
|
||||
bbprintf0(stmt,"stat = nf_put_att_text(ncid, %s, %s, %lu, ",
|
||||
(asym->att.var == NULL?"NF_GLOBAL"
|
||||
:f77varncid(asym->att.var)),
|
||||
f77escapifyname(asym->name),
|
||||
len);
|
||||
codedump(stmt);
|
||||
codedump(code);
|
||||
codeline(")");
|
||||
break;
|
||||
|
||||
|
||||
default: /* User defined type */
|
||||
verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
|
||||
break;
|
||||
}
|
||||
|
||||
Bytebuffer* code = bbNew();
|
||||
List* oldstate = NULL;
|
||||
generator_getstate(f77_generator,(void*)&oldstate);
|
||||
listfree(oldstate);
|
||||
generator_reset(f77_generator,(void*)listnew());
|
||||
generate_attrdata(asym,f77_generator,(Writer)genf77_write,code);
|
||||
bbFree(code);
|
||||
codeline("call check_err(stat)");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -756,91 +718,80 @@ ncftype(nc_type type)
|
||||
static void
|
||||
genf77_definevardata(Symbol* vsym)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int isscalar = (dimset->ndims == 0);
|
||||
Bytebuffer* code = NULL;
|
||||
Datasrc* src = NULL;
|
||||
Datalist* fillsrc = NULL;
|
||||
nciter_t iter;
|
||||
Odometer* odom = NULL;
|
||||
size_t nelems;
|
||||
int chartype = (vsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
if(vsym->data == NULL) return;
|
||||
src = datalist2src(vsym->data);
|
||||
|
||||
code = bbNew();
|
||||
/* give the buffer a running start to be large enough*/
|
||||
bbSetalloc(code, nciterbuffersize);
|
||||
|
||||
if(!isscalar && chartype) {
|
||||
gen_chararray(vsym,src,code,fillsrc);
|
||||
genf77_write(vsym,code,NULL,0,0);
|
||||
} else { /* not character constant */
|
||||
fillsrc = vsym->var.special._Fillvalue;
|
||||
/* Handle special cases first*/
|
||||
if(isscalar) {
|
||||
f77data_basetype(vsym->typ.basetype,src,code,fillsrc);
|
||||
commify(code);
|
||||
genf77_write(vsym,code,NULL,1,0);
|
||||
} else { /* Non-scalar*/
|
||||
int index;
|
||||
/* Create an iterator to generate blocks of data */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
/* Fill in the local odometer instance */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
for(index=0;;index++) {
|
||||
nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
f77data_array(vsym,code,src,odom,/*index=*/0,fillsrc);
|
||||
genf77_write(vsym,code,odom,0,index);
|
||||
}
|
||||
}
|
||||
odometerfree(odom);
|
||||
}
|
||||
Bytebuffer* code = bbNew();
|
||||
List* oldstate = NULL;
|
||||
generator_getstate(f77_generator,(void*)&oldstate);
|
||||
listfree(oldstate);
|
||||
generator_reset(f77_generator,(void*)listnew());
|
||||
generate_vardata(vsym,f77_generator,(Writer)genf77_write,code);
|
||||
bbFree(code);
|
||||
}
|
||||
|
||||
static void
|
||||
genf77_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar,
|
||||
int index)
|
||||
genf77_write(Generator* generator, Symbol* sym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
if(sym->objectclass == NC_ATT)
|
||||
genf77_writeattr(generator,sym,code,rank,start,count);
|
||||
else if(sym->objectclass == NC_VAR) {
|
||||
genf77_writevar(generator,sym,code,rank,start,count);
|
||||
}
|
||||
else
|
||||
PANIC("illegal symbol for genf77_write");
|
||||
}
|
||||
|
||||
static void
|
||||
genf77_writevar(Generator* generator, Symbol* vsym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
int typecode = vsym->typ.basetype->typ.typecode;
|
||||
int chartype = (typecode == NC_CHAR);
|
||||
int i;
|
||||
|
||||
if(isscalar) {
|
||||
if(chartype) {
|
||||
bbprintf0(stmt,"stat = nf_put_var_%s(ncid, %s, %s)\n",
|
||||
/* Deal with character variables specially */
|
||||
if(typecode == NC_CHAR) {
|
||||
f77quotestring(code);
|
||||
bbprintf0(stmt,"stat = nf_put_var_%s(ncid, %s, %s)\n",
|
||||
nfstype(typecode),
|
||||
f77varncid(vsym),
|
||||
bbContents(code));
|
||||
codedump(stmt);
|
||||
} else {
|
||||
bbprintf0(stmt,"data %s /%s/\n",
|
||||
codedump(stmt);
|
||||
codeline("call check_err(stat)");
|
||||
f77skip();
|
||||
} else if(rank == 0) {
|
||||
commify(code); /* insert commas as needed */
|
||||
bbprintf0(stmt,"data %s /%s/\n",
|
||||
f77name(vsym),bbContents(code));
|
||||
codedump(stmt);
|
||||
bbprintf0(stmt,"stat = nf_put_var_%s(ncid, %s, %s)\n",
|
||||
codedump(stmt);
|
||||
bbprintf0(stmt,"stat = nf_put_var_%s(ncid, %s, %s)\n",
|
||||
nfstype(typecode),
|
||||
f77varncid(vsym),
|
||||
f77name(vsym));
|
||||
codedump(stmt);
|
||||
}
|
||||
codedump(stmt);
|
||||
codeline("call check_err(stat)");
|
||||
f77skip();
|
||||
} else { /* array */
|
||||
} else { /* rank > 0 && typecode != NC_CHAR*/
|
||||
char* dimstring;
|
||||
int index = listlength(f77procs);
|
||||
Bytebuffer* proctext;
|
||||
Bytebuffer* save;
|
||||
List* calllist;
|
||||
|
||||
/* Construct the procedure body */
|
||||
f77skip();
|
||||
if(index == 0)
|
||||
bbprintf0(stmt,"subroutine write_%s(ncid,%s_id)\n",
|
||||
f77name(vsym),f77name(vsym));
|
||||
else
|
||||
bbprintf0(stmt,"subroutine write_%s_%d(ncid,%s_id)\n",
|
||||
f77name(vsym),f77name(vsym),index);
|
||||
/* Generate the call to the procedure */
|
||||
bbprintf0(stmt,"call write_%s_%d(ncid,%s_id_%d)\n",
|
||||
f77name(vsym),index,f77name(vsym));
|
||||
/* save in the generator state */
|
||||
generator_getstate(generator,(void*)&calllist);
|
||||
ASSERT(calllist != NULL);
|
||||
listpush(calllist,(elem_t)bbDup(stmt));
|
||||
|
||||
/* Construct the procedure body and save it */
|
||||
proctext = bbNew();
|
||||
save = codebuffer;
|
||||
codebuffer = proctext;
|
||||
f77skip();
|
||||
bbprintf0(stmt,"subroutine write_%s_%d(ncid,%s_id)\n",
|
||||
f77name(vsym),index,f77name(vsym));
|
||||
codedump(stmt);
|
||||
codeline("integer ncid");
|
||||
bbprintf0(stmt,"integer %s_id\n",f77name(vsym));
|
||||
@ -856,69 +807,129 @@ genf77_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar,
|
||||
codedump(stmt);
|
||||
f77skip();
|
||||
|
||||
if(typecode != NC_CHAR) {
|
||||
/* Compute the dimensions (in reverse order for fortran) */
|
||||
bbClear(stmt);
|
||||
for(i=rank-1;i>=0;i--) {
|
||||
char tmp[32];
|
||||
nprintf(tmp,sizeof(tmp),"%s%lu",
|
||||
/* Compute the dimensions (in reverse order for fortran) */
|
||||
bbClear(stmt);
|
||||
for(i=rank-1;i>=0;i--) {
|
||||
char tmp[32];
|
||||
nprintf(tmp,sizeof(tmp),"%s%lu",
|
||||
(i==(rank-1)?"":","),
|
||||
odom->count[i]);
|
||||
bbCat(stmt,tmp);
|
||||
}
|
||||
dimstring = bbDup(stmt);
|
||||
commify(code);
|
||||
|
||||
bbprintf0(stmt,"%s %s(%s)\n",
|
||||
count[i]);
|
||||
bbCat(stmt,tmp);
|
||||
}
|
||||
dimstring = bbDup(stmt);
|
||||
commify(code);
|
||||
bbprintf0(stmt,"%s %s(%s)\n",
|
||||
nfdtype(typecode),
|
||||
f77name(vsym),
|
||||
dimstring);
|
||||
efree(dimstring);
|
||||
codedump(stmt);
|
||||
|
||||
/* Generate the data // statement */
|
||||
bbprintf0(stmt,"data %s /",f77name(vsym));
|
||||
bbCatbuf(stmt,code);
|
||||
bbCat(stmt,"/\n");
|
||||
codedump(stmt);
|
||||
}
|
||||
|
||||
/* Set the values for the start and count sets
|
||||
but in reverse order
|
||||
*/
|
||||
for(i=0;i<dimset->ndims;i++) {
|
||||
int reverse = (dimset->ndims - i) - 1;
|
||||
bbprintf0(stmt,"%s_start(%d) = %lu\n",
|
||||
f77name(vsym),
|
||||
i+1,
|
||||
odom->start[reverse]+1); /* +1 for FORTRAN */
|
||||
codedump(stmt);
|
||||
}
|
||||
for(i=0;i<dimset->ndims;i++) {
|
||||
int reverse = (dimset->ndims - i) - 1;
|
||||
bbprintf0(stmt,"%s_count(%d) = %lu\n",
|
||||
f77name(vsym),
|
||||
i+1,
|
||||
odom->count[reverse]);
|
||||
codedump(stmt);
|
||||
}
|
||||
bbprintf0(stmt,"stat = nf_put_vara_%s(ncid, %s, %s_start, %s_count, ",
|
||||
nfstype(typecode),
|
||||
f77varncid(vsym),
|
||||
f77name(vsym),
|
||||
f77name(vsym));
|
||||
efree(dimstring);
|
||||
codedump(stmt);
|
||||
if(typecode == NC_CHAR) {
|
||||
f77quotestring(code);
|
||||
codedump(code);
|
||||
} else {
|
||||
codeprintf("%s",f77name(vsym));
|
||||
}
|
||||
codeline(")");
|
||||
codeline("call check_err(stat)");
|
||||
/* Close off the procedure */
|
||||
codeline("end");
|
||||
|
||||
/* Generate the data // statement */
|
||||
commify(code); /* insert commas as needed */
|
||||
bbprintf0(stmt,"data %s /",f77name(vsym));
|
||||
bbCatbuf(stmt,code);
|
||||
bbCat(stmt,"/\n");
|
||||
codedump(stmt);
|
||||
|
||||
/* Set the values for the start and count sets
|
||||
but in reverse order
|
||||
*/
|
||||
for(i=0;i<dimset->ndims;i++) {
|
||||
int reverse = (dimset->ndims - i) - 1;
|
||||
bbprintf0(stmt,"%s_start(%d) = %lu\n",
|
||||
f77name(vsym),
|
||||
i+1,
|
||||
start[reverse]+1); /* +1 for FORTRAN */
|
||||
codedump(stmt);
|
||||
}
|
||||
for(i=0;i<dimset->ndims;i++) {
|
||||
int reverse = (dimset->ndims - i) - 1;
|
||||
bbprintf0(stmt,"%s_count(%d) = %lu\n",
|
||||
f77name(vsym),
|
||||
i+1,
|
||||
count[reverse]);
|
||||
codedump(stmt);
|
||||
}
|
||||
bbprintf0(stmt,"stat = nf_put_vara_%s(ncid, %s, %s_start, %s_count, ",
|
||||
nfstype(typecode),
|
||||
f77varncid(vsym),
|
||||
f77name(vsym),
|
||||
f77name(vsym));
|
||||
codedump(stmt);
|
||||
if(typecode == NC_CHAR) {
|
||||
f77quotestring(code);
|
||||
codedump(code);
|
||||
} else {
|
||||
codeprintf("%s",f77name(vsym));
|
||||
}
|
||||
codeline(")");
|
||||
codeline("call check_err(stat)");
|
||||
/* Close off the procedure */
|
||||
codeline("end");
|
||||
/* save the generated procedure(s) */
|
||||
if(f77procs == NULL) f77procs = listnew();
|
||||
listpush(f77procs,(elem_t)codebuffer);
|
||||
codebuffer = save;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
genf77_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Datalist* list;
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
size_t len = asym->data->length; /* default assumption */
|
||||
|
||||
list = asym->data;
|
||||
len = list==NULL?0:list->length;
|
||||
|
||||
bbprintf0(stmt,"* define %s\n",asym->name);
|
||||
codedump(stmt);
|
||||
|
||||
/* Use the specialized put_att_XX routines if possible*/
|
||||
switch (basetype->typ.typecode) {
|
||||
case NC_BYTE:
|
||||
case NC_SHORT:
|
||||
case NC_INT:
|
||||
case NC_FLOAT:
|
||||
case NC_DOUBLE:
|
||||
f77attrify(asym,code);
|
||||
codedump(code);
|
||||
bbClear(code);
|
||||
bbprintf0(stmt,"stat = nf_put_att_%s(ncid, %s, %s, %s, %lu, %sval)\n",
|
||||
nfstype(basetype->typ.typecode),
|
||||
(asym->att.var == NULL?"NF_GLOBAL"
|
||||
:f77varncid(asym->att.var)),
|
||||
f77escapifyname(asym->name),
|
||||
nftype(basetype->typ.typecode),
|
||||
len,
|
||||
ncftype(basetype->typ.typecode));
|
||||
codedump(stmt);
|
||||
break;
|
||||
|
||||
case NC_CHAR:
|
||||
len = bbLength(code);
|
||||
f77quotestring(code);
|
||||
if(len==0) len++;
|
||||
bbprintf0(stmt,"stat = nf_put_att_text(ncid, %s, %s, %lu, ",
|
||||
(asym->att.var == NULL?"NF_GLOBAL"
|
||||
:f77varncid(asym->att.var)),
|
||||
f77escapifyname(asym->name),
|
||||
len);
|
||||
codedump(stmt);
|
||||
codedump(code);
|
||||
codeline(")");
|
||||
break;
|
||||
|
||||
|
||||
default: /* User defined type */
|
||||
verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
|
||||
break;
|
||||
}
|
||||
|
||||
codeline("call check_err(stat)");
|
||||
}
|
||||
|
||||
#endif /*ENABLE_F77*/
|
||||
|
338
ncgen/genj.c
338
ncgen/genj.c
@ -21,18 +21,18 @@ extern List* vlenconstants; /* List<Constant*>;*/
|
||||
/* Forward */
|
||||
static void genj_definevardata(Symbol* vsym);
|
||||
|
||||
static void genj_defineattribute(Symbol* asym);
|
||||
static void genj_definevardata(Symbol*);
|
||||
|
||||
static void genj_write(Symbol*, Bytebuffer*, Odometer*, int, int);
|
||||
|
||||
static const char* jtypeallcaps(nc_type type);
|
||||
static const char* jtypecap(nc_type type);
|
||||
static const char* jtype(nc_type type);
|
||||
static const char* jarraytype(nc_type type);
|
||||
static const char* jname(Symbol* sym);
|
||||
|
||||
static void computemaxunlimited(void);
|
||||
static void genj_defineattr(Symbol* asym);
|
||||
static void genj_definevardata(Symbol*);
|
||||
static void genj_write(Generator*,Symbol* sym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count);
|
||||
static void genj_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
static void genj_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
|
||||
|
||||
/*
|
||||
* Generate code for creating netCDF from in-memory structure.
|
||||
@ -174,7 +174,7 @@ gen_ncjava(const char *filename)
|
||||
codelined(1,"/* assign global attributes */");
|
||||
for(iatt = 0; iatt < ngatts; iatt++) {
|
||||
Symbol* gasym = (Symbol*)listget(gattdefs,iatt);
|
||||
genj_defineattribute(gasym);
|
||||
genj_defineattr(gasym);
|
||||
}
|
||||
codeline("");
|
||||
codeflush();
|
||||
@ -186,7 +186,7 @@ gen_ncjava(const char *filename)
|
||||
codelined(1,"/* assign per-variable attributes */");
|
||||
for(iatt = 0; iatt < natts; iatt++) {
|
||||
Symbol* asym = (Symbol*)listget(attdefs,iatt);
|
||||
genj_defineattribute(asym);
|
||||
genj_defineattr(asym);
|
||||
}
|
||||
codeline("");
|
||||
codeflush();
|
||||
@ -204,8 +204,6 @@ gen_ncjava(const char *filename)
|
||||
if(vsym->data != NULL) genj_definevardata(vsym);
|
||||
}
|
||||
codeline("");
|
||||
/* compute the max actual size of the unlimited dimension*/
|
||||
if(usingclassic) computemaxunlimited();
|
||||
}
|
||||
codeflush();
|
||||
|
||||
@ -224,130 +222,6 @@ cl_java(void)
|
||||
codeflush();
|
||||
}
|
||||
|
||||
static void
|
||||
computemaxunlimited(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long maxsize;
|
||||
Symbol* udim = rootgroup->grp.unlimiteddim;
|
||||
if(udim == NULL) return; /* there is no unlimited dimension*/
|
||||
/* Look at each variable and see what*/
|
||||
/* size it gives to the unlimited dim (if any)*/
|
||||
maxsize = 0;
|
||||
for(i=0;i<listlength(vardefs);i++) {
|
||||
Symbol* dim;
|
||||
Symbol* var = (Symbol*)listget(vardefs,i);
|
||||
if(var->typ.dimset.ndims == 0) continue; /* rank == 0*/
|
||||
dim = var->typ.dimset.dimsyms[0];
|
||||
if(dim->dim.declsize != NC_UNLIMITED) continue; /* var does not use unlimited*/
|
||||
if(var->typ.dimset.dimsyms[0]->dim.declsize > maxsize)
|
||||
maxsize = var->typ.dimset.dimsyms[0]->dim.declsize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return java type name for netCDF type, given type code.
|
||||
*/
|
||||
static void
|
||||
genj_defineattribute(Symbol* asym)
|
||||
{
|
||||
unsigned long len;
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
Datalist* list;
|
||||
Bytebuffer* code = NULL; /* capture other decls*/
|
||||
nc_type typecode = basetype->typ.typecode;
|
||||
|
||||
list = asym->data;
|
||||
len = list == NULL?0:list->length;
|
||||
|
||||
codeprintf("%s/* attribute: %s */\n",indented(1),asym->name);
|
||||
|
||||
code = bbNew();
|
||||
|
||||
if(typecode == NC_CHAR) {
|
||||
gen_charattr(asym,code);
|
||||
} else {
|
||||
Datasrc* src = datalist2src(asym->data);
|
||||
while(srcmore(src)) {
|
||||
jdata_basetype(asym->typ.basetype,src,code,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle NC_CHAR specially */
|
||||
if(typecode == NC_CHAR) {
|
||||
/* revise the length count */
|
||||
len = bbLength(code);
|
||||
if(len == 0) {
|
||||
bbAppend(code,'\0'); len++;
|
||||
bbClear(code);
|
||||
bbCat(code,"\"\"");
|
||||
len++;
|
||||
} else
|
||||
jquotestring(code,'"');
|
||||
bbNull(code);
|
||||
} else {
|
||||
char* code2;
|
||||
commify(code);
|
||||
/* Convert to constant */
|
||||
code2 = bbDup(code);
|
||||
bbClear(code);
|
||||
bbprintf0(stmt,"new %s[]",
|
||||
jarraytype(typecode));
|
||||
bbCatbuf(code,stmt);
|
||||
bbCat(code,"{");
|
||||
bbCat(code,code2);
|
||||
bbCat(code,"}");
|
||||
efree(code2);
|
||||
}
|
||||
switch (typecode) {
|
||||
case NC_BYTE:
|
||||
case NC_SHORT:
|
||||
case NC_INT:
|
||||
case NC_FLOAT:
|
||||
case NC_DOUBLE:
|
||||
codelined(1,"{");
|
||||
bbprintf0(stmt,"%sArray data = Array.factory(%s.class, new int[]{%lu}, ",
|
||||
indented(1),
|
||||
jtype(basetype->typ.typecode),
|
||||
len);
|
||||
codedump(stmt);
|
||||
codedump(code);
|
||||
codeline(");");
|
||||
if(asym->att.var == NULL) {
|
||||
bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",data);\n",
|
||||
indented(1),jescapifyname(asym->name));
|
||||
} else {
|
||||
bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",data);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->att.var->name),
|
||||
jescapifyname(asym->name));
|
||||
}
|
||||
codedump(stmt);
|
||||
codelined(1,"}");
|
||||
codeflush();
|
||||
break;
|
||||
|
||||
case NC_CHAR:
|
||||
if(asym->att.var == NULL) {
|
||||
bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",%s);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->name),
|
||||
bbContents(code));
|
||||
} else {
|
||||
bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",%s);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->att.var->name),
|
||||
jescapifyname(asym->name),
|
||||
bbContents(code));
|
||||
}
|
||||
codedump(stmt);
|
||||
codeflush();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
jtypeallcaps(nc_type type)
|
||||
{
|
||||
@ -539,84 +413,66 @@ jstype(nc_type nctype)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
genj_defineattr(Symbol* asym)
|
||||
{
|
||||
Bytebuffer* code; /* capture so we can dump vlens first */
|
||||
ASSERT(asym->data != NULL);
|
||||
code = bbNew();
|
||||
generator_reset(j_generator,NULL);
|
||||
generate_attrdata(asym,j_generator,(Writer)genj_write,code);
|
||||
bbFree(code);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
genj_definevardata(Symbol* vsym)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int isscalar = (dimset->ndims == 0);
|
||||
Bytebuffer* code;
|
||||
Datasrc* src = NULL;
|
||||
Datalist* fillsrc = NULL;
|
||||
nciter_t iter;
|
||||
Odometer* odom = NULL;
|
||||
size_t nelems;
|
||||
int chartype = (vsym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
Bytebuffer* code; /* capture so we can dump vlens first */
|
||||
if(vsym->data == NULL) return;
|
||||
src = datalist2src(vsym->data);
|
||||
|
||||
code = bbNew();
|
||||
/* give the buffer a running start to be large enough*/
|
||||
bbSetalloc(code, nciterbuffersize);
|
||||
|
||||
if(!isscalar && chartype) {
|
||||
gen_chararray(vsym,src,code,fillsrc);
|
||||
genj_write(vsym,code,NULL,0,0);
|
||||
} else { /* not character constant */
|
||||
fillsrc = vsym->var.special._Fillvalue;
|
||||
/* Handle special cases first*/
|
||||
if(isscalar) {
|
||||
jdata_basetype(vsym->typ.basetype,src,code,fillsrc);
|
||||
commify(code);
|
||||
genj_write(vsym,code,NULL,1,0);
|
||||
} else { /* Non-scalar*/
|
||||
int index;
|
||||
/* Create an iterator to generate blocks of data */
|
||||
nc_get_iter(vsym,nciterbuffersize,&iter);
|
||||
/* Fill in the local odometer instance */
|
||||
odom = newodometer(&vsym->typ.dimset,NULL,NULL);
|
||||
for(index=0;;index++) {
|
||||
nelems=nc_next_iter(&iter,odom->start,odom->count);
|
||||
if(nelems == 0) break;
|
||||
jdata_array(vsym,code,src,odom,/*index=*/0,fillsrc);
|
||||
genj_write(vsym,code,odom,0,index);
|
||||
}
|
||||
}
|
||||
odometerfree(odom);
|
||||
}
|
||||
generator_reset(j_generator,NULL);
|
||||
generate_vardata(vsym,j_generator,(Writer)genj_write,code);
|
||||
bbFree(code);
|
||||
}
|
||||
|
||||
static void
|
||||
genj_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar, int index)
|
||||
genj_write(Generator* generator, Symbol* sym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
if(sym->objectclass == NC_ATT)
|
||||
genj_writeattr(generator,sym,code,rank,start,count);
|
||||
else if(sym->objectclass == NC_VAR)
|
||||
genj_writevar(generator,sym,code,rank,start,count);
|
||||
else
|
||||
PANIC("illegal symbol for genj_write");
|
||||
}
|
||||
|
||||
static void
|
||||
genj_writevar(Generator* generator, Symbol* vsym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
int typecode = vsym->typ.basetype->typ.typecode;
|
||||
int chartype = (typecode == NC_CHAR);
|
||||
int i;
|
||||
|
||||
codeline("");
|
||||
codelined(1,"{"); /* Enclose in {...} for scoping */
|
||||
|
||||
if(isscalar) {
|
||||
/* Construct the data Array */
|
||||
if(rank == 0) {
|
||||
bbprintf0(stmt,"%sArray%s.D0 data = new Array%s.D0();\n",
|
||||
indented(1),jtypecap(typecode), jtypecap(typecode));
|
||||
codedump(stmt);
|
||||
if(chartype) {
|
||||
#ifdef IGNORE
|
||||
jquotestring(code,'"');
|
||||
bbprintf0(stmt,"%sdata.set(%s.charAt(0));\n",
|
||||
indented(1),bbContents(code));
|
||||
#else
|
||||
bbprintf0(stmt,"%sdata.set((char)%s);\n",
|
||||
indented(1),bbContents(code));
|
||||
#endif
|
||||
if(typecode == NC_CHAR) {
|
||||
/* Construct the data Array */
|
||||
jquotestring(code,'\'');
|
||||
bbprintf0(stmt,"%sdata.set((char)%s);\n",
|
||||
indented(1),bbContents(code));
|
||||
} else {
|
||||
commify(code);
|
||||
bbprintf0(stmt,"%sdata.set((%s)%s);\n",
|
||||
indented(1),jtype(typecode),bbContents(code));
|
||||
}
|
||||
indented(1),jtype(typecode),bbContents(code));
|
||||
}
|
||||
codedump(stmt);
|
||||
/* do the actual write */
|
||||
bbprintf0(stmt,"%sncfile.write(\"%s\",data);\n",
|
||||
@ -629,10 +485,7 @@ genj_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar, int ind
|
||||
for(i=0;i<rank;i++) {
|
||||
Symbol* dsym = dimset->dimsyms[i];
|
||||
char tmp[32];
|
||||
if(i==0 && dsym->dim.declsize == NC_UNLIMITED)
|
||||
nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.unlimitedsize);
|
||||
else
|
||||
nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.declsize);
|
||||
nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.declsize);
|
||||
if(i>0) {bbCat(dimbuf,", ");}
|
||||
bbCat(dimbuf,tmp);
|
||||
}
|
||||
@ -668,10 +521,10 @@ genj_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar, int ind
|
||||
indented(2),jtypecap(typecode));
|
||||
codedump(stmt);
|
||||
bbFree(dimbuf);
|
||||
/* Construct the origin set from the odometer start set */
|
||||
/* Construct the origin set from the start set */
|
||||
bbprintf0(stmt,"%sint[] origin = new int[]{",indented(1));
|
||||
for(i=0;i<rank;i++) {
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),odom->start[i]);
|
||||
bbprintf(stmt,"%s%lu",(i>0?", ":""),start[i]);
|
||||
}
|
||||
bbCat(stmt,"};\n");
|
||||
codedump(stmt);
|
||||
@ -681,5 +534,98 @@ genj_write(Symbol* vsym, Bytebuffer* code, Odometer* odom, int isscalar, int ind
|
||||
codedump(stmt);
|
||||
}
|
||||
codelined(1,"}"); /* Enclose in {...} for scoping */
|
||||
codeflush();
|
||||
}
|
||||
|
||||
static void
|
||||
genj_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code,
|
||||
int rank, size_t* start, size_t* count)
|
||||
{
|
||||
Symbol* basetype = asym->typ.basetype;
|
||||
nc_type typecode = basetype->typ.typecode;
|
||||
size_t len = asym->data->length; /* default assumption */
|
||||
Datalist* list;
|
||||
|
||||
list = asym->data;
|
||||
len = list == NULL?0:list->length;
|
||||
|
||||
codeprintf("%s/* attribute: %s */\n",indented(1),asym->name);
|
||||
|
||||
/* Handle NC_CHAR specially */
|
||||
if(typecode == NC_CHAR) {
|
||||
/* revise the length count */
|
||||
len = bbLength(code);
|
||||
if(len == 0) {
|
||||
bbAppend(code,'\0'); len++;
|
||||
bbClear(code);
|
||||
bbCat(code,"\"\"");
|
||||
len++;
|
||||
} else
|
||||
jquotestring(code,'"');
|
||||
bbNull(code);
|
||||
} else { /* not NC_CHAR*/
|
||||
char* code2;
|
||||
commify(code);
|
||||
/* Convert to constant */
|
||||
code2 = bbDup(code);
|
||||
bbClear(code);
|
||||
bbprintf0(stmt,"new %s[]",
|
||||
jarraytype(typecode));
|
||||
bbCatbuf(code,stmt);
|
||||
bbCat(code,"{");
|
||||
bbCat(code,code2);
|
||||
bbCat(code,"}");
|
||||
efree(code2);
|
||||
}
|
||||
switch (typecode) {
|
||||
case NC_BYTE:
|
||||
case NC_SHORT:
|
||||
case NC_INT:
|
||||
case NC_FLOAT:
|
||||
case NC_DOUBLE:
|
||||
codelined(1,"{");
|
||||
bbprintf0(stmt,"%sArray data = Array.factory(%s.class, new int[]{%lu}, ",
|
||||
indented(1),
|
||||
jtype(basetype->typ.typecode),
|
||||
len);
|
||||
codedump(stmt);
|
||||
codedump(code);
|
||||
codeline(");");
|
||||
if(asym->att.var == NULL) {
|
||||
bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",data);\n",
|
||||
indented(1),jescapifyname(asym->name));
|
||||
} else {
|
||||
bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",data);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->att.var->name),
|
||||
jescapifyname(asym->name));
|
||||
}
|
||||
codedump(stmt);
|
||||
codelined(1,"}");
|
||||
codeflush();
|
||||
break;
|
||||
|
||||
case NC_CHAR:
|
||||
if(asym->att.var == NULL) {
|
||||
bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",%s);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->name),
|
||||
bbContents(code));
|
||||
} else {
|
||||
bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",%s);\n",
|
||||
indented(1),
|
||||
jescapifyname(asym->att.var->name),
|
||||
jescapifyname(asym->name),
|
||||
bbContents(code));
|
||||
}
|
||||
codedump(stmt);
|
||||
codeflush();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
codeflush();
|
||||
}
|
||||
|
||||
|
||||
#endif /*ENABLE_JAVA*/
|
||||
|
@ -39,6 +39,7 @@ extern void verror ( const char *fmt, ... )
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
extern void markcdf4(const char *msg);
|
||||
extern char* getmarkcdf4(void);
|
||||
|
||||
@ -54,13 +55,14 @@ extern void close_netcdf ( void ); /* generates close */
|
||||
extern char* cprefixed(List* prefix, char* suffix, char* separator);
|
||||
|
||||
/* from: escapes.c */
|
||||
extern void expand_escapes ( char* termstring, char* yytext, int yyleng );
|
||||
extern void expand_escapes (Bytebuffer* termstring, char* yytext, int yyleng );
|
||||
extern void deescapify(char *name); /* redunandt over expand_escapes?*/
|
||||
extern char* decodify(const char *name);
|
||||
extern char* escapifychar(unsigned int c, char* s0, int quote);
|
||||
extern char* escapify(char*,int,size_t);
|
||||
extern char* escapifyname(char* s0);
|
||||
extern void cquotestring(Bytebuffer*);
|
||||
extern void cquotestring(Bytebuffer*,char quote);
|
||||
extern void f77quotestring(Bytebuffer*);
|
||||
extern char* f77escapifyname(char* s0);
|
||||
extern char* xescapify(char* s0, int quote, size_t len);
|
||||
extern char* jescapify(char* s0, int quote, size_t len);
|
||||
@ -70,8 +72,7 @@ extern char* jdecodify(const char *name);
|
||||
/* from: getfill.c */
|
||||
extern void nc_getfill(Constant*);
|
||||
extern char* nc_dfaltfillname(nc_type);
|
||||
extern struct Datalist* getfiller(Symbol*,Datalist*); /* type or variable*/
|
||||
extern int checkfillvalue(Symbol*, struct Datalist*);
|
||||
extern struct Datalist* getfiller(Symbol*); /* symbol isa variable|type */
|
||||
|
||||
/* from: ncgen.y */
|
||||
extern Symbol* install(const char *sname);
|
||||
@ -93,32 +94,36 @@ extern Symbol* lookupingroup(nc_class objectclass, char* name, Symbol* grp);
|
||||
extern Symbol* lookupgroup(List* prefix);
|
||||
#ifndef NO_STDARG
|
||||
extern void semerror(const int, const char *fmt, ...);
|
||||
extern void semwarn(const int, const char *fmt, ...);
|
||||
#else
|
||||
extern void semerror(lno,fmt,va_alist) const int lno; const char* fmt; va_dcl;
|
||||
extern void semwarnlno,fmt,va_alist) const int lno; const char* fmt; va_dcl;
|
||||
#endif
|
||||
extern int nounlimited(Dimset* dimset, int from);
|
||||
extern int lastunlimited(Dimset* dimset);
|
||||
extern void padstring(Constant* con, size_t desiredlength, int fillchar);
|
||||
|
||||
|
||||
extern Datalist* explodestrings(Datalist*,char*);
|
||||
extern Datalist* implodestrings(Datalist*,char*);
|
||||
extern int explodestringconst(Constant* con, char* tag, Constant*);
|
||||
|
||||
extern char* indented(int n);
|
||||
|
||||
/* Generators for cdf, c, and fortran */
|
||||
|
||||
#ifdef ENABLE_BINARY
|
||||
/* from: genbin.c */
|
||||
extern Generator* bin_generator;
|
||||
extern void gen_netcdf(const char *filename);
|
||||
extern void cl_netcdf(void);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_C
|
||||
/* from: genc.c */
|
||||
extern Generator* c_generator;
|
||||
extern void gen_ncc(const char *filename);
|
||||
extern void cl_c(void);
|
||||
extern const char* ctypename(Symbol*);
|
||||
extern char* indented(int n);
|
||||
extern const char* nctype(nc_type type);
|
||||
extern const char* ncctype(nc_type type);
|
||||
extern const char* ncstype(nc_type type);
|
||||
@ -126,22 +131,16 @@ extern const char* ncstype(nc_type type);
|
||||
|
||||
#ifdef ENABLE_F77
|
||||
/* from: genf77.c */
|
||||
extern Generator* f77_generator;
|
||||
extern void gen_ncf77(const char *filename);
|
||||
extern void cl_f77(void);
|
||||
extern const char* f77name(Symbol*);
|
||||
extern const char* f77typename(Symbol*);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CML
|
||||
/* from: gencml.c */
|
||||
extern void gen_nccml(const char *filename);
|
||||
extern void cl_cml(void);
|
||||
extern char* xname(struct Symbol* sym);
|
||||
extern char* xtypename(struct Symbol* tsym);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_JAVA
|
||||
/* from: genj.c */
|
||||
extern Generator* j_generator;
|
||||
extern void gen_ncjava(const char *filename);
|
||||
extern void cl_java(void);
|
||||
extern void jpartial(char*);
|
||||
@ -150,9 +149,12 @@ extern void jlined(int,char*);
|
||||
extern void jflush(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* from: main.c */
|
||||
extern int usingclassic; /* 0=>false; 1=>true; */
|
||||
extern int allowspecial;
|
||||
extern int format_flag; /* _Format attribute value (same range as -k flag) */
|
||||
extern int enhanced_flag; /* 1 => netcdf-4 constructs appear in the parse */
|
||||
extern int specials_flag; /* 1 => special attributes are present */
|
||||
extern int usingclassic; /* 1 => k_flag == 1|2 */
|
||||
|
||||
/* Global data */
|
||||
|
||||
|
128
ncgen/getfill.c
128
ncgen/getfill.c
@ -11,68 +11,58 @@
|
||||
#define TOPLEVEL 1
|
||||
|
||||
/*Forward*/
|
||||
static Datalist* buildfill(Symbol* tsym);
|
||||
static void fill(Symbol* tsym, Datalist*);
|
||||
static void fillarray(Symbol* tsym, Dimset* dimset, int index, Datalist*);
|
||||
static void filllist(Symbol* tvsym, Datalist* dl);
|
||||
static int checkfill(Symbol* tvsym, Datasrc* src, Symbol*);
|
||||
static int checkarray(Symbol* tsym, Dimset* dimset, int index, Datasrc*, Symbol*, int);
|
||||
|
||||
|
||||
/* Construct a Datalist representing a complete fill value*/
|
||||
/* for a specified type*/
|
||||
/* for a specified variable */
|
||||
/* Cache if needed later*/
|
||||
|
||||
Datalist*
|
||||
getfiller(Symbol* tvsym, Datalist* fillsrc)
|
||||
getfiller(Symbol* tvsym)
|
||||
{
|
||||
Datalist* filler = fillsrc;
|
||||
if(filler == NULL)
|
||||
Datalist* filler = NULL;
|
||||
Symbol* tsym = tvsym;
|
||||
ASSERT(tvsym->objectclass == NC_VAR || tvsym->objectclass == NC_TYPE);
|
||||
if(tvsym->objectclass == NC_VAR) {
|
||||
tsym = tvsym->typ.basetype;
|
||||
filler = tvsym->var.special._Fillvalue; /* get cached value (if any)*/
|
||||
if(filler == NULL) { /* need to compute it*/
|
||||
filler = buildfill(tvsym);
|
||||
tvsym->var.special._Fillvalue = filler; /* cache value*/
|
||||
}
|
||||
if(debug >= 1)
|
||||
if(filler == NULL || tvsym->objectclass == NC_TYPE) {
|
||||
filler = tvsym->typ._Fillvalue; /* get cached value (if any)*/
|
||||
}
|
||||
if(filler == NULL) { /* need to compute it*/
|
||||
filler = builddatalist(0);
|
||||
fill(tsym,filler);
|
||||
}
|
||||
#ifdef DEBUG2
|
||||
dumpdatalist(filler,"getfiller");
|
||||
#endif
|
||||
if(tvsym->objectclass == NC_VAR) {
|
||||
tvsym->var.special._Fillvalue = filler;
|
||||
} else if(tvsym->objectclass == NC_TYPE) {
|
||||
tvsym->typ._Fillvalue = filler; /* cache value*/
|
||||
}
|
||||
return filler;
|
||||
}
|
||||
|
||||
static Datalist*
|
||||
buildfill(Symbol* tvasym)
|
||||
{
|
||||
Datalist* filler = builddatalist(0);
|
||||
ASSERT(tvasym->objectclass == NC_VAR
|
||||
|| tvasym->objectclass == NC_TYPE
|
||||
|| tvasym->objectclass == NC_ATT);
|
||||
if(tvasym->objectclass == NC_VAR) {
|
||||
if(tvasym->typ.dimset.ndims > 0) {
|
||||
fillarray(tvasym->typ.basetype,&tvasym->typ.dimset,0,filler);
|
||||
} else
|
||||
fill(tvasym->typ.basetype,filler);
|
||||
} else if(tvasym->objectclass == NC_ATT) {
|
||||
fill(tvasym->typ.basetype,filler);
|
||||
} else /*NC_TYPE*/
|
||||
fill(tvasym,filler);
|
||||
return filler;
|
||||
}
|
||||
|
||||
static void
|
||||
fill(Symbol* tvsym, Datalist* filler)
|
||||
fill(Symbol* tsym, Datalist* filler)
|
||||
{
|
||||
int i;
|
||||
Constant con;
|
||||
Datalist* sublist;
|
||||
/* NC_TYPE case*/
|
||||
switch (tvsym->subclass) {
|
||||
ASSERT(tsym->objectclass == NC_TYPE);
|
||||
switch (tsym->subclass) {
|
||||
case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
|
||||
con.nctype = tvsym->typ.typecode;
|
||||
con.nctype = tsym->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);
|
||||
sublist = builddatalist(listlength(tsym->subnodes));
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* field = (Symbol*)listget(tsym->subnodes,i);
|
||||
if(field->typ.dimset.ndims > 0) {
|
||||
fillarray(field->typ.basetype,&field->typ.dimset,0,filler);
|
||||
} else
|
||||
@ -82,32 +72,32 @@ fill(Symbol* tvsym, Datalist* filler)
|
||||
break;
|
||||
case NC_VLEN:
|
||||
sublist = builddatalist(0);
|
||||
filllist(tvsym->typ.basetype,sublist); /* generate a single instance*/
|
||||
filllist(tsym->typ.basetype,sublist); /* generate a single instance*/
|
||||
con = builddatasublist(sublist);
|
||||
break;
|
||||
default: PANIC1("fill: unexpected subclass %d",tvsym->subclass);
|
||||
default: PANIC1("fill: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
dlappend(filler,&con);
|
||||
}
|
||||
|
||||
static void
|
||||
filllist(Symbol* tvsym, Datalist* dl)
|
||||
filllist(Symbol* tsym, Datalist* dl)
|
||||
{
|
||||
int i;
|
||||
Datalist* sublist;
|
||||
Constant con;
|
||||
|
||||
/* NC_TYPE case*/
|
||||
switch (tvsym->subclass) {
|
||||
ASSERT(tsym->objectclass == NC_TYPE);
|
||||
switch (tsym->subclass) {
|
||||
case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
|
||||
con.nctype = tvsym->typ.typecode;
|
||||
con.nctype = tsym->typ.typecode;
|
||||
nc_getfill(&con);
|
||||
dlappend(dl,&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);
|
||||
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);
|
||||
@ -115,11 +105,11 @@ filllist(Symbol* tvsym, Datalist* dl)
|
||||
break;
|
||||
case NC_VLEN:
|
||||
sublist = builddatalist(0);
|
||||
filllist(tvsym->typ.basetype,sublist); /* generate a single instance*/
|
||||
filllist(tsym->typ.basetype,sublist); /* generate a single instance*/
|
||||
con = builddatasublist(sublist);
|
||||
dlappend(dl,&con);
|
||||
break;
|
||||
default: PANIC1("fill: unexpected subclass %d",tvsym->subclass);
|
||||
default: PANIC1("fill: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,41 +143,26 @@ fillarray(Symbol* basetype, Dimset* dimset, int index, Datalist* arraylist)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NOTUSED
|
||||
/* Verify that a user provided fill value does in fact*/
|
||||
/* conform to the structure of a given type or variable*/
|
||||
/* Structure conforms to fill procedures above.*/
|
||||
|
||||
int
|
||||
checkfillvalue(Symbol* tvsym, Datalist* filler)
|
||||
{
|
||||
Datasrc* src = datalist2src(filler);
|
||||
int result;
|
||||
ASSERT(tvsym->objectclass == NC_VAR || tvsym->objectclass == NC_TYPE);
|
||||
if(tvsym->objectclass == NC_VAR) {
|
||||
if(tvsym->typ.dimset.ndims > 0) {
|
||||
result = checkarray(tvsym->typ.basetype,&tvsym->typ.dimset,0,src,tvsym,TOPLEVEL);
|
||||
} else
|
||||
result = checkfill(tvsym->typ.basetype,src,tvsym);
|
||||
} else /* NC_TYPE*/
|
||||
result = checkfill(tvsym,src,tvsym);
|
||||
freedatasrc(src);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
checkfill(Symbol* tvsym, Datasrc* src, Symbol* original)
|
||||
checkfill(Symbol* tsym, Datasrc* src)
|
||||
{
|
||||
int i,iscmpd,result;
|
||||
Constant* con;
|
||||
Symbol* original = tsym;
|
||||
|
||||
result = 1;
|
||||
switch (tvsym->subclass) {
|
||||
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 != tvsym->typ.typecode) result = 0; /* wrong type*/
|
||||
} else if(con->nctype != tsym->typ.typecode) result = 0; /* wrong type*/
|
||||
break;
|
||||
|
||||
case NC_COMPOUND:
|
||||
@ -195,8 +170,8 @@ checkfill(Symbol* tvsym, Datasrc* src, Symbol* original)
|
||||
semerror(srcline(src),"Compound constants must be enclosed in {..}");
|
||||
}
|
||||
srcpush(src);
|
||||
for(i=0;i<listlength(tvsym->subnodes);i++) {
|
||||
Symbol* field = (Symbol*)listget(tvsym->subnodes,i);
|
||||
for(i=0;i<listlength(tsym->subnodes);i++) {
|
||||
Symbol* field = (Symbol*)listget(tsym->subnodes,i);
|
||||
result = checkfill(field,src,original);
|
||||
if(!result) break;
|
||||
}
|
||||
@ -210,7 +185,7 @@ checkfill(Symbol* tvsym, Datasrc* src, Symbol* original)
|
||||
} else {
|
||||
srcpush(src);
|
||||
while(srcmore(src)) {
|
||||
result = checkfill(tvsym->typ.basetype,src,original);
|
||||
result = checkfill(tsym->typ.basetype,src,original);
|
||||
if(!result) break;
|
||||
}
|
||||
srcpop(src);
|
||||
@ -220,14 +195,14 @@ checkfill(Symbol* tvsym, Datasrc* src, Symbol* original)
|
||||
case NC_FIELD:
|
||||
/* Braces are optional */
|
||||
if((iscmpd=issublist(src))) srcpush(src);
|
||||
if(tvsym->typ.dimset.ndims > 0) {
|
||||
result = checkarray(tvsym->typ.basetype,&tvsym->typ.dimset,0,src,original,!TOPLEVEL);
|
||||
if(tsym->typ.dimset.ndims > 0) {
|
||||
result = checkarray(tsym->typ.basetype,&tsym->typ.dimset,0,src,original,!TOPLEVEL);
|
||||
} else
|
||||
result = checkfill(tvsym->typ.basetype,src,original);
|
||||
result = checkfill(tsym->typ.basetype,src,original);
|
||||
if(iscmpd) srcpop(src);
|
||||
break;
|
||||
|
||||
default: PANIC1("checkfillvalue: unexpected subclass %d",tvsym->subclass);
|
||||
default: PANIC1("checkfillvalue: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -274,6 +249,7 @@ checkarray(Symbol* basetype, Dimset* dimset, int index, Datasrc* src, Symbol* or
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
#endif /*NOTUSED*/
|
||||
|
||||
/*
|
||||
* Given primitive netCDF type, return a default fill_value appropriate for
|
||||
|
@ -39,7 +39,6 @@
|
||||
#define ENABLE_JAVA
|
||||
|
||||
#include "netcdf.h"
|
||||
#include "odom.h"
|
||||
#include "data.h"
|
||||
#include "ncgen.h"
|
||||
#include "genlib.h"
|
||||
|
263
ncgen/jdata.c
263
ncgen/jdata.c
@ -1,162 +1,155 @@
|
||||
/*********************************************************************
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
|
||||
#include "includes.h"
|
||||
#include "offsets.h"
|
||||
#include "nciter.h"
|
||||
|
||||
#ifdef ENABLE_JAVA
|
||||
|
||||
extern List* vlenconstants; /* List<Constant*>;*/
|
||||
#include <math.h>
|
||||
|
||||
/* Forward*/
|
||||
static void jdata_primdata(Symbol*, Datasrc*, Bytebuffer*, Datalist*);
|
||||
static int j_uid = 0;
|
||||
|
||||
/**************************************************/
|
||||
/* Code for generating Java language data lists*/
|
||||
/**************************************************/
|
||||
/* Datalist rules: see the rules on the man page */
|
||||
|
||||
void
|
||||
jdata_array(Symbol* vsym,
|
||||
Bytebuffer* databuf,
|
||||
Datasrc* src,
|
||||
Odometer* odom,
|
||||
int index,
|
||||
Datalist* fillsrc)
|
||||
static int
|
||||
j_charconstant(Generator* generator, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
int i;
|
||||
int rank = odom->rank;
|
||||
int firstdim = (index == 0); /* first dimension*/
|
||||
int lastdim = (index == (rank - 1)); /* last dimension*/
|
||||
size_t count;
|
||||
Symbol* basetype = vsym->typ.basetype;
|
||||
int isunlimited = (odom->declsize[index] == 0);
|
||||
int pushed = 0;
|
||||
|
||||
ASSERT(index >= 0 && index < rank);
|
||||
|
||||
count = odom->count[index];
|
||||
|
||||
/* Unpack the nested unlimited (unless first dimension)*/
|
||||
if(!firstdim && isunlimited && issublist(src)) {
|
||||
srcpush(src);
|
||||
pushed = 1;
|
||||
}
|
||||
|
||||
if(lastdim) {
|
||||
for(i=0;i<count;i++) {
|
||||
jdata_basetype(basetype,src,databuf,fillsrc);
|
||||
}
|
||||
} else {
|
||||
/* now walk count elements and generate recursively */
|
||||
for(i=0;i<count;i++) {
|
||||
jdata_array(vsym,databuf,src,odom,index+1,fillsrc);
|
||||
}
|
||||
}
|
||||
|
||||
if(isunlimited && pushed) srcpop(src);
|
||||
|
||||
return;
|
||||
/* Escapes and quoting will be handled in genc_write */
|
||||
/* Just transfer charbuf to codebuf */
|
||||
Bytebuffer* charbuf;
|
||||
va_list ap;
|
||||
vastart(ap,codebuf);
|
||||
charbuf = va_arg(ap, Bytebuffer*);
|
||||
va_end(ap);
|
||||
bbNull(charbuf);
|
||||
bbCatbuf(codebuf,charbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generate an instance of the basetype using datasrc */
|
||||
void
|
||||
jdata_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* codebuf, Datalist* fillsrc)
|
||||
static int
|
||||
j_constant(Generator* generator, Constant* con, Bytebuffer* buf,...)
|
||||
{
|
||||
switch (tsym->subclass) {
|
||||
Bytebuffer* codetmp = bbNew();
|
||||
char* special = NULL;
|
||||
|
||||
case NC_PRIM:
|
||||
if(issublist(datasrc)) {
|
||||
semerror(srcline(datasrc),"Expected primitive found {..}");
|
||||
}
|
||||
bbAppend(codebuf,' ');
|
||||
jdata_primdata(tsym,datasrc,codebuf,fillsrc);
|
||||
break;
|
||||
|
||||
default: PANIC1("jdata_basetype: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
static void
|
||||
jdata_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* databuf, Datalist* fillsrc)
|
||||
{
|
||||
Constant target, *prim;
|
||||
|
||||
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(databuf,' ');
|
||||
jdata_primdata(basetype,src,databuf,NULL);
|
||||
srcpop(src);
|
||||
goto done;
|
||||
}
|
||||
|
||||
target.nctype = basetype->typ.typecode;
|
||||
|
||||
ASSERT(prim->nctype != NC_COMPOUND);
|
||||
|
||||
convert1(prim,&target);
|
||||
/* add hack for java bug in converting floats */
|
||||
if(target.nctype == NC_FLOAT) bbCat(databuf," (float)");
|
||||
bbCat(databuf,jdata_const(&target));
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Result is a pool string or a constant => do not free*/
|
||||
char*
|
||||
jdata_const(Constant* ci)
|
||||
{
|
||||
char tmp[64];
|
||||
char* result = NULL;
|
||||
|
||||
tmp[0] = '\0';
|
||||
|
||||
switch (ci->nctype) {
|
||||
case NC_CHAR:
|
||||
{
|
||||
strcpy(tmp,"'");
|
||||
escapifychar(ci->value.charv,tmp+1,'\'');
|
||||
strcat(tmp,"'");
|
||||
}
|
||||
break;
|
||||
switch (con->nctype) {
|
||||
case NC_BYTE:
|
||||
sprintf(tmp,"%hhd",ci->value.int8v);
|
||||
bbprintf(codetmp,"%hhd",con->value.int8v);
|
||||
break;
|
||||
case NC_SHORT:
|
||||
sprintf(tmp,"%hd",ci->value.int16v);
|
||||
bbprintf(codetmp,"%hd",con->value.int16v);
|
||||
break;
|
||||
case NC_INT:
|
||||
sprintf(tmp,"%d",ci->value.int32v);
|
||||
bbprintf(codetmp,"%d",con->value.int32v);
|
||||
break;
|
||||
case NC_FLOAT:
|
||||
sprintf(tmp,"%.8g",ci->value.floatv);
|
||||
bbprintf(codetmp,"%f",con->value.floatv);
|
||||
break;
|
||||
case NC_DOUBLE:
|
||||
sprintf(tmp,"%.16g",ci->value.doublev);
|
||||
bbprintf(codetmp,"%lf",con->value.doublev);
|
||||
break;
|
||||
|
||||
case NC_STRING:
|
||||
{
|
||||
char* escaped = escapify(ci->value.stringv.stringv,
|
||||
'"',ci->value.stringv.len);
|
||||
result = poolalloc(1+2+strlen(escaped));
|
||||
strcpy(result,"\"");
|
||||
strcat(result,escaped);
|
||||
strcat(result,"\"");
|
||||
goto done;
|
||||
}
|
||||
case NC_UBYTE:
|
||||
bbprintf(codetmp,"%hhu",con->value.uint8v);
|
||||
break;
|
||||
case NC_USHORT:
|
||||
bbprintf(codetmp,"%hu",con->value.uint16v);
|
||||
break;
|
||||
case NC_UINT:
|
||||
bbprintf(codetmp,"%uU",con->value.uint32v);
|
||||
break;
|
||||
case NC_INT64:
|
||||
bbprintf(codetmp,"%lldLL",con->value.int64v);
|
||||
break;
|
||||
case NC_UINT64:
|
||||
bbprintf(codetmp,"%lluLLU",con->value.uint64v);
|
||||
break;
|
||||
case NC_STRING: { /* handle separately */
|
||||
char* escaped = escapify(con->value.stringv.stringv,
|
||||
'"',con->value.stringv.len);
|
||||
special = poolalloc(1+2+strlen(escaped));
|
||||
strcpy(special,"\"");
|
||||
strcat(special,escaped);
|
||||
strcat(special,"\"");
|
||||
} break;
|
||||
|
||||
default: PANIC1("ncstype: bad type code: %d",con->nctype);
|
||||
|
||||
default: PANIC1("ncstype: bad type code: %d",ci->nctype);
|
||||
}
|
||||
result = pooldup(tmp);
|
||||
done:
|
||||
return result; /*except for NC_STRING and NC_OPAQUE*/
|
||||
if(special == NULL)
|
||||
bbCatbuf(buf,codetmp);
|
||||
else
|
||||
bbCat(buf,special);
|
||||
bbFree(codetmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
j_listbegin(Generator* generator, ListClass lc, size_t size, Bytebuffer* codebuf, int* uidp, ...)
|
||||
{
|
||||
if(uidp) *uidp = ++j_uid;
|
||||
switch (lc) {
|
||||
case LISTATTR:
|
||||
case LISTDATA:
|
||||
break;
|
||||
case LISTFIELDARRAY:
|
||||
case LISTVLEN:
|
||||
case LISTCOMPOUND:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
j_list(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* codebuf, ...)
|
||||
{
|
||||
switch (lc) {
|
||||
case LISTATTR:
|
||||
if(count > 0) bbCat(codebuf,", ");
|
||||
break;
|
||||
case LISTDATA:
|
||||
bbCat(codebuf," ");
|
||||
break;
|
||||
case LISTVLEN:
|
||||
case LISTCOMPOUND:
|
||||
case LISTFIELDARRAY:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
j_listend(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
j_vlendecl(Generator* generator, Bytebuffer* codebuf, Symbol* tsym, int uid, size_t count, ...)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
j_vlenstring(Generator* generator, Bytebuffer* vlenmem, int* uidp, size_t* countp,...)
|
||||
{
|
||||
if(uidp) *uidp = ++j_uid;
|
||||
if(countp) *countp = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Define the single static bin data generator */
|
||||
static Generator j_generator_singleton = {
|
||||
NULL,
|
||||
j_charconstant,
|
||||
j_constant,
|
||||
j_listbegin,
|
||||
j_list,
|
||||
j_listend,
|
||||
j_vlendecl,
|
||||
j_vlenstring
|
||||
};
|
||||
Generator* j_generator = &j_generator_singleton;
|
||||
|
||||
#endif /*ENABLE_JAVA*/
|
||||
|
159
ncgen/main.c
159
ncgen/main.c
@ -22,17 +22,24 @@ extern int ncgparse(void);
|
||||
char* progname;
|
||||
char* cdlname;
|
||||
|
||||
int kflag_flag; /* 1 => -k was specified on command line*/
|
||||
int cmode_modifier;
|
||||
/* option flags */
|
||||
int nofill_flag;
|
||||
char* mainname; /* name to use for main function; defaults to "main"*/
|
||||
int c_flag;
|
||||
int binary_flag;
|
||||
int f77_flag;
|
||||
int cml_flag;
|
||||
int java_flag; /* 1=> use netcdf java interface (=>usingclassic)*/
|
||||
int java_flag; /* 1=> use netcdf java interface */
|
||||
int syntax_only;
|
||||
|
||||
/* flags for tracking what output format to use */
|
||||
int k_flag; /* > 0 => -k was specified on command line*/
|
||||
int format_flag; /* _Format attribute value (same range as -k flag) */
|
||||
int enhanced_flag; /* 1 => netcdf-4 constructs appear in the parse */
|
||||
int specials_flag; /* 1=> special attributes are present */
|
||||
int usingclassic;
|
||||
int cmode_modifier;
|
||||
|
||||
size_t nciterbuffersize;
|
||||
|
||||
struct Vlendata* vlendata;
|
||||
@ -40,39 +47,36 @@ struct Vlendata* vlendata;
|
||||
char *netcdf_name; /* command line -o file name */
|
||||
char *datasetname; /* name from the netcdf <name> {} */
|
||||
|
||||
/* Misc. flags*/
|
||||
int usingclassic;
|
||||
int allowspecial; /* are special attributes ok to use */
|
||||
|
||||
extern FILE *ncgin;
|
||||
|
||||
/* Forward */
|
||||
static char* ubasename ( const char* av0 );
|
||||
void usage ( void );
|
||||
int main ( int argc, char** argv );
|
||||
static char* ubasename(char*);
|
||||
void usage( void );
|
||||
int main( int argc, char** argv );
|
||||
|
||||
/* Define tables vs modes for legal -k values*/
|
||||
struct Kvalues legalkinds[NKVALUES] = {
|
||||
{"1", 0},
|
||||
{"classic", 0},
|
||||
{"1", 1},
|
||||
{"classic", 1},
|
||||
|
||||
/* The 64-bit offset kind (2) should only be used if actually needed */
|
||||
{"2", NC_64BIT_OFFSET},
|
||||
{"64-bit-offset", NC_64BIT_OFFSET},
|
||||
{"64-bit offset", NC_64BIT_OFFSET},
|
||||
{"2", 2},
|
||||
{"64-bit-offset", 2},
|
||||
{"64-bit offset", 2},
|
||||
|
||||
/* NetCDF-4 HDF5 format*/
|
||||
{"3", NC_NETCDF4},
|
||||
{"hdf5", NC_NETCDF4},
|
||||
{"netCDF-4", NC_NETCDF4},
|
||||
{"netcdf-4", NC_NETCDF4},
|
||||
{"netcdf4", NC_NETCDF4},
|
||||
{"enhanced", NC_NETCDF4},
|
||||
{"3", 3},
|
||||
{"hdf5", 3},
|
||||
{"netCDF-4", 3},
|
||||
{"netcdf-4", 3},
|
||||
{"netcdf4", 3},
|
||||
{"enhanced", 3},
|
||||
|
||||
/* NetCDF-4 HDF5 format, but using only nc3 data model */
|
||||
{"4", NC_NETCDF4 | NC_CLASSIC_MODEL},
|
||||
{"hdf5-nc3", NC_NETCDF4 | NC_CLASSIC_MODEL},
|
||||
{"netCDF-4 classic model", NC_NETCDF4 | NC_CLASSIC_MODEL},
|
||||
{"enhanced-nc3", NC_NETCDF4 | NC_CLASSIC_MODEL},
|
||||
{"4", 4},
|
||||
{"hdf5-nc3", 4},
|
||||
{"netCDF-4 classic model", 4},
|
||||
{"enhanced-nc3", 4},
|
||||
|
||||
/* null terminate*/
|
||||
{NULL,0}
|
||||
@ -104,9 +108,8 @@ struct Languages {
|
||||
/* result is malloc'd */
|
||||
|
||||
static char *
|
||||
ubasename(const char *av0)
|
||||
ubasename(char *logident)
|
||||
{
|
||||
char *logident = nulldup(av0);
|
||||
char* sep;
|
||||
|
||||
sep = strrchr(logident,'/');
|
||||
@ -151,13 +154,16 @@ main(
|
||||
cml_flag = 0;
|
||||
java_flag = 0;
|
||||
binary_flag = 0;
|
||||
kflag_flag = 0;
|
||||
cmode_modifier = 0;
|
||||
nofill_flag = 0;
|
||||
syntax_only = 0;
|
||||
mainname = "main";
|
||||
nciterbuffersize = 0;
|
||||
|
||||
k_flag = 0;
|
||||
format_flag = 0;
|
||||
enhanced_flag = 0;
|
||||
specials_flag = 0;
|
||||
|
||||
#if _CRAYMPP && 0
|
||||
/* initialize CRAY MPP parallel-I/O library */
|
||||
(void) par_io_init(32, 32);
|
||||
@ -234,7 +240,7 @@ main(
|
||||
(void)strcpy(kind_name, optarg);
|
||||
for(kvalue=legalkinds;kvalue->name;kvalue++) {
|
||||
if(strcmp(kind_name,kvalue->name) == 0) {
|
||||
cmode_modifier = kvalue->mode;
|
||||
k_flag = kvalue->k_flag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -242,7 +248,6 @@ main(
|
||||
derror("Invalid format: %s",kind_name);
|
||||
return 2;
|
||||
}
|
||||
kflag_flag = 1;
|
||||
}
|
||||
break;
|
||||
case 'M': /* Determine the name for the main function */
|
||||
@ -269,7 +274,7 @@ main(
|
||||
|
||||
if(languages == 0) {
|
||||
binary_flag = 1; /* default */
|
||||
if(kflag_flag == 0)
|
||||
if(k_flag == 0)
|
||||
syntax_only = 1;
|
||||
}
|
||||
|
||||
@ -329,30 +334,6 @@ main(
|
||||
if(strlen(cdlname) > NC_MAX_NAME) cdlname[NC_MAX_NAME] = '\0';
|
||||
}
|
||||
|
||||
/* Initially set up the cmode value and related items*/
|
||||
if(kflag_flag == 0) cmode_modifier = DFALTCMODE;
|
||||
|
||||
usingclassic = 0;
|
||||
allowspecial = 0;
|
||||
|
||||
/* Do first pass on flags */
|
||||
if((cmode_modifier & NC_NETCDF4) != 0) {
|
||||
allowspecial = 1;
|
||||
if((cmode_modifier & NC_CLASSIC_MODEL)) {
|
||||
usingclassic = 1;
|
||||
} else {
|
||||
usingclassic = 0;
|
||||
}
|
||||
} else {
|
||||
usingclassic = 1;
|
||||
}
|
||||
|
||||
/* F77 || STD java => classic */
|
||||
if(f77_flag || java_flag) {
|
||||
usingclassic=1;
|
||||
cmode_modifier &= ~(NC_NETCDF4);
|
||||
}
|
||||
|
||||
/* Standard Unidata java interface => usingclassic */
|
||||
|
||||
parse_init();
|
||||
@ -360,31 +341,55 @@ main(
|
||||
if(debug >= 2) {ncgdebug=1;}
|
||||
if(ncgparse() != 0) return 1;
|
||||
|
||||
/* Recompute flags */
|
||||
if((cmode_modifier & NC_NETCDF4) != 0) {
|
||||
allowspecial = 1;
|
||||
if((cmode_modifier & NC_CLASSIC_MODEL)) {
|
||||
usingclassic = 1;
|
||||
} else {
|
||||
usingclassic = 0;
|
||||
}
|
||||
} else {
|
||||
usingclassic = 1;
|
||||
}
|
||||
|
||||
/* Complain if still usingclassic =1 && a cdf4
|
||||
construct was used
|
||||
*/
|
||||
if(usingclassic && getmarkcdf4() != NULL) {
|
||||
verror(getmarkcdf4());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compute the k_flag (1st pass) using rules in the man page (ncgen.1).*/
|
||||
|
||||
#ifndef USE_NETCDF4
|
||||
allowspecial = 0;
|
||||
if(enhanced_flag) {
|
||||
derror("CDL input is enhanced mode, but --disable-netcdf4 was specified during build");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(java_flag || f77_flag) {
|
||||
k_flag = 1;
|
||||
if(enhanced_flag) {
|
||||
derror("Java or Fortran requires classic model CDL input");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(k_flag == 0)
|
||||
k_flag = format_flag;
|
||||
|
||||
if(enhanced_flag && k_flag == 0)
|
||||
k_flag = 3;
|
||||
|
||||
if(enhanced_flag && k_flag != 3) {
|
||||
derror("-k or _Format conflicts with enhanced CDL input");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(specials_flag && k_flag == 0)
|
||||
#ifdef USE_NETCDF4
|
||||
k_flag = 4;
|
||||
#else
|
||||
k_flag = 1;
|
||||
#endif
|
||||
|
||||
if(k_flag == 0)
|
||||
k_flag = 1;
|
||||
|
||||
usingclassic = (k_flag <= 2?1:0);
|
||||
|
||||
/* compute cmode_modifier */
|
||||
switch (k_flag) {
|
||||
case 1: cmode_modifier = 0; break;
|
||||
case 2: cmode_modifier = NC_64BIT_OFFSET; break;
|
||||
case 3: cmode_modifier = NC_NETCDF4; break;
|
||||
case 4: cmode_modifier = NC_NETCDF4 | NC_CLASSIC_MODEL; break;
|
||||
default: ASSERT(0); /* cannot happen */
|
||||
}
|
||||
|
||||
processsemantics();
|
||||
if(!syntax_only)
|
||||
define_netcdf();
|
||||
|
128
ncgen/ncgen.1
128
ncgen/ncgen.1
@ -77,8 +77,7 @@ The possible arguments are as follows.
|
||||
.IP "'4', 'hdf5-nc3', 'netCDF-4 classic model', 'enhanced-nc3' => netcdf-4 file format, netcdf-3 type model."
|
||||
.RE
|
||||
.RE
|
||||
If no -k is specified then it defaults to -k1 (i.e. classic).
|
||||
Note also that -v is accepted to mean the same thing as
|
||||
Note that -v is accepted to mean the same thing as
|
||||
-k for backward compatibility, but -k is preferred, to match
|
||||
the corresponding ncdump option.
|
||||
.IP "\fB-x\fP"
|
||||
@ -101,6 +100,43 @@ The currently supported languages have the following flags.
|
||||
only the classic model is supported.
|
||||
.RE
|
||||
.RE
|
||||
.SH Choosing the output format
|
||||
The choice of output format is determined by three flags.
|
||||
.IP "\fB-k flag.\fP"
|
||||
.IP "\fB_Format attribute (see below).\fP"
|
||||
.IP "\fBOccurrence of netcdf-4 constructs in the input CDL.\fP"
|
||||
The term "netCDF-4 constructs" means
|
||||
construct from the enhanced data model,
|
||||
not just special performance-related attributes such as
|
||||
_ChunkSizes, _DeflateLevel, _Endianness, etc.
|
||||
.LP
|
||||
The rules are as follows, in order of application.
|
||||
.IP "\fB1.\fP"
|
||||
If either Fortran or Java output is specified,
|
||||
then -k flag value of 1 (classic model) will be used.
|
||||
Conflicts with the use of enhanced constructs
|
||||
in the CDL will report an error.
|
||||
.IP "\fB2.\fP"
|
||||
If both the -k flag and _Format attribute are specified,
|
||||
the _Format flag will be ignored.
|
||||
If no -k flag is specified, and a _Format attribute value
|
||||
is specified, then the -k flag value
|
||||
will be set to that of the _Format attribute.
|
||||
Otherwise the -k flag is undefined.
|
||||
.IP "\fB3.\fP"
|
||||
If the -k option is defined and is consistent with the CDL,
|
||||
ncgen will output a file in the requested form,
|
||||
else an error will be reported.
|
||||
.IP "\fB4.\fP"
|
||||
If the -k flag is undefined,
|
||||
and if there are netCDF-4 constructs in the CDL,
|
||||
a -k flag value of 3 (enhanced model) will be used.
|
||||
.IP "\fB5.\fP"
|
||||
If special performance-related attributes are specified in the CDL,
|
||||
a -k flag value of 4 (netCDF-4 classic model) will be used.
|
||||
.IP "\fB6.\fP"
|
||||
Otherwise ncgen will set the -k flag to 1 (classic model).
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
.LP
|
||||
Check the syntax of the CDL file `\fBfoo.cdl\fP':
|
||||
@ -688,60 +724,50 @@ and we have three strings of length 1, 3, 5.
|
||||
How do we assign the characters in the strings to the
|
||||
twenty elements?
|
||||
.LP
|
||||
The basic rule is "greedy" plus "right dimension rules".
|
||||
By this we mean the following.
|
||||
This is challenging because it is desirable to mimic
|
||||
the original ncgen (ncgen3).
|
||||
The core algorithm is notionally as follows.
|
||||
.IP 1. 3
|
||||
Use the size of the rightmost dimension (d4=4)
|
||||
and modify the constant list so that every string is less
|
||||
than or equal to this dimension size. Longer strings are decomposed.
|
||||
For our example, we get this.
|
||||
.in +5
|
||||
datalist: var= "1", "two", "thre", "e";
|
||||
.in -5
|
||||
|
||||
Assume we have a set of dimensions D1..Dn,
|
||||
where D1 may optionally be an Unlimited dimension.
|
||||
It is assumed that the sizes of the Di are all known
|
||||
(including unlimited dimensions).
|
||||
.IP 2. 3
|
||||
Pad any short strings to the length of the right dimension.
|
||||
This produces the following.
|
||||
.in +5
|
||||
datalist: var= "1\\0\\0\\0", "two\\0", "thre", "e\\0\\0\\0";
|
||||
.in -5
|
||||
|
||||
Given a sequence of string or character constants
|
||||
C1..Cm, our goal is to construct a single string
|
||||
whose length is the cross product of D1 thru Dn.
|
||||
Note that for purposes of this algorithm, character constants
|
||||
are treated as strings of size 1.
|
||||
.IP 3. 3
|
||||
Move the the next to the rightmost dimension (d5 in this case)
|
||||
and add fill values as needed, producing this.
|
||||
.in +5
|
||||
datalist: var= "1\\0\\0\\0", "two\\0", "thre", "e\\0\\0\\0", "\\0\\0\\0\\0";
|
||||
.in -5
|
||||
|
||||
4. Repeat step 3 for successively more left dimensions until the
|
||||
first dimension is reached. If the first dimension is UNLIMITED,
|
||||
and has not had any previous value assigned to it, then
|
||||
do not pad, but instead use the length at that point
|
||||
as the unlimited length. In all other cases, pad to the
|
||||
specified length.
|
||||
Construct Dx = cross product of D1 thru D(n-1).
|
||||
.IP 4. 3
|
||||
For each constant Ci, add fill characters as needed
|
||||
so that its length is a multiple of Dn.
|
||||
.IP 5. 3
|
||||
Concatenate the modified C1..Cm to produce string S.
|
||||
.IP 6. 3
|
||||
Add fill characters to S to make its length be a multiple of Dn.
|
||||
.IP 8. 3
|
||||
If S is longer than the Dx * Dn, then truncate
|
||||
and generate a warning.
|
||||
.LP
|
||||
Note that the term "greedy" is used because the above algorithm
|
||||
causes the strings to be assigned to the "front" of the variable
|
||||
and fill values to the end.
|
||||
.LP
|
||||
There are several additional edge cases that must be dealt with.
|
||||
There are three other cases of note.
|
||||
.IP 1. 3
|
||||
Suppose we have only an unlimited dimension such as this case.
|
||||
.in +5
|
||||
.nf
|
||||
variables: char var(u);
|
||||
datalist: var="1", "two", "three";
|
||||
.fi
|
||||
.in -5
|
||||
In this case, we treat it like it was defined as this.
|
||||
.in +5
|
||||
.nf
|
||||
variables: char var(u,d1);
|
||||
datalist: var="1","t","w","o","t","h","r","e","e";
|
||||
.fi
|
||||
.in -5
|
||||
This means that u will have the length of nine.
|
||||
If there is only a single, unlimited dimension,
|
||||
then all of the constants are concatenated
|
||||
and fill characers are added to the
|
||||
end of the resulting string to make its
|
||||
length be that of the unlimited dimension.
|
||||
If the length is larger than
|
||||
the unlimited dimension, then it is truncated
|
||||
with a warning.
|
||||
.IP 2. 3
|
||||
For the case of character typed vlen, "char(*) vlen_t" for example.
|
||||
we simply concatenate all the constants with no filling at all.
|
||||
.IP 3. 3
|
||||
For the case of a character typed attribute,
|
||||
we simply concatenate all the constants.
|
||||
.LP
|
||||
In netcdf-4, dimensions other than the first can be unlimited.
|
||||
Of course by the rules above, the interior unlimited instances
|
||||
must be delimited by {...}. For example.
|
||||
@ -751,14 +777,12 @@ variables: char var(u,u2);
|
||||
datalist: var={"1", "two"}, {"three"};
|
||||
.fi
|
||||
.in -5
|
||||
|
||||
In this case u will have the effective length of two.
|
||||
Within each instance of u2, the rules above will apply, leading
|
||||
to this.
|
||||
.in +5
|
||||
datalist: var={"1","t","w","o"}, {"t","h","r","e","e"};
|
||||
.in -5
|
||||
|
||||
The effective size of u2 will be the max of the two instance lengths
|
||||
(five in this case)
|
||||
and the shorter will be padded to produce this.
|
||||
|
@ -82,16 +82,16 @@ various C global variables
|
||||
|
||||
struct Kvalues {
|
||||
char* name;
|
||||
int mode;
|
||||
int k_flag;
|
||||
};
|
||||
|
||||
#define NKVALUES 16
|
||||
extern struct Kvalues legalkinds[NKVALUES];
|
||||
|
||||
/* Note: non-variable specials (e.g. _Format) are not included in this struct*/
|
||||
/* Note: some non-var specials (i.e. _Format) are not included in this struct*/
|
||||
typedef struct Specialdata {
|
||||
int flags;
|
||||
Datalist* _Fillvalue;
|
||||
Datalist* _Fillvalue; /* This is a per-type */
|
||||
int _Storage; /* NC_CHUNKED | NC_CONTIGUOUS*/
|
||||
size_t* _ChunkSizes; /* NULL => defaults*/
|
||||
int nchunks; /* |_Chunksize| ; 0 => not specified*/
|
||||
@ -111,7 +111,7 @@ typedef struct Dimset {
|
||||
|
||||
typedef struct Diminfo {
|
||||
int isconstant; /* separate constant from named dimension*/
|
||||
size_t unlimitedsize; /* if unlimited */
|
||||
int isunlimited;
|
||||
size_t declsize; /* 0 => unlimited/unspecified*/
|
||||
} Diminfo;
|
||||
|
||||
@ -130,6 +130,8 @@ typedef struct Typeinfo {
|
||||
size_t size; /* for opaque, compound, etc.*/
|
||||
size_t nelems; /* size in terms of # of datalist constants
|
||||
it takes to represent it */
|
||||
Datalist* _Fillvalue; /* per-type cached fillvalue
|
||||
(overridden by var fillvalue) */
|
||||
} Typeinfo;
|
||||
|
||||
typedef struct Varinfo {
|
||||
@ -140,7 +142,6 @@ typedef struct Varinfo {
|
||||
|
||||
typedef struct Groupinfo {
|
||||
int is_root;
|
||||
struct Symbol* unlimiteddim;
|
||||
} Groupinfo;
|
||||
|
||||
typedef struct Symbol { /* symbol table entry*/
|
||||
|
@ -14,7 +14,7 @@
|
||||
8859 characters above 128 will be handles as n-byte utf8 and so
|
||||
will probably not lex correctly.
|
||||
Solution: assume utf8 and note in the documentation that
|
||||
ISO8859 is specifically unsupported (except as noted below).
|
||||
ISO8859 is specifically unsupported.
|
||||
2. The netcdf function NC_check_name in string.c must be modified to
|
||||
conform to the use of UTF8.
|
||||
3. We actually have three tests for UTF8 of increasing correctness
|
||||
@ -24,7 +24,8 @@
|
||||
http://www.w3.org/2005/03/23-lex-U
|
||||
We include lexical definitions for all three, but use the second version.
|
||||
4. Single character constants enclosed in '...' cannot be
|
||||
utf-8, so we assume they are the one case where ISO-8859-1 is allowed.
|
||||
utf-8, so we assume they are the one case where US-Ascii (7-bit) is used.
|
||||
We could use ISO-8859-1, but that conflicts with UTF-8 above value 127.
|
||||
*/
|
||||
|
||||
/* lex specification for tokens for ncgen */
|
||||
@ -40,7 +41,7 @@
|
||||
char errstr[100]; /* for short error messages */
|
||||
|
||||
int lineno; /* line number for error messages */
|
||||
char* lextext; /* name or string with escapes removed */
|
||||
Bytebuffer* lextext; /* name or string with escapes removed */
|
||||
|
||||
#define YY_BREAK /* defining as nothing eliminates unreachable
|
||||
statement warnings from flex output,
|
||||
@ -159,7 +160,7 @@ FLTNUMBER [+-]?[0-9]*\.[0-9]*{exp}?[Ff]|[+-]?[0-9]*{exp}[Ff]
|
||||
|
||||
SPECIAL "_FillValue"|"_Format"|"_Storage"|"_ChunkSizes"|"_Fletcher32"|"_DeflateLevel"|"_Shuffle"|"_Endianness"|"_NoFill"
|
||||
|
||||
ISO8859CHAR [\x01-\xFF]
|
||||
USASCII [\x01-\x7F]
|
||||
|
||||
%%
|
||||
[ \r\t\f]+ { /* whitespace */
|
||||
@ -179,10 +180,10 @@ yyerror("string too long, truncated\n");
|
||||
yytext[MAXTRST-1] = '\0';
|
||||
}
|
||||
*/
|
||||
lextext = emalloc(1+4*yyleng); /* should be max
|
||||
needed */
|
||||
/* Assumes expand escapes also does normalization */
|
||||
bbClear(lextext);
|
||||
expand_escapes(lextext,(char *)yytext,yyleng);
|
||||
bbNull(lextext);
|
||||
return lexdebug(TERMSTRING);
|
||||
}
|
||||
|
||||
@ -191,12 +192,11 @@ yytext[MAXTRST-1] = '\0';
|
||||
int len = yyleng - 2;
|
||||
int padlen = len;
|
||||
if((padlen % 2) == 1) padlen++;
|
||||
lextext = emalloc(1+padlen);
|
||||
strncpy(lextext,p,len+1); /*include null */
|
||||
lextext[len] = '0'; /* assume padding */
|
||||
lextext[padlen] = '\0'; /* make sure null terminated */
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,p,len);
|
||||
bbNull(lextext);
|
||||
/* convert all chars to lower case */
|
||||
for(p=lextext;*p;p++) *p = tolower(*p);
|
||||
for(p=bbContents(lextext);*p;p++) *p = tolower(*p);
|
||||
return lexdebug(OPAQUESTRING);
|
||||
}
|
||||
|
||||
@ -257,19 +257,20 @@ NaNf|nanf { /* missing value (pre-2.4 backward compatibility) */
|
||||
}
|
||||
|
||||
{PATH} {
|
||||
lextext = emalloc(1+4*yyleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
yylval.sym = makepath(lextext);
|
||||
free(lextext);
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
yylval.sym = makepath(bbContents(lextext));
|
||||
return lexdebug(PATH);
|
||||
}
|
||||
|
||||
|
||||
{SPECIAL} {struct Specialtoken* st;
|
||||
lextext = emalloc(1+4*yyleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
for(st=specials;st->name;st++) {
|
||||
if(strcmp(lextext,st->name)==0) {return lexdebug(st->token);}
|
||||
if(strcmp(bbContents(lextext),st->name)==0) {return lexdebug(st->token);}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -277,24 +278,27 @@ NaNf|nanf { /* missing value (pre-2.4 backward compatibility) */
|
||||
<TEXT>{DATASETID} {
|
||||
int c;
|
||||
char* p; char* q;
|
||||
lextext = emalloc(1+4*yyleng); /* should be max needed */
|
||||
/* copy the trimmed name */
|
||||
strncpy(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
p = lextext;
|
||||
q = lextext;
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
p = bbContents(lextext);
|
||||
q = p;
|
||||
while((c=*p++)) {if(c > ' ') *q++ = c;}
|
||||
*q = '\0';
|
||||
datasetname = lextext;
|
||||
datasetname = bbDup(lextext);
|
||||
BEGIN(INITIAL);
|
||||
return lexdebug(DATASETID);
|
||||
}
|
||||
|
||||
{ID} {
|
||||
lextext = emalloc(1+4*yyleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
deescapify(lextext);
|
||||
if (STREQ((char *)lextext, FILL_STRING)) return lexdebug(FILLMARKER);
|
||||
yylval.sym = install(lextext);
|
||||
{ID} { char* id;
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)yytext,yyleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
id = bbContents(lextext);
|
||||
deescapify(id);
|
||||
if (STREQ(id, FILL_STRING)) return lexdebug(FILLMARKER);
|
||||
yylval.sym = install(id);
|
||||
return lexdebug(IDENT);
|
||||
}
|
||||
|
||||
@ -559,7 +563,7 @@ int
|
||||
lex_init(void)
|
||||
{
|
||||
lineno = 1;
|
||||
lextext = NULL;
|
||||
lextext = bbNew();
|
||||
if(0) unput(0); /* keep -Wall quiet */
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ char* primtypenames[PRIMNO] = {
|
||||
|
||||
/*Defined in ncgen.l*/
|
||||
extern int lineno; /* line number for error messages */
|
||||
extern char* lextext; /* name or string with escapes removed */
|
||||
extern Bytebuffer* lextext; /* name or string with escapes removed */
|
||||
|
||||
extern double double_val; /* last double value read */
|
||||
extern float float_val; /* last float value read */
|
||||
@ -101,8 +101,6 @@ static Constant makeconstdata(nc_type);
|
||||
static Constant evaluate(Symbol* fcn, Datalist* arglist);
|
||||
static Constant makeenumconst(Symbol*);
|
||||
static void addtogroup(Symbol*);
|
||||
static Symbol* getunlimiteddim(void);
|
||||
static void setunlimiteddim(Symbol* udim);
|
||||
static Symbol* currentgroup(void);
|
||||
static Symbol* createrootgroup(void);
|
||||
static Symbol* creategroup(Symbol*);
|
||||
@ -440,6 +438,9 @@ dimdecl:
|
||||
dimd '=' UINT_CONST
|
||||
{
|
||||
$1->dim.declsize = (size_t)uint32_val;
|
||||
#ifdef DEBUG1
|
||||
fprintf(stderr,"dimension: %s = %lu\n",$1->name,(unsigned long)$1->dim.declsize);
|
||||
#endif
|
||||
}
|
||||
| dimd '=' INT_CONST
|
||||
{
|
||||
@ -448,6 +449,9 @@ dimdecl:
|
||||
YYABORT;
|
||||
}
|
||||
$1->dim.declsize = (size_t)int32_val;
|
||||
#ifdef DEBUG1
|
||||
fprintf(stderr,"dimension: %s = %lu\n",$1->name,(unsigned long)$1->dim.declsize);
|
||||
#endif
|
||||
}
|
||||
| dimd '=' DOUBLE_CONST
|
||||
{ /* for rare case where 2^31 < dimsize < 2^32 */
|
||||
@ -458,16 +462,17 @@ dimdecl:
|
||||
if (double_val - (size_t) double_val > 0)
|
||||
yyerror("dimension length must be an integer");
|
||||
$1->dim.declsize = (size_t)double_val;
|
||||
#ifdef DEBUG1
|
||||
fprintf(stderr,"dimension: %s = %lu\n",$1->name,(unsigned long)$1->dim.declsize);
|
||||
#endif
|
||||
}
|
||||
| dimd '=' NC_UNLIMITED_K
|
||||
{
|
||||
if(usingclassic) {
|
||||
/* check for multiple UNLIMITED decls*/
|
||||
if(getunlimiteddim() != NULL)
|
||||
markcdf4("Type specification");
|
||||
setunlimiteddim($1);
|
||||
}
|
||||
$1->dim.declsize = NC_UNLIMITED;
|
||||
$1->dim.declsize = NC_UNLIMITED;
|
||||
$1->dim.isunlimited = 1;
|
||||
#ifdef DEBUG1
|
||||
fprintf(stderr,"dimension: %s = UNLIMITED\n",$1->name);
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
@ -782,7 +787,7 @@ datalist:
|
||||
;
|
||||
|
||||
datalist0:
|
||||
/*empty*/ {$$ = builddatalist(0);}
|
||||
/*empty*/ {$$ = NULL;}
|
||||
;
|
||||
|
||||
datalist1: /* Must have at least 1 element */
|
||||
@ -954,18 +959,6 @@ install(const char *sname)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setunlimiteddim(Symbol* udim)
|
||||
{
|
||||
rootgroup->grp.unlimiteddim = udim;
|
||||
}
|
||||
|
||||
static Symbol*
|
||||
getunlimiteddim(void)
|
||||
{
|
||||
return rootgroup->grp.unlimiteddim;
|
||||
}
|
||||
|
||||
static Symbol*
|
||||
currentgroup(void)
|
||||
{
|
||||
@ -981,7 +974,6 @@ createrootgroup(void)
|
||||
gsym->container = NULL;
|
||||
gsym->subnodes = listnew();
|
||||
gsym->grp.is_root = 1;
|
||||
gsym->grp.unlimiteddim = NULL;
|
||||
gsym->prefix = listnew();
|
||||
listpush(grpdefs,(elem_t)gsym);
|
||||
rootgroup = gsym;
|
||||
@ -1024,9 +1016,10 @@ makeconstdata(nc_type nctype)
|
||||
break;
|
||||
case NC_STRING: { /* convert to a set of chars*/
|
||||
int len;
|
||||
len = strlen(lextext);
|
||||
len = bbLength(lextext);
|
||||
con.value.stringv.len = len;
|
||||
con.value.stringv.stringv = nulldup(lextext);
|
||||
con.value.stringv.stringv = bbDup(lextext);
|
||||
bbClear(lextext);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1041,14 +1034,14 @@ makeconstdata(nc_type nctype)
|
||||
case NC_OPAQUE: {
|
||||
char* s;
|
||||
int len,padlen;
|
||||
len = strlen(lextext);
|
||||
len = bbLength(lextext);
|
||||
padlen = len;
|
||||
if(padlen < 16) padlen = 16;
|
||||
if((padlen % 2) == 1) padlen++;
|
||||
s = (char*)emalloc(padlen+1);
|
||||
memset((void*)s,'0',padlen);
|
||||
s[padlen]='\0';
|
||||
strncpy(s,lextext,len);
|
||||
strncpy(s,bbContents(lextext),len);
|
||||
con.value.opaquev.stringv = s;
|
||||
con.value.opaquev.len = padlen;
|
||||
} break;
|
||||
@ -1070,9 +1063,7 @@ static Constant
|
||||
makeenumconst(Symbol* econst)
|
||||
{
|
||||
Constant con;
|
||||
if(usingclassic) {
|
||||
markcdf4("Enum type");
|
||||
}
|
||||
markcdf4("Enum type");
|
||||
consttype = NC_ENUM;
|
||||
con.nctype = NC_ECONST;
|
||||
con.lineno = lineno;
|
||||
@ -1185,6 +1176,8 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
char* sdata = NULL;
|
||||
int idata = -1;
|
||||
|
||||
specials_flag = 1;
|
||||
|
||||
if(isconst) {
|
||||
con = (Constant*)data;
|
||||
list = builddatalist(1);
|
||||
@ -1236,35 +1229,17 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
if(tag == _FORMAT_FLAG) {
|
||||
struct Kvalues* kvalue;
|
||||
int found;
|
||||
int modifier;
|
||||
found = 0;
|
||||
modifier = 0;
|
||||
if(kflag_flag != 0) goto done;
|
||||
/* Only use this tag if kflag is not set */
|
||||
/* Use the table in main.c */
|
||||
for(kvalue=legalkinds;kvalue->name;kvalue++) {
|
||||
if(strcmp(sdata,kvalue->name) == 0) {
|
||||
modifier = kvalue->mode;
|
||||
format_flag = kvalue->k_flag;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
derror("_Format: illegal value: %s",sdata);
|
||||
else {
|
||||
/* Recompute mode flag */
|
||||
cmode_modifier &= ~(NC_NETCDF4 | NC_CLASSIC_MODEL | NC_64BIT_OFFSET);
|
||||
cmode_modifier |= modifier;
|
||||
if((cmode_modifier & NC_NETCDF4)) {
|
||||
allowspecial = 1;
|
||||
if((cmode_modifier & NC_CLASSIC_MODEL)) {
|
||||
usingclassic = 1;
|
||||
} else {
|
||||
usingclassic = 0;
|
||||
}
|
||||
} else
|
||||
usingclassic = 1;
|
||||
}
|
||||
} else if(tag == _FILLVALUE_FLAG) {
|
||||
special->_Fillvalue = list;
|
||||
/* fillvalue must be a single value*/
|
||||
@ -1338,7 +1313,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
|
||||
} break;
|
||||
default: PANIC1("makespecial: illegal token: %d",tag);
|
||||
}
|
||||
done:
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
@ -1375,12 +1350,14 @@ makeattribute(Symbol* asym,
|
||||
static int
|
||||
containsfills(Datalist* list)
|
||||
{
|
||||
int i;
|
||||
Constant* con = list->data;
|
||||
for(i=0;i<list->length;i++,con++) {
|
||||
if(con->nctype == NC_COMPOUND) {
|
||||
if(containsfills(con->value.compoundv)) return 1;
|
||||
} else if(con->nctype == NC_FILLVALUE) return 1;
|
||||
if(list != NULL) {
|
||||
int i;
|
||||
Constant* con = list->data;
|
||||
for(i=0;i<list->length;i++,con++) {
|
||||
if(con->nctype == NC_COMPOUND) {
|
||||
if(containsfills(con->value.compoundv)) return 1;
|
||||
} else if(con->nctype == NC_FILLVALUE) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
1286
ncgen/ncgentab.c
1286
ncgen/ncgentab.c
File diff suppressed because it is too large
Load Diff
122
ncgen/ncgenyy.c
122
ncgen/ncgenyy.c
@ -1211,7 +1211,7 @@ char *ncgtext;
|
||||
8859 characters above 128 will be handles as n-byte utf8 and so
|
||||
will probably not lex correctly.
|
||||
Solution: assume utf8 and note in the documentation that
|
||||
ISO8859 is specifically unsupported (except as noted below).
|
||||
ISO8859 is specifically unsupported.
|
||||
2. The netcdf function NC_check_name in string.c must be modified to
|
||||
conform to the use of UTF8.
|
||||
3. We actually have three tests for UTF8 of increasing correctness
|
||||
@ -1221,7 +1221,8 @@ char *ncgtext;
|
||||
http://www.w3.org/2005/03/23-lex-U
|
||||
We include lexical definitions for all three, but use the second version.
|
||||
4. Single character constants enclosed in '...' cannot be
|
||||
utf-8, so we assume they are the one case where ISO-8859-1 is allowed.
|
||||
utf-8, so we assume they are the one case where US-Ascii (7-bit) is used.
|
||||
We could use ISO-8859-1, but that conflicts with UTF-8 above value 127.
|
||||
*/
|
||||
|
||||
/* lex specification for tokens for ncgen */
|
||||
@ -1237,7 +1238,7 @@ char *ncgtext;
|
||||
char errstr[100]; /* for short error messages */
|
||||
|
||||
int lineno; /* line number for error messages */
|
||||
char* lextext; /* name or string with escapes removed */
|
||||
Bytebuffer* lextext; /* name or string with escapes removed */
|
||||
|
||||
#define YY_BREAK /* defining as nothing eliminates unreachable
|
||||
statement warnings from flex output,
|
||||
@ -1320,7 +1321,7 @@ ID ([A-Za-z_]|{UTF8})([A-Z.@#\[\]a-z_0-9+-]|{UTF8})*
|
||||
/* Note: this definition of string will work for utf8 as well,
|
||||
although it is a very relaxed definition
|
||||
*/
|
||||
#line 1324 "lex.ncg.c"
|
||||
#line 1325 "lex.ncg.c"
|
||||
|
||||
#define INITIAL 0
|
||||
#define ST_C_COMMENT 1
|
||||
@ -1411,7 +1412,7 @@ static int input (void );
|
||||
/* This used to be an fputs(), but since the string might contain NUL's,
|
||||
* we now use fwrite().
|
||||
*/
|
||||
#define ECHO fwrite( ncgtext, ncgleng, 1, ncgout )
|
||||
#define ECHO do { if (fwrite( ncgtext, ncgleng, 1, ncgout )) {} } while (0)
|
||||
#endif
|
||||
|
||||
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
|
||||
@ -1422,7 +1423,7 @@ static int input (void );
|
||||
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
|
||||
{ \
|
||||
int c = '*'; \
|
||||
int n; \
|
||||
unsigned n; \
|
||||
for ( n = 0; n < max_size && \
|
||||
(c = getc( ncgin )) != EOF && c != '\n'; ++n ) \
|
||||
buf[n] = (char) c; \
|
||||
@ -1504,9 +1505,9 @@ YY_DECL
|
||||
register char *yy_cp, *yy_bp;
|
||||
register int yy_act;
|
||||
|
||||
#line 164 "ncgen.l"
|
||||
#line 165 "ncgen.l"
|
||||
|
||||
#line 1510 "lex.ncg.c"
|
||||
#line 1511 "lex.ncg.c"
|
||||
|
||||
if ( !(yy_init) )
|
||||
{
|
||||
@ -1591,14 +1592,14 @@ do_action: /* This label is used only to access EOF actions. */
|
||||
|
||||
case 1:
|
||||
YY_RULE_SETUP
|
||||
#line 165 "ncgen.l"
|
||||
#line 166 "ncgen.l"
|
||||
{ /* whitespace */
|
||||
break;
|
||||
}
|
||||
YY_BREAK
|
||||
case 2:
|
||||
YY_RULE_SETUP
|
||||
#line 169 "ncgen.l"
|
||||
#line 170 "ncgen.l"
|
||||
{ /* comment */
|
||||
break;
|
||||
}
|
||||
@ -1606,7 +1607,7 @@ YY_RULE_SETUP
|
||||
case 3:
|
||||
/* rule 3 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 173 "ncgen.l"
|
||||
#line 174 "ncgen.l"
|
||||
{
|
||||
/* In netcdf4, this will be used in a variety
|
||||
of places, so only remove escapes */
|
||||
@ -1616,27 +1617,26 @@ yyerror("string too long, truncated\n");
|
||||
ncgtext[MAXTRST-1] = '\0';
|
||||
}
|
||||
*/
|
||||
lextext = emalloc(1+4*ncgleng); /* should be max
|
||||
needed */
|
||||
/* Assumes expand escapes also does normalization */
|
||||
bbClear(lextext);
|
||||
expand_escapes(lextext,(char *)ncgtext,ncgleng);
|
||||
bbNull(lextext);
|
||||
return lexdebug(TERMSTRING);
|
||||
}
|
||||
YY_BREAK
|
||||
case 4:
|
||||
YY_RULE_SETUP
|
||||
#line 189 "ncgen.l"
|
||||
#line 190 "ncgen.l"
|
||||
{ /* drop leading 0x; pad to even number of chars */
|
||||
char* p = ncgtext+2;
|
||||
int len = ncgleng - 2;
|
||||
int padlen = len;
|
||||
if((padlen % 2) == 1) padlen++;
|
||||
lextext = emalloc(1+padlen);
|
||||
strncpy(lextext,p,len+1); /*include null */
|
||||
lextext[len] = '0'; /* assume padding */
|
||||
lextext[padlen] = '\0'; /* make sure null terminated */
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,p,len);
|
||||
bbNull(lextext);
|
||||
/* convert all chars to lower case */
|
||||
for(p=lextext;*p;p++) *p = tolower(*p);
|
||||
for(p=bbContents(lextext);*p;p++) *p = tolower(*p);
|
||||
return lexdebug(OPAQUESTRING);
|
||||
}
|
||||
YY_BREAK
|
||||
@ -1794,10 +1794,10 @@ case 30:
|
||||
YY_RULE_SETUP
|
||||
#line 259 "ncgen.l"
|
||||
{
|
||||
lextext = emalloc(1+4*ncgleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
yylval.sym = makepath(lextext);
|
||||
free(lextext);
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
yylval.sym = makepath(bbContents(lextext));
|
||||
return lexdebug(PATH);
|
||||
}
|
||||
YY_BREAK
|
||||
@ -1805,10 +1805,11 @@ case 31:
|
||||
YY_RULE_SETUP
|
||||
#line 268 "ncgen.l"
|
||||
{struct Specialtoken* st;
|
||||
lextext = emalloc(1+4*ncgleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
for(st=specials;st->name;st++) {
|
||||
if(strcmp(lextext,st->name)==0) {return lexdebug(st->token);}
|
||||
if(strcmp(bbContents(lextext),st->name)==0) {return lexdebug(st->token);}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1816,37 +1817,40 @@ YY_RULE_SETUP
|
||||
case 32:
|
||||
/* rule 32 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 277 "ncgen.l"
|
||||
#line 278 "ncgen.l"
|
||||
{
|
||||
int c;
|
||||
char* p; char* q;
|
||||
lextext = emalloc(1+4*ncgleng); /* should be max needed */
|
||||
/* copy the trimmed name */
|
||||
strncpy(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
p = lextext;
|
||||
q = lextext;
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
p = bbContents(lextext);
|
||||
q = p;
|
||||
while((c=*p++)) {if(c > ' ') *q++ = c;}
|
||||
*q = '\0';
|
||||
datasetname = lextext;
|
||||
datasetname = bbDup(lextext);
|
||||
BEGIN(INITIAL);
|
||||
return lexdebug(DATASETID);
|
||||
}
|
||||
YY_BREAK
|
||||
case 33:
|
||||
YY_RULE_SETUP
|
||||
#line 292 "ncgen.l"
|
||||
{
|
||||
lextext = emalloc(1+4*ncgleng); /* should be max needed */
|
||||
strncpy(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
deescapify(lextext);
|
||||
if (STREQ((char *)lextext, FILL_STRING)) return lexdebug(FILLMARKER);
|
||||
yylval.sym = install(lextext);
|
||||
#line 294 "ncgen.l"
|
||||
{ char* id;
|
||||
bbClear(lextext);
|
||||
bbAppendn(lextext,(char*)ncgtext,ncgleng+1); /* include null */
|
||||
bbNull(lextext);
|
||||
id = bbContents(lextext);
|
||||
deescapify(id);
|
||||
if (STREQ(id, FILL_STRING)) return lexdebug(FILLMARKER);
|
||||
yylval.sym = install(id);
|
||||
return lexdebug(IDENT);
|
||||
}
|
||||
YY_BREAK
|
||||
case 34:
|
||||
YY_RULE_SETUP
|
||||
#line 301 "ncgen.l"
|
||||
#line 305 "ncgen.l"
|
||||
{
|
||||
/* We need to try to see what size of integer ((u)int). */
|
||||
/* Technically, the user should specify, but... */
|
||||
@ -1898,7 +1902,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 35:
|
||||
YY_RULE_SETUP
|
||||
#line 350 "ncgen.l"
|
||||
#line 354 "ncgen.l"
|
||||
{ /* The number may be signed or unsigned (signed has priority) */
|
||||
int slen = strlen(ncgtext);
|
||||
int tag = ncgtext[slen-1];
|
||||
@ -1953,7 +1957,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 36:
|
||||
YY_RULE_SETUP
|
||||
#line 402 "ncgen.l"
|
||||
#line 406 "ncgen.l"
|
||||
{
|
||||
int slen = strlen(ncgtext);
|
||||
int tag = ncgtext[slen-1];
|
||||
@ -1996,7 +2000,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 37:
|
||||
YY_RULE_SETUP
|
||||
#line 441 "ncgen.l"
|
||||
#line 445 "ncgen.l"
|
||||
{
|
||||
int c;
|
||||
int token = 0;
|
||||
@ -2034,7 +2038,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 38:
|
||||
YY_RULE_SETUP
|
||||
#line 475 "ncgen.l"
|
||||
#line 479 "ncgen.l"
|
||||
{
|
||||
if (sscanf((char*)ncgtext, "%le", &double_val) != 1) {
|
||||
sprintf(errstr,"bad long or double constant: %s",(char*)ncgtext);
|
||||
@ -2045,7 +2049,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 39:
|
||||
YY_RULE_SETUP
|
||||
#line 482 "ncgen.l"
|
||||
#line 486 "ncgen.l"
|
||||
{
|
||||
if (sscanf((char*)ncgtext, "%e", &float_val) != 1) {
|
||||
sprintf(errstr,"bad float constant: %s",(char*)ncgtext);
|
||||
@ -2057,7 +2061,7 @@ YY_RULE_SETUP
|
||||
case 40:
|
||||
/* rule 40 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 489 "ncgen.l"
|
||||
#line 493 "ncgen.l"
|
||||
{
|
||||
(void) sscanf((char*)&ncgtext[1],"%c",&byte_val);
|
||||
return lexdebug(BYTE_CONST);
|
||||
@ -2065,7 +2069,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 41:
|
||||
YY_RULE_SETUP
|
||||
#line 493 "ncgen.l"
|
||||
#line 497 "ncgen.l"
|
||||
{
|
||||
byte_val = (char) strtol((char*)&ncgtext[2], (char **) 0, 8);
|
||||
return lexdebug(BYTE_CONST);
|
||||
@ -2073,7 +2077,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 42:
|
||||
YY_RULE_SETUP
|
||||
#line 497 "ncgen.l"
|
||||
#line 501 "ncgen.l"
|
||||
{
|
||||
byte_val = (char) strtol((char*)&ncgtext[3], (char **) 0, 16);
|
||||
return lexdebug(BYTE_CONST);
|
||||
@ -2081,7 +2085,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 43:
|
||||
YY_RULE_SETUP
|
||||
#line 501 "ncgen.l"
|
||||
#line 505 "ncgen.l"
|
||||
{
|
||||
switch ((char)ncgtext[2]) {
|
||||
case 'a': byte_val = '\007'; break; /* not everyone under-
|
||||
@ -2103,7 +2107,7 @@ YY_RULE_SETUP
|
||||
case 44:
|
||||
/* rule 44 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 519 "ncgen.l"
|
||||
#line 523 "ncgen.l"
|
||||
{
|
||||
lineno++ ;
|
||||
break;
|
||||
@ -2111,7 +2115,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 45:
|
||||
YY_RULE_SETUP
|
||||
#line 524 "ncgen.l"
|
||||
#line 528 "ncgen.l"
|
||||
{/*initial*/
|
||||
BEGIN(ST_C_COMMENT);
|
||||
break;
|
||||
@ -2120,21 +2124,21 @@ YY_RULE_SETUP
|
||||
case 46:
|
||||
/* rule 46 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 529 "ncgen.l"
|
||||
#line 533 "ncgen.l"
|
||||
{/* continuation */
|
||||
break;
|
||||
}
|
||||
YY_BREAK
|
||||
case 47:
|
||||
YY_RULE_SETUP
|
||||
#line 533 "ncgen.l"
|
||||
#line 537 "ncgen.l"
|
||||
{/* final */
|
||||
BEGIN(INITIAL);
|
||||
break;
|
||||
}
|
||||
YY_BREAK
|
||||
case YY_STATE_EOF(ST_C_COMMENT):
|
||||
#line 538 "ncgen.l"
|
||||
#line 542 "ncgen.l"
|
||||
{/* final, error */
|
||||
fprintf(stderr,"unterminated /**/ comment");
|
||||
BEGIN(INITIAL);
|
||||
@ -2143,17 +2147,17 @@ case YY_STATE_EOF(ST_C_COMMENT):
|
||||
YY_BREAK
|
||||
case 48:
|
||||
YY_RULE_SETUP
|
||||
#line 544 "ncgen.l"
|
||||
#line 548 "ncgen.l"
|
||||
{/* Note: this next rule will not work for UTF8 characters */
|
||||
return lexdebug(ncgtext[0]) ;
|
||||
}
|
||||
YY_BREAK
|
||||
case 49:
|
||||
YY_RULE_SETUP
|
||||
#line 547 "ncgen.l"
|
||||
#line 551 "ncgen.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 2157 "lex.ncg.c"
|
||||
#line 2161 "lex.ncg.c"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
case YY_STATE_EOF(TEXT):
|
||||
yyterminate();
|
||||
@ -3152,7 +3156,7 @@ void ncgfree (void * ptr )
|
||||
|
||||
#define YYTABLES_NAME "yytables"
|
||||
|
||||
#line 547 "ncgen.l"
|
||||
#line 551 "ncgen.l"
|
||||
|
||||
|
||||
static int
|
||||
@ -3169,7 +3173,7 @@ int
|
||||
lex_init(void)
|
||||
{
|
||||
lineno = 1;
|
||||
lextext = NULL;
|
||||
lextext = bbNew();
|
||||
if(0) unput(0); /* keep -Wall quiet */
|
||||
return 0;
|
||||
}
|
||||
|
221
ncgen/nciter.c
221
ncgen/nciter.c
@ -7,29 +7,19 @@
|
||||
#include "includes.h"
|
||||
#include "nciter.h"
|
||||
|
||||
#undef DOCHUNK
|
||||
|
||||
#define CHECK(stat,f) if(stat != NC_NOERR) {check(stat,#f,__FILE__,__LINE__);} else {}
|
||||
|
||||
/* forward declarations */
|
||||
static int nc_blkio_init(size_t bufsize, size_t value_size, int rank,
|
||||
const size_t *dims, int chunked, size_t *chunksizes,
|
||||
nciter_t *iter);
|
||||
const size_t *dims, nciter_t *iter);
|
||||
static int up_start(int ndims, const size_t *dims, int incdim, size_t inc,
|
||||
size_t* odom);
|
||||
#ifdef DOCHUNK
|
||||
static int up_start_by_chunks(int ndims, const size_t *dims,
|
||||
const size_t *chunks, size_t* odom);
|
||||
#endif
|
||||
|
||||
static int nciter_ndims(Symbol*,int*);
|
||||
static int nciter_dimlens(Symbol*,size_t*);
|
||||
static int nciter_vartype(Symbol*,Symbol**);
|
||||
static int nciter_valuesize(Symbol*,size_t*);
|
||||
#ifdef DOCHUNK
|
||||
static int nciter_contiguous(Symbol*,int*); /* always returns contiguous */
|
||||
static int nciter_chunking(Symbol*,int,size_t*); /* no-op */
|
||||
#endif
|
||||
|
||||
static void
|
||||
check(int err, const char* fcn, const char* file, const int line)
|
||||
@ -54,10 +44,8 @@ nc_get_iter(Symbol* vsym,
|
||||
size_t value_size; /* size in bytes of each variable element */
|
||||
int ndims; /* number of dimensions for variable */
|
||||
size_t dimsizes[NC_MAX_VAR_DIMS]; /* variable dimension sizes */
|
||||
size_t chunksizes[NC_MAX_VAR_DIMS]; /* corresponding chunk sizes */
|
||||
long long nvalues = 1;
|
||||
int dim;
|
||||
int chunked = 0;
|
||||
|
||||
memset((void*)iterp,0,sizeof(nciter_t)); /* make sure it is initialized */
|
||||
|
||||
@ -73,26 +61,7 @@ nc_get_iter(Symbol* vsym,
|
||||
CHECK(stat, nciter_vartype);
|
||||
stat = nciter_valuesize(vartype,&value_size);
|
||||
CHECK(stat, nciter_valuesize);
|
||||
#ifdef USE_NETCDF4
|
||||
#ifdef DOCHUNK
|
||||
{
|
||||
int contig = 1;
|
||||
if(ndims > 0) {
|
||||
stat = nc_inq_var_chunking(ncid, varid, &contig, NULL);
|
||||
CHECK(stat, nc_inq_var_chunking);
|
||||
}
|
||||
if(contig == 0) { /* chunked */
|
||||
stat = nc_inq_var_chunking(ncid, varid, &contig, chunksizes);
|
||||
CHECK(stat, nc_inq_var_chunking);
|
||||
chunked = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
chunked = 0;
|
||||
#endif
|
||||
#endif /* USE_NETCDF4 */
|
||||
stat = nc_blkio_init(bufsize, value_size, ndims, dimsizes,
|
||||
chunked, chunksizes, iterp);
|
||||
stat = nc_blkio_init(bufsize, value_size, ndims, dimsizes, iterp);
|
||||
CHECK(stat, nc_blkio_init);
|
||||
iterp->to_get = 0;
|
||||
return stat;
|
||||
@ -114,59 +83,34 @@ nc_next_iter(nciter_t *iter, /* returned opaque iteration state */
|
||||
size_t *count /* returned count vector for next vara call */
|
||||
) {
|
||||
int i;
|
||||
/* Note: special case for chunked variables is just an
|
||||
* optimization, the contiguous code below is OK even
|
||||
* for chunked variables, but in general will do more I/O ... */
|
||||
if(iter->first) {
|
||||
if(!iter->chunked) { /* contiguous storage */
|
||||
for(i = 0; i < iter->right_dim; i++) {
|
||||
start[i] = 0;
|
||||
count[i] = 1;
|
||||
}
|
||||
start[iter->right_dim] = 0;
|
||||
count[iter->right_dim] = iter->rows;
|
||||
for(i = iter->right_dim + 1; i < iter->rank; i++) {
|
||||
start[i] = 0;
|
||||
count[i] = iter->dimsizes[i];
|
||||
}
|
||||
} else { /* chunked storage */
|
||||
#ifdef DOCHUNK
|
||||
for(i = 0; i < iter->rank; i++) {
|
||||
start[i] = 0;
|
||||
count[i] = iter->chunksizes[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
iter->first = 0;
|
||||
for(i = 0; i < iter->right_dim; i++) {
|
||||
start[i] = 0;
|
||||
count[i] = 1;
|
||||
}
|
||||
start[iter->right_dim] = 0;
|
||||
count[iter->right_dim] = iter->rows;
|
||||
for(i = iter->right_dim + 1; i < iter->rank; i++) {
|
||||
start[i] = 0;
|
||||
count[i] = iter->dimsizes[i];
|
||||
}
|
||||
iter->first = 0;
|
||||
} else {
|
||||
if(!iter->chunked) { /* contiguous storage */
|
||||
iter->more = up_start(iter->rank, iter->dimsizes, iter->right_dim,
|
||||
iter->inc, start);
|
||||
/* iterate on pieces of variable */
|
||||
if(iter->cur < iter->numrows) {
|
||||
iter->inc = iter->rows;
|
||||
count[iter->right_dim] = iter->rows;
|
||||
iter->cur++;
|
||||
} else {
|
||||
if(iter->leftover > 0) {
|
||||
count[iter->right_dim] = iter->leftover;
|
||||
iter->inc = iter->leftover;
|
||||
iter->cur = 0;
|
||||
}
|
||||
}
|
||||
} else { /* chunked storage */
|
||||
#ifdef DOCHUNK
|
||||
iter->more = up_start_by_chunks(iter->rank, iter->dimsizes,
|
||||
iter->chunksizes, start);
|
||||
/* adjust count to stay in range of dimsizes */
|
||||
for(i = 0; i < iter->rank; i++) {
|
||||
int leftover = iter->dimsizes[i] - start[i];
|
||||
count[i] = iter->chunksizes[i];
|
||||
if(leftover < count[i])
|
||||
count[i] = leftover;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
iter->more = up_start(iter->rank, iter->dimsizes, iter->right_dim,
|
||||
iter->inc, start);
|
||||
/* iterate on pieces of variable */
|
||||
if(iter->cur < iter->numrows) {
|
||||
iter->inc = iter->rows;
|
||||
count[iter->right_dim] = iter->rows;
|
||||
iter->cur++;
|
||||
} else {
|
||||
if(iter->leftover > 0) {
|
||||
count[iter->right_dim] = iter->leftover;
|
||||
iter->inc = iter->leftover;
|
||||
iter->cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
iter->to_get = 1;
|
||||
for(i = 0; i < iter->rank; i++) {
|
||||
@ -177,16 +121,13 @@ nc_next_iter(nciter_t *iter, /* returned opaque iteration state */
|
||||
|
||||
|
||||
/* Initialize block iteration for variables, including those that
|
||||
* won't fit in the copy buffer all at once. Returns error if
|
||||
* variable is chunked but size of chunks is too big to fit in bufsize
|
||||
* bytes. */
|
||||
* won't fit in the copy buffer all at once.
|
||||
*/
|
||||
static int
|
||||
nc_blkio_init(size_t bufsize, /* size in bytes of in-memory copy buffer */
|
||||
size_t value_size, /* size in bytes of each variable element */
|
||||
int rank, /* number of dimensions for variable */
|
||||
const size_t *dims, /* variable dimension sizes */
|
||||
int chunked, /* 1 if variable is chunked, 0 otherwise */
|
||||
size_t *chunksizes, /* if chunked, variable chunk sizes */
|
||||
nciter_t *iter /* returned iteration state, don't mess with it */
|
||||
) {
|
||||
int stat = NC_NOERR;
|
||||
@ -196,45 +137,30 @@ nc_blkio_init(size_t bufsize, /* size in bytes of in-memory copy buffer */
|
||||
iter->rank = rank;
|
||||
iter->first = 1;
|
||||
iter->more = 1;
|
||||
iter->chunked = chunked;
|
||||
for(i = 0; i < rank; i++)
|
||||
iter->dimsizes[i] = dims[i];
|
||||
prod = value_size;
|
||||
if(iter->chunked == 0) { /* contiguous */
|
||||
iter->right_dim = rank - 1;
|
||||
for(i = rank; i > 0; i--) {
|
||||
if(prod*dims[i-1] <= bufsize) {
|
||||
prod *= dims[i-1];
|
||||
iter->right_dim--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i > 0) { /* variable won't fit in bufsize bytes */
|
||||
iter->rows = bufsize/prod;
|
||||
iter->numrows = dims[iter->right_dim] / iter->rows;
|
||||
iter->leftover = dims[iter->right_dim] - iter->numrows * iter->rows;
|
||||
iter->cur = 1;
|
||||
iter->inc = iter->rows;
|
||||
return stat;
|
||||
}
|
||||
/* else, variable will fit in bufsize bytes of memory. */
|
||||
iter->right_dim = 0;
|
||||
iter->rows = dims[0];
|
||||
iter->inc = 0;
|
||||
return stat;
|
||||
}
|
||||
#ifdef DOCHUNK
|
||||
/* else, handle chunked case */
|
||||
for(i = 0; i < rank; i++) {
|
||||
iter->chunksizes[i] = chunksizes[i];
|
||||
prod *= chunksizes[i];
|
||||
iter->right_dim = rank - 1;
|
||||
for(i = rank; i > 0; i--) {
|
||||
if(prod*dims[i-1] <= bufsize) {
|
||||
prod *= dims[i-1];
|
||||
iter->right_dim--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(prod > bufsize) {
|
||||
stat = NC_ENOMEM;
|
||||
fprintf(stderr, "chunksize (= %ld) > copy_buffer size (= %ld)\n", prod, bufsize);
|
||||
if (i > 0) { /* variable won't fit in bufsize bytes */
|
||||
iter->rows = bufsize/prod;
|
||||
iter->numrows = dims[iter->right_dim] / iter->rows;
|
||||
iter->leftover = dims[iter->right_dim] - iter->numrows * iter->rows;
|
||||
iter->cur = 1;
|
||||
iter->inc = iter->rows;
|
||||
return stat;
|
||||
}
|
||||
#endif
|
||||
/* else, variable will fit in bufsize bytes of memory. */
|
||||
iter->right_dim = 0;
|
||||
iter->rows = dims[0];
|
||||
iter->inc = 0;
|
||||
return stat;
|
||||
}
|
||||
|
||||
@ -269,36 +195,6 @@ up_start(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DOCHUNK
|
||||
/*
|
||||
* Updates a vector of size_t, odometer style, for chunk access.
|
||||
* Returns 0 if odometer overflowed, else 1.
|
||||
*/
|
||||
static int
|
||||
up_start_by_chunks(
|
||||
int ndims, /* Number of dimensions */
|
||||
const size_t *dims, /* The "odometer" limits for each dimension */
|
||||
const size_t *chunks, /* the odometer increments for each dimension */
|
||||
size_t* odom /* The "odometer" vector to be updated */
|
||||
)
|
||||
{
|
||||
int incdim = ndims - 1;
|
||||
int id;
|
||||
int ret = 1;
|
||||
|
||||
odom[incdim] += chunks[incdim];
|
||||
for (id = incdim; id > 0; id--) {
|
||||
if(odom[id] >= dims[id]) {
|
||||
odom[id-1] += chunks[id-1];
|
||||
/* odom[id] -= dims[id]; */
|
||||
odom[id] = 0;
|
||||
}
|
||||
}
|
||||
if (odom[0] >= dims[0])
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
nciter_ndims(Symbol* sym, int* ndimsp)
|
||||
@ -314,7 +210,7 @@ nciter_dimlens(Symbol* sym, size_t* dimlens)
|
||||
int ndims = sym->typ.dimset.ndims;
|
||||
for(i=0;i<ndims;i++) {
|
||||
Symbol* dim = sym->typ.dimset.dimsyms[i];
|
||||
dimlens[i] = MAX(dim->dim.declsize,dim->dim.unlimitedsize);
|
||||
dimlens[i] = dim->dim.declsize;
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -338,20 +234,3 @@ nciter_valuesize(Symbol* tsym, size_t* valuesizep)
|
||||
*valuesizep = 1;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
#ifdef DOCHUNK
|
||||
static int
|
||||
nciter_contiguous(Symbol* sym, int* iscontiguous)
|
||||
{
|
||||
if(iscontiguous != NULL)
|
||||
*iscontiguous = 1; /* always returns contiguous */
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
static int
|
||||
nciter_chunking(Symbol* sym, int contig, size_t* sizep)
|
||||
{
|
||||
return NC_NOERR; /* no-op */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -28,9 +28,7 @@ typedef struct {
|
||||
size_t to_get; /* number of values to get on this access */
|
||||
int rank; /* number of dimensions */
|
||||
size_t inc; /* increment for right_dim element of start vector */
|
||||
int chunked; /* 1 if chunked, 0 if contiguous */
|
||||
size_t dimsizes[NC_MAX_VAR_DIMS];
|
||||
size_t chunksizes[NC_MAX_VAR_DIMS]; /* ignored if not chunked */
|
||||
} nciter_t;
|
||||
|
||||
/*
|
||||
|
169
ncgen/odom.c
169
ncgen/odom.c
@ -11,31 +11,45 @@
|
||||
/**************************************************/
|
||||
/* Define methods for a dimension odometer*/
|
||||
|
||||
static void
|
||||
initodometer(Odometer* odom, Dimset* dimset, size_t* startp, size_t* countp)
|
||||
Odometer*
|
||||
newodometer(Dimset* dimset, size_t* startp, size_t* countp)
|
||||
{
|
||||
int i;
|
||||
odom->rank = (dimset==NULL?0:dimset->ndims);
|
||||
Odometer* odom;
|
||||
ASSERT(dimset != NULL);
|
||||
ASSERT(dimset->ndims > 0);
|
||||
odom = (Odometer*)emalloc(sizeof(Odometer));
|
||||
if(odom == NULL) return NULL;
|
||||
odom->origin = odom;
|
||||
odom->offset = 0;
|
||||
odom->rank = dimset->ndims;
|
||||
ASSERT(odom->rank <= NC_MAX_VAR_DIMS);
|
||||
for(i=0;i<odom->rank;i++) {
|
||||
odom->declsize[i] = dimset->dimsyms[i]->dim.declsize;
|
||||
odom->unlimitedsize[i] = dimset->dimsyms[i]->dim.unlimitedsize;
|
||||
odom->start[i] = 0;
|
||||
odom->count[i] = odom->declsize[i];
|
||||
if(odom->unlimitedsize[i] > 0)odom->count[i] = odom->unlimitedsize[i];
|
||||
if(startp != NULL) {
|
||||
odom->start[i] = startp[i];
|
||||
odom->count[i] = countp[i];
|
||||
}
|
||||
odom->start[i] = (startp == NULL ? 0
|
||||
: startp[i]);
|
||||
odom->count[i] = (countp == NULL ? odom->declsize[i]
|
||||
: countp[i]);
|
||||
odom->index[i] = odom->start[i];
|
||||
/* verify */
|
||||
ASSERT(odom->start[i] + odom->count[i] <= odom->declsize[i]);
|
||||
}
|
||||
return odom;
|
||||
}
|
||||
|
||||
Odometer*
|
||||
newodometer(Dimset* dimset, size_t* start, size_t* count)
|
||||
newsubodometer(Odometer* origin, Dimset* dimset, int start, int stop)
|
||||
{
|
||||
Odometer* odom = (Odometer*)emalloc(sizeof(Odometer));
|
||||
initodometer(odom,dimset,start,count);
|
||||
Odometer* odom;
|
||||
ASSERT(dimset != NULL);
|
||||
ASSERT(dimset->ndims > 0 && dimset->ndims >= stop);
|
||||
ASSERT(stop > start);
|
||||
odom = (Odometer*)emalloc(sizeof(Odometer));
|
||||
if(odom == NULL) return NULL;
|
||||
odom->origin = origin;
|
||||
odom->offset = start;
|
||||
odom->rank = (stop - start);
|
||||
ASSERT(odom->rank <= NC_MAX_VAR_DIMS);
|
||||
return odom;
|
||||
}
|
||||
|
||||
@ -52,13 +66,16 @@ odometerprint(Odometer* odom)
|
||||
static char line[1024];
|
||||
char tmp[64];
|
||||
line[0] = '\0';
|
||||
if(odom->rank == 0) {
|
||||
if(odom->origin->rank == 0) {
|
||||
strcat(line,"[]");
|
||||
} else for(i=0;i<odom->rank;i++) {
|
||||
sprintf(tmp,"[%lu..(%lu/%lu)]",
|
||||
odom->index[i],
|
||||
odom->unlimitedsize[i],
|
||||
odom->declsize[i]);
|
||||
int ioffset = i + odom->offset;
|
||||
sprintf(tmp,"[%lu/%lu..%lu:%lu]",
|
||||
odom->origin->index[ioffset],
|
||||
odom->origin->start[ioffset],
|
||||
odom->origin->declsize[ioffset],
|
||||
odom->origin->count[ioffset]
|
||||
);
|
||||
strcat(line,tmp);
|
||||
}
|
||||
return line;
|
||||
@ -67,10 +84,38 @@ odometerprint(Odometer* odom)
|
||||
int
|
||||
odometermore(Odometer* odom)
|
||||
{
|
||||
return (odom->rank > 0
|
||||
&& odom->index[0] < (odom->start[0]+odom->count[0]));
|
||||
size_t index,start,count;
|
||||
int offset = odom->offset;
|
||||
ASSERT(odom->rank > 0);
|
||||
index = odom->origin->index[offset];
|
||||
start = odom->origin->start[offset];
|
||||
count = odom->origin->count[offset];
|
||||
if(index < start + count) return 1;
|
||||
/* reset the zero'th wheel before returning */
|
||||
odom->origin->index[offset] = odom->origin->start[offset];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
odometerincr(Odometer* odom)
|
||||
{
|
||||
int i;
|
||||
int last = odom->rank-1;
|
||||
ASSERT(odom->rank > 0);
|
||||
for(i=last;i>=0;i--) {
|
||||
int ioffset = i+odom->offset;
|
||||
odom->origin->index[ioffset]++;
|
||||
if(odom->origin->index[ioffset]
|
||||
< (odom->origin->start[ioffset]
|
||||
+odom->origin->count[ioffset]))
|
||||
break;
|
||||
if(i==0) break; /* leave 0'th for next more() check */
|
||||
odom->origin->index[ioffset] = odom->origin->start[ioffset];
|
||||
}
|
||||
return i; /* return rightmost incremented */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Suppose we have the declaration int F[2][5][3];
|
||||
There are obviously a total of 2 X 5 X 3 = 30 integers in F.
|
||||
@ -80,85 +125,15 @@ A particular point in the three dimensions, say [x][y][z], is reduced to
|
||||
a number in the range 0..29 by computing ((x*5)+y)*3+z
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
odometercount(Odometer* odom)
|
||||
size_t
|
||||
odometeroffset(Odometer* odom)
|
||||
{
|
||||
int i;
|
||||
unsigned long count = 0;
|
||||
size_t count = 0;
|
||||
for(i=0;i<odom->rank;i++) {
|
||||
if(i > 0) count *= odom->count[i];
|
||||
count += odom->index[i];
|
||||
int ioffset = i+odom->offset;
|
||||
if(i > 0) count *= odom->origin->declsize[ioffset];
|
||||
count += odom->origin->index[ioffset];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
odometerreset(Odometer* odom)
|
||||
{
|
||||
int rank = odom->rank;
|
||||
while(rank-- > 0) {odom->index[rank] = odom->start[rank];}
|
||||
}
|
||||
|
||||
/*
|
||||
Given an odometer compute the total
|
||||
number of values it would return starting at a
|
||||
given wheel position; unlimited dimensions
|
||||
are treated as having size 0;
|
||||
*/
|
||||
|
||||
size_t
|
||||
odometertotal(Odometer* odom, int wheel)
|
||||
{
|
||||
int i;
|
||||
unsigned long count = 1;
|
||||
for(i=wheel;i<odom->rank;i++) {
|
||||
count *= odom->count[i];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
odometerincr(Odometer* odom)
|
||||
{
|
||||
int i;
|
||||
int last = odom->rank-1;
|
||||
ASSERT(odom->rank > 0);
|
||||
for(i=last;i>=0;i--) {
|
||||
odom->index[i]++;
|
||||
if(odom->index[i] < (odom->start[i]+odom->count[i])) break;
|
||||
if(i == 0) break; /* leave the 0th entry if it overflows*/
|
||||
odom->index[i] = odom->start[i];
|
||||
}
|
||||
return i; /* return rightmost incremented */
|
||||
}
|
||||
|
||||
/* compute the total n-dimensional size as 1 long array;
|
||||
stop if we encounter an unlimited dimension
|
||||
*/
|
||||
size_t
|
||||
odomsubarray(Odometer* odom, int index)
|
||||
{
|
||||
size_t result = 1;
|
||||
int i;
|
||||
for(i=index;i<odom->rank;i++) {
|
||||
/* treat unlimited as having size 1 because it will be a sublist */
|
||||
if(odom->declsize[i] == 0) break; /*unlimited*/
|
||||
result *= odom->declsize[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* compute the total offset represented by the current wheel
|
||||
positions for indices 0 .. index.
|
||||
*/
|
||||
size_t
|
||||
odomprefixcount(Odometer* odom, int index)
|
||||
{
|
||||
size_t result = 1;
|
||||
int i;
|
||||
for(i=0;i<=index;i++) {
|
||||
result *= odom->count[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
28
ncgen/odom.h
28
ncgen/odom.h
@ -2,36 +2,42 @@
|
||||
* Copyright 2009, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
/* $Id: odom.h,v 1.5 2010/05/27 21:34:18 dmh Exp $ */
|
||||
/* $Header: /upc/share/CVS/netcdf-3/ncgen/odom.h,v 1.5 2010/05/27 21:34:18 dmh Exp $ */
|
||||
|
||||
#ifndef ODOM_H
|
||||
#define ODOM_H 1
|
||||
|
||||
typedef struct Odometer {
|
||||
int rank;
|
||||
int wholepoint; /*point where whole dimensions are being used; -1=>none*/
|
||||
size_t index[NC_MAX_VAR_DIMS];
|
||||
size_t start[NC_MAX_VAR_DIMS];
|
||||
size_t count[NC_MAX_VAR_DIMS];
|
||||
size_t unlimitedsize[NC_MAX_VAR_DIMS];
|
||||
size_t declsize[NC_MAX_VAR_DIMS]; /* 0 => unlimited */
|
||||
int offset;
|
||||
struct Odometer* origin;
|
||||
size_t start[NC_MAX_VAR_DIMS];
|
||||
size_t count[NC_MAX_VAR_DIMS];
|
||||
size_t index[NC_MAX_VAR_DIMS];
|
||||
size_t declsize[NC_MAX_VAR_DIMS];
|
||||
} Odometer;
|
||||
|
||||
struct Dimset; /* forward */
|
||||
/*Forward*/
|
||||
struct Dimset;
|
||||
|
||||
/* Odometer operators*/
|
||||
extern Odometer* newodometer(struct Dimset*, size_t* startp, size_t* countp);
|
||||
extern Odometer* newsubodometer(Odometer*, struct Dimset*, int, int);
|
||||
|
||||
extern Odometer* newsubodometer(Odometer*, struct Dimset*,
|
||||
int start, int stop);
|
||||
|
||||
extern void odometerfree(Odometer*);
|
||||
extern char* odometerprint(Odometer* odom);
|
||||
extern int odomupdate(Odometer*, size_t* startp, size_t* countp);
|
||||
|
||||
extern int odometermore(Odometer* odom);
|
||||
extern int odometerincr(Odometer* odo);
|
||||
extern unsigned long odometercount(Odometer* odo);
|
||||
extern size_t odometeroffset(Odometer* odom);
|
||||
|
||||
#ifdef NOTUSED
|
||||
extern void odometerreset(Odometer*);
|
||||
extern size_t odometertotal(Odometer*,int);
|
||||
extern size_t odomsubarray(Odometer* odom, int index);
|
||||
extern size_t odomprefixcount(Odometer* odom, int index);
|
||||
#endif
|
||||
|
||||
#endif /*ODOM_H*/
|
||||
|
@ -17,25 +17,13 @@ static void processtypesizes(void);
|
||||
static void processvars(void);
|
||||
static void processattributes(void);
|
||||
static void processspecials(void);
|
||||
|
||||
static void processdatalists(void);
|
||||
static void processdatalist(Symbol*);
|
||||
static void processunlimiteddims(void);
|
||||
|
||||
static void inferattributetype(Symbol* asym);
|
||||
static void checkconsistency(void);
|
||||
static void validate(void);
|
||||
static int tagvlentypes(Symbol* tsym);
|
||||
|
||||
static void walkdata(Symbol*);
|
||||
static void walkarray(Symbol*, Datasrc*, int, Datalist*);
|
||||
static void walktype(Symbol*, Datasrc*, Datalist*);
|
||||
static void walkfieldarray(Symbol*, Datasrc*, Dimset*, int);
|
||||
|
||||
static void walkchararray(Symbol*,Datalist*);
|
||||
static void walkchararrayr(Dimset* dimset, Datalist** datap, int lastunlim, int index, int fillchar);
|
||||
static void walkcharfieldarray(Constant*, Dimset*, Datalist*);
|
||||
static void walkcharvlen(Constant*);
|
||||
|
||||
static Symbol* uniquetreelocate(Symbol* refsym, Symbol* root);
|
||||
|
||||
List* vlenconstants; /* List<Constant*>;*/
|
||||
@ -61,8 +49,8 @@ processsemantics(void)
|
||||
processattributes();
|
||||
/* Fix up enum constant values*/
|
||||
processenums();
|
||||
/* Fix up datalists*/
|
||||
processdatalists();
|
||||
/* Compute the unlimited dimension sizes */
|
||||
processunlimiteddims();
|
||||
/* check internal consistency*/
|
||||
checkconsistency();
|
||||
/* do any needed additional semantic checks*/
|
||||
@ -422,10 +410,10 @@ computesize(Symbol* tsym)
|
||||
}
|
||||
tsym->typ.size = offset;
|
||||
break;
|
||||
case NC_FIELD: /* Compute size of all non-unlimited dimensions*/
|
||||
case NC_FIELD: /* Compute size assume no unlimited dimensions*/
|
||||
if(tsym->typ.dimset.ndims > 0) {
|
||||
computesize(tsym->typ.basetype);
|
||||
totaldimsize = arraylength(&tsym->typ.dimset);
|
||||
totaldimsize = crossproduct(&tsym->typ.dimset,0,0);
|
||||
tsym->typ.size = tsym->typ.basetype->typ.size * totaldimsize;
|
||||
tsym->typ.alignment = tsym->typ.basetype->typ.alignment;
|
||||
tsym->typ.nelems = 1;
|
||||
@ -577,7 +565,6 @@ static void
|
||||
processspecials(void)
|
||||
{
|
||||
int i;
|
||||
if(allowspecial) return; /* Only dump attributes if using netcdf-3 */
|
||||
for(i=0;i<listlength(vardefs);i++) {
|
||||
Symbol* vsym = (Symbol*)listget(vardefs,i);
|
||||
processspecial1(vsym);
|
||||
@ -594,7 +581,9 @@ processattributes(void)
|
||||
/* If the attribute has a zero length, then default it */
|
||||
if(asym->data == NULL || asym->data->length == 0) {
|
||||
asym->data = builddatalist(1);
|
||||
#ifdef IGNORE
|
||||
dlappend(asym->data,NULL);
|
||||
#endif
|
||||
emptystringconst(asym->lineno,&asym->data->data[asym->data->length]);
|
||||
/* force type to be NC_CHAR */
|
||||
asym->typ.basetype = primsymbols[NC_CHAR];
|
||||
@ -609,12 +598,29 @@ processattributes(void)
|
||||
/* If the attribute has a zero length, then default it */
|
||||
if(asym->data == NULL || asym->data->length == 0) {
|
||||
asym->data = builddatalist(1);
|
||||
#ifdef IGNORE
|
||||
dlappend(asym->data,NULL);
|
||||
#endif
|
||||
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);
|
||||
/* 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;
|
||||
}
|
||||
@ -746,21 +752,6 @@ lookup(nc_class objectclass, Symbol* pattern)
|
||||
return lookupingroup(objectclass,pattern->name,grp);
|
||||
}
|
||||
|
||||
#ifndef NO_STDARG
|
||||
void
|
||||
semerror(const int lno, const char *fmt, ...)
|
||||
#else
|
||||
void
|
||||
semerror(lno,fmt,va_alist) const int lno; const char* fmt; va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list argv;
|
||||
vastart(argv,fmt);
|
||||
(void)fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lno);
|
||||
vderror(fmt,argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* return internal size for values of specified netCDF type */
|
||||
size_t
|
||||
@ -846,494 +837,112 @@ validate(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Do any pre-processing of datalists.
|
||||
1. Compute the effective size of unlimited
|
||||
dimensions vis-a-vis this data list
|
||||
2. Compute the length of attribute lists
|
||||
3. Collect the VLEN constants
|
||||
4. add fills as needed to get lengths correct
|
||||
5. comput max of interior unlimited instances
|
||||
*/
|
||||
|
||||
void
|
||||
processdatalists(void)
|
||||
static void
|
||||
computeunlimitedsizes(Dimset* dimset, int dimindex, Datalist* data, int ischar)
|
||||
{
|
||||
int i;
|
||||
if(debug > 0) fdebug("processdatalists:\n");
|
||||
vlenconstants = listnew();
|
||||
size_t xproduct, unlimsize;
|
||||
int nextunlim,lastunlim;
|
||||
Symbol* thisunlim = dimset->dimsyms[dimindex];
|
||||
size_t length;
|
||||
|
||||
ASSERT(thisunlim->dim.isunlimited);
|
||||
nextunlim = findunlimited(dimset,dimindex+1);
|
||||
lastunlim = (nextunlim == dimset->ndims);
|
||||
|
||||
listsetalloc(vlenconstants,1024);
|
||||
xproduct = crossproduct(dimset,dimindex+1,nextunlim);
|
||||
|
||||
/* process global attributes*/
|
||||
for(i=0;i<listlength(gattdefs);i++) {
|
||||
Symbol* asym = (Symbol*)listget(gattdefs,i);
|
||||
if(asym->data != NULL)
|
||||
processdatalist(asym);
|
||||
if(debug > 0 && asym->data != NULL) {
|
||||
fdebug(":%s.datalist: ",asym->name);
|
||||
dumpdatalist(asym->data,"");
|
||||
fdebug("\n");
|
||||
if(!lastunlim) {
|
||||
/*!lastunlim => data is list of sublists, recurse on each sublist*/
|
||||
for(i=0;i<data->length;i++) {
|
||||
Constant* con = data->data+i;
|
||||
ASSERT(con->nctype == NC_COMPOUND);
|
||||
computeunlimitedsizes(dimset,nextunlim,con->value.compoundv,ischar);
|
||||
}
|
||||
}
|
||||
/* process per variable attributes*/
|
||||
for(i=0;i<listlength(attdefs);i++) {
|
||||
Symbol* asym = (Symbol*)listget(attdefs,i);
|
||||
if(asym->data != NULL)
|
||||
processdatalist(asym);
|
||||
if(debug > 0 && asym->data != NULL) {
|
||||
fdebug("%s:%s.datalist: ",asym->att.var->name,asym->name);
|
||||
dumpdatalist(asym->data,"");
|
||||
fdebug("\n");
|
||||
/* Compute candiate size of this unlimited */
|
||||
length = data->length;
|
||||
unlimsize = length / xproduct;
|
||||
if(length % xproduct != 0)
|
||||
unlimsize++; /* => fill requires at some point */
|
||||
#ifdef DEBUG2
|
||||
fprintf(stderr,"unlimsize: dim=%s declsize=%d xproduct=%d newsize=%d\n",
|
||||
thisunlim->name,thisunlim->dim.declsize,xproduct,unlimsize);
|
||||
#endif
|
||||
if(thisunlim->dim.declsize < unlimsize) /* want max length of the unlimited*/
|
||||
thisunlim->dim.declsize = unlimsize;
|
||||
} else {//lastunlim
|
||||
if(ischar) {
|
||||
/* Char case requires special computations;
|
||||
compute total number of characters */
|
||||
length = 0;
|
||||
for(i=0;i<data->length;i++) {
|
||||
Constant* con = &data->data[i];
|
||||
switch (con->nctype) {
|
||||
case NC_CHAR: case NC_BYTE: case NC_UBYTE:
|
||||
length++;
|
||||
break;
|
||||
case NC_STRING:
|
||||
length += con->value.stringv.len;
|
||||
break;
|
||||
default:
|
||||
semwarn(datalistline(data),"Illegal character constant");
|
||||
}
|
||||
}
|
||||
} else { /* Data list should be a list of simple non-char constants */
|
||||
length = data->length;
|
||||
}
|
||||
unlimsize = length / xproduct;
|
||||
if(length % xproduct != 0)
|
||||
unlimsize++; /* => fill requires at some point */
|
||||
#ifdef DEBUG2
|
||||
fprintf(stderr,"unlimsize: dim=%s declsize=%d xproduct=%d newsize=%d\n",
|
||||
thisunlim->name,thisunlim->dim.declsize,xproduct,unlimsize);
|
||||
#endif
|
||||
if(thisunlim->dim.declsize < unlimsize) /* want max length of the unlimited*/
|
||||
thisunlim->dim.declsize = unlimsize;
|
||||
}
|
||||
/* process all variable data lists */
|
||||
}
|
||||
|
||||
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* vsym = (Symbol*)listget(vardefs,i);
|
||||
if(vsym->data != NULL)
|
||||
processdatalist(vsym);
|
||||
if(debug > 0 && vsym->data != NULL) {
|
||||
fdebug("%s.datalist: ",vsym->name);
|
||||
dumpdatalist(vsym->data,"");
|
||||
fdebug("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
processdatalist(Symbol* sym)
|
||||
{
|
||||
walkdata(sym);
|
||||
}
|
||||
|
||||
/*
|
||||
Recursively walk the variable/basetype and
|
||||
simultaneously walk the datasrc.
|
||||
Uses separate code for:
|
||||
1. variables
|
||||
2. types
|
||||
3. field arrays
|
||||
This set of procedures is an example of the
|
||||
canonical way to simultaneously walk a variable
|
||||
and a datalist.
|
||||
*/
|
||||
|
||||
static void
|
||||
walkdata(Symbol* sym)
|
||||
{
|
||||
int rank = sym->typ.dimset.ndims;
|
||||
size_t total = 0;
|
||||
Datasrc* src = NULL;
|
||||
Datalist* fillsrc = sym->var.special._Fillvalue;
|
||||
int ischartype = (sym->typ.basetype->typ.typecode == NC_CHAR);
|
||||
|
||||
/* special case */
|
||||
if(sym->objectclass == NC_VAR && ischartype && rank > 0) {
|
||||
walkchararray(sym, fillsrc);
|
||||
} else {
|
||||
src = datalist2src(sym->data);
|
||||
switch (sym->objectclass) {
|
||||
case NC_VAR:
|
||||
if(rank == 0) /*scalar*/
|
||||
walktype(sym->typ.basetype,src,fillsrc);
|
||||
else
|
||||
walkarray(sym,src,0,fillsrc);
|
||||
break;
|
||||
case NC_ATT:
|
||||
for(total=0;srcpeek(src) != NULL;total++)
|
||||
walktype(sym->typ.basetype,src,NULL);
|
||||
break;
|
||||
default:
|
||||
PANIC1("walkdata: illegal objectclass: %d",(int)sym->objectclass);
|
||||
break;
|
||||
}
|
||||
if(src) freedatasrc(src);
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk non-character arrays */
|
||||
static void
|
||||
walkarray(Symbol* vsym, Datasrc* src, int dimindex, Datalist* fillsrc)
|
||||
{
|
||||
int i;
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int rank = dimset->ndims;
|
||||
int lastdim = (dimindex == (rank-1));
|
||||
int firstdim = (dimindex == 0);
|
||||
Symbol* dim = dimset->dimsyms[dimindex];
|
||||
int isunlimited = (dim->dim.declsize == NC_UNLIMITED);
|
||||
size_t count = 0;
|
||||
|
||||
ASSERT(rank > 0);
|
||||
|
||||
ASSERT(vsym->typ.basetype->typ.typecode != NC_CHAR);
|
||||
|
||||
if(isunlimited) {
|
||||
int pushed = 0;
|
||||
if(!firstdim) {
|
||||
if(!issublist(src))
|
||||
semerror(srcline(src),"Expected {..} found primitive");
|
||||
srcpush(src);
|
||||
pushed = 1;
|
||||
}
|
||||
for(count=0;srcpeek(src) != NULL;count++) {
|
||||
if(lastdim)
|
||||
walktype(vsym->typ.basetype,src,fillsrc);
|
||||
else
|
||||
walkarray(vsym,src,dimindex+1,fillsrc);
|
||||
}
|
||||
/* compute unlimited max */
|
||||
dim->dim.unlimitedsize = MAX(count,dim->dim.unlimitedsize);
|
||||
if(pushed) srcpop(src);
|
||||
} else { /* !ischartype && !isunlimited */
|
||||
count = dim->dim.declsize;
|
||||
for(i=0;i<dim->dim.declsize;i++) {
|
||||
if(lastdim)
|
||||
walktype(vsym->typ.basetype,src,fillsrc);
|
||||
else
|
||||
walkarray(vsym,src,dimindex+1,fillsrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
walktype(Symbol* tsym, Datasrc* src, Datalist* fillsrc)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
Constant* con;
|
||||
Datalist* dl;
|
||||
|
||||
ASSERT(tsym->objectclass == NC_TYPE);
|
||||
|
||||
switch (tsym->subclass) {
|
||||
|
||||
case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
|
||||
srcnext(src);
|
||||
break;
|
||||
|
||||
case NC_COMPOUND:
|
||||
if(!isfillvalue(src) && !issublist(src)) {/* fail on no compound*/
|
||||
semerror(srcline(src),"Compound constants must be enclosed in {..}");
|
||||
}
|
||||
con = srcnext(src);
|
||||
if(con == NULL || con->nctype == NC_FILLVALUE) {
|
||||
dl = getfiller(tsym,fillsrc);
|
||||
ASSERT(dl->length == 1);
|
||||
con = &dl->data[0];
|
||||
if(con->nctype != NC_COMPOUND) {
|
||||
semerror(srcline(src),"Vlen fill constants must be enclosed in {..}");
|
||||
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 {
|
||||
for(i=0;i<var->data->length;i++) {
|
||||
Constant* con = var->data->data+i;
|
||||
ASSERT(con->nctype == NC_COMPOUND);
|
||||
computeunlimitedsizes(dimset,first,con->value.compoundv,ischar);
|
||||
}
|
||||
}
|
||||
dl = con->value.compoundv;
|
||||
srcpushlist(src,dl); /* enter the sublist*/
|
||||
for(count=0,i=0;i<listlength(tsym->subnodes) && srcmore(src);i++,count++) {
|
||||
Symbol* field = (Symbol*)listget(tsym->subnodes,i);
|
||||
walktype(field,src,NULL);
|
||||
}
|
||||
srcpop(src);
|
||||
break;
|
||||
|
||||
case NC_VLEN:
|
||||
if(!isfillvalue(src) && !issublist(src)) {/* fail on no compound*/
|
||||
semerror(srcline(src),"Vlen constants must be enclosed in {..}");
|
||||
}
|
||||
con = srcnext(src);
|
||||
if(con == NULL || con->nctype == NC_FILLVALUE) {
|
||||
dl = getfiller(tsym,fillsrc);
|
||||
ASSERT(dl->length == 1);
|
||||
con = &dl->data[0];
|
||||
if(con->nctype != NC_COMPOUND) {
|
||||
semerror(srcline(src),"Vlen fill constants must be enclosed in {..}");
|
||||
}
|
||||
}
|
||||
if(!listcontains(vlenconstants,(elem_t)con)) {
|
||||
dl = con->value.compoundv;
|
||||
/* Process list only if new */
|
||||
srcpushlist(src,dl); /* enter the sublist*/
|
||||
if(tsym->typ.basetype->typ.typecode == NC_CHAR) {
|
||||
walkcharvlen(con);
|
||||
} else for(count = 0;srcmore(src);count++) {
|
||||
walktype(tsym->typ.basetype,src,NULL);
|
||||
}
|
||||
srcpop(src);
|
||||
dl->vlen.count = count;
|
||||
dl->vlen.uid = listlength(vlenconstants);
|
||||
dl->vlen.schema = tsym;
|
||||
listpush(vlenconstants,(elem_t)con);
|
||||
}
|
||||
break;
|
||||
case NC_FIELD:
|
||||
if(tsym->typ.dimset.ndims > 0) {
|
||||
if(tsym->typ.basetype->typ.typecode == NC_CHAR) {
|
||||
Constant* con = srcnext(src);
|
||||
walkcharfieldarray(con,&tsym->typ.dimset,fillsrc);
|
||||
} else
|
||||
walkfieldarray(tsym->typ.basetype,src,&tsym->typ.dimset,0);
|
||||
} else
|
||||
walktype(tsym->typ.basetype,src,NULL);
|
||||
break;
|
||||
|
||||
default: PANIC1("processdatalist: unexpected subclass %d",tsym->subclass);
|
||||
}
|
||||
}
|
||||
|
||||
/* Used only for structure field arrays*/
|
||||
static void
|
||||
walkfieldarray(Symbol* basetype, Datasrc* src, Dimset* dimset, int index)
|
||||
{
|
||||
int i;
|
||||
int rank = dimset->ndims;
|
||||
int lastdim = (index == (rank-1));
|
||||
Symbol* dim = dimset->dimsyms[index];
|
||||
size_t datasize = dim->dim.declsize;
|
||||
|
||||
ASSERT(datasize != 0);
|
||||
for(i=0;i<datasize;i++) {
|
||||
if(lastdim)
|
||||
walktype(basetype,src,NULL);
|
||||
else
|
||||
walkfieldarray(basetype,src,dimset,index+1);
|
||||
#ifdef DEBUG1
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if the set of dimensions from..rank-1 are not unlimited */
|
||||
int
|
||||
nounlimited(Dimset* dimset, int from)
|
||||
{
|
||||
int index;
|
||||
index = lastunlimited(dimset);
|
||||
return (index <= from ? 1: 0);
|
||||
}
|
||||
|
||||
/* Return index of the rightmost unlimited dimension; -1 => no unlimiteds */
|
||||
int
|
||||
lastunlimited(Dimset* dimset)
|
||||
{
|
||||
int i,index;
|
||||
for(index=-1,i=0;i<dimset->ndims;i++) {
|
||||
Symbol* dim = dimset->dimsyms[i];
|
||||
if(dim->dim.declsize == NC_UNLIMITED) index = i;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Field is an array and basetype is character.
|
||||
The constant should be of the form { <stringable>, <stringable>...}.
|
||||
Make each stringable be a multiple of the size of the last
|
||||
dimension of the field array. Then concat all of them
|
||||
together into one long string. Then pad that string to be
|
||||
as long as the product of the array dimensions. Finally,
|
||||
modify the constant to hold that long string.
|
||||
*/
|
||||
static void
|
||||
walkcharfieldarray(Constant* con, Dimset* dimset, Datalist* fillsrc)
|
||||
{
|
||||
int rank = dimset->ndims;
|
||||
Symbol* lastdim = dimset->dimsyms[rank-1];
|
||||
size_t lastdimsize = lastdim->dim.declsize;
|
||||
size_t slabsize = subarraylength(dimset,0);
|
||||
int fillchar = getfillchar(fillsrc);
|
||||
Datalist* data;
|
||||
Constant newcon;
|
||||
|
||||
/* By data constant rules, con should be a compound object */
|
||||
if(con->nctype != NC_COMPOUND) {
|
||||
semerror(con->lineno,"Malformed character field array");
|
||||
return;
|
||||
}
|
||||
data = con->value.compoundv;
|
||||
/* canonicalize the strings in con and then pad to slabsize */
|
||||
if(!buildcanonicalcharlist(data,lastdimsize,fillchar,&newcon))
|
||||
return;
|
||||
/* pad to slabsize */
|
||||
padstring(&newcon,slabsize,fillchar);
|
||||
/* Now, since we have a compound containing a single string,
|
||||
optimize by replacing the compound with the string.
|
||||
*/
|
||||
*con = newcon;
|
||||
}
|
||||
|
||||
/* Vsym is an array variable whose basetype is character.
|
||||
The vsym->data list should be a set of strings
|
||||
possibly enclosed in one or more nested sets of braces.
|
||||
{<stringlist>}, {<stringlist>}...
|
||||
There are several cases to consider.
|
||||
1. the variable's dimension set has no unlimiteds
|
||||
Actions:
|
||||
1. for each stringable in the data list,
|
||||
pad it up to a multiple of the size of the
|
||||
last dimension.
|
||||
2. concat all of the stringables
|
||||
3. pad the concat to the size of the product of
|
||||
the dimension sizes.
|
||||
2. the dimension set has one or more unlimiteds.
|
||||
This means that we have to recursively deal with
|
||||
nested compound instances.
|
||||
|
||||
The last (rightmost) unlimited will correspond
|
||||
to a sequence of stringables.
|
||||
This has two special subcases
|
||||
2a. the last dimension IS NOT unlimited
|
||||
Actions:
|
||||
1. for each stringable in the data list,
|
||||
pad it up to a multiple of the size of the
|
||||
last dimension.
|
||||
2. concat all of the stringables
|
||||
3. Use the length of the concat plus the
|
||||
product of the dimensions from just
|
||||
after the last unlimited to the last dimension
|
||||
to inform the size of the unlimited.
|
||||
2b. the last dimension IS unlimited
|
||||
Actions:
|
||||
1. concat all of the stringables with no padding
|
||||
2. Use the length of the concat to inform the size
|
||||
of the unlimited.
|
||||
|
||||
Each unlimited dimension to the left of the last unlimited
|
||||
will introduce another nesting of braces.
|
||||
|
||||
3. For each dimension to the left of the last
|
||||
unlimited, there are two cases.
|
||||
3a. dimension is NOT unlimited
|
||||
ACTION:
|
||||
1. The set of items from the right are padded to
|
||||
the length of the dimension size
|
||||
3b. dimension IS unlimited
|
||||
ACTION:
|
||||
1. no action
|
||||
|
||||
Finally, modify the variable's data list to contain these
|
||||
modified stringlists.
|
||||
*/
|
||||
static void
|
||||
walkchararray(Symbol* vsym, Datalist* fillsrc)
|
||||
{
|
||||
Dimset* dimset = &vsym->typ.dimset;
|
||||
int lastunlimindex;
|
||||
int rank = dimset->ndims;
|
||||
Symbol* lastdim = dimset->dimsyms[rank-1];
|
||||
size_t lastdimsize = lastdim->dim.declsize;
|
||||
Constant newcon = nullconstant;
|
||||
int fillchar = getfillchar(fillsrc);
|
||||
|
||||
lastunlimindex = lastunlimited(dimset);
|
||||
#ifdef IGNORE
|
||||
simpleunlim = (lastunlimindex == 0);
|
||||
#endif
|
||||
/* If the unlimited is also the last dimension, then do no padding */
|
||||
if(lastdimsize == 0) lastdimsize = 1;
|
||||
|
||||
if(lastunlimindex < 0) {
|
||||
/* If it turns out that there are no unlimiteds, then canonicalize
|
||||
the string and then pad to the dim product
|
||||
*/
|
||||
size_t slabsize = arraylength(dimset);
|
||||
/* If rank is 1, then dont' pad the string */
|
||||
if(rank == 1) lastdimsize = 1;
|
||||
if(!buildcanonicalcharlist(vsym->data,lastdimsize,fillchar,&newcon))
|
||||
return;
|
||||
/* pad to slabsize */
|
||||
padstring(&newcon,slabsize,fillchar);
|
||||
/* replace vsym->data */
|
||||
vsym->data = const2list(&newcon);
|
||||
#ifdef IGNORE
|
||||
} else if(simpleunlim) {
|
||||
/* First dimension is the only unlimited */
|
||||
/* canonicalize but do not attempt to pad because
|
||||
we do not yet know the final size of the unlimited dimension
|
||||
*/
|
||||
size_t count, subslabsize;
|
||||
Symbol* dim0 = dimset->dimsyms[0];
|
||||
ASSERT(dim0->dim.declsize == NC_UNLIMITED);
|
||||
if(!buildcanonicalcharlist(vsym->data,lastdimsize,fillchar,&newcon))
|
||||
return;
|
||||
/* track consistency with the unlimited dimension */
|
||||
/* Compute the size of the subslab below this dimension */
|
||||
subslabsize = subarraylength(dimset,lastunlimindex+1);
|
||||
/* divide stringv.len by subslabsize and use as the unlim count*/
|
||||
count = newcon.value.stringv.len / subslabsize;
|
||||
dim0->dim.unlimitedsize = MAX(count,dim0->dim.unlimitedsize);
|
||||
/* replace vsym->data */
|
||||
vsym->data = const2list(&newcon);
|
||||
#endif
|
||||
} else {/* 1 or more unlimiteds */
|
||||
walkchararrayr(&vsym->typ.dimset, &vsym->data, lastunlimindex, 0, fillchar);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle case 3:
|
||||
this will recursively walk down the
|
||||
compound nesting to apply actions.
|
||||
*/
|
||||
|
||||
static void
|
||||
walkchararrayr(Dimset* dimset, Datalist** datap, int lastunlimited, int index, int fillchar)
|
||||
{
|
||||
int i;
|
||||
Symbol* dim = dimset->dimsyms[index];
|
||||
int rank = dimset->ndims;
|
||||
int isunlimited = (dim->dim.declsize == NC_UNLIMITED);
|
||||
Datalist* data = *datap;
|
||||
|
||||
/* Split on islastunlimited or not */
|
||||
if(index == lastunlimited) {
|
||||
size_t subslabsize,count;
|
||||
Symbol* lastdim = dimset->dimsyms[rank-1];
|
||||
size_t lastdimsize = (lastdim->dim.declsize==NC_UNLIMITED?1:lastdim->dim.declsize);
|
||||
Constant newcon = nullconstant;
|
||||
/* The datalist should contain just stringables; concat them with padding */
|
||||
if(!buildcanonicalcharlist(data,lastdimsize,fillchar,&newcon))
|
||||
return;
|
||||
/* track consistency with the unlimited dimension */
|
||||
/* Compute the size of the subslab below this dimension */
|
||||
subslabsize = subarraylength(dimset,index+1);
|
||||
/* divide stringv.len by subslabsize and use as the unlim count*/
|
||||
count = newcon.value.stringv.len / subslabsize;
|
||||
dim->dim.unlimitedsize = MAX(count,dim->dim.unlimitedsize);
|
||||
/* replace parent compound */
|
||||
*datap = const2list(&newcon);
|
||||
} else {/* dimension to left of last unlimited */
|
||||
/* data should be a set of compounds */
|
||||
size_t expected = (isunlimited ? data->length : dim->dim.declsize );
|
||||
for(i=0;i<expected;i++) {
|
||||
Constant* con;
|
||||
if(i >= data->length) {/* extend data */
|
||||
Constant cmpd;
|
||||
emptycompoundconst(datalistline(data),&cmpd);
|
||||
dlappend(data,&cmpd);
|
||||
}
|
||||
con = data->data+i;
|
||||
if(con->nctype != NC_COMPOUND) {
|
||||
semerror(datalistline(data),"Malformed Character datalist");
|
||||
continue;
|
||||
}
|
||||
/* recurse */
|
||||
walkchararrayr(dimset,&con->value.compoundv,lastunlimited,index+1,fillchar);
|
||||
|
||||
if(isunlimited) /* set unlim count */
|
||||
dim->dim.unlimitedsize = MAX(data->length,dim->dim.unlimitedsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
walkcharvlen(Constant* src)
|
||||
{
|
||||
Datalist* data;
|
||||
Constant newcon;
|
||||
|
||||
/* By data constant rules, src should be a compound object */
|
||||
if(src->nctype != NC_COMPOUND) {
|
||||
semerror(src->lineno,"Malformed character vlen");
|
||||
return;
|
||||
}
|
||||
data = src->value.compoundv;
|
||||
/* canonicalize the strings in src */
|
||||
if(!buildcanonicalcharlist(data,1,NC_FILL_CHAR,&newcon))
|
||||
return;
|
||||
/* replace src */
|
||||
*src = newcon;
|
||||
}
|
||||
|
||||
|
60
ncgen/util.c
60
ncgen/util.c
@ -6,6 +6,8 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#define DATALISTINIT 32
|
||||
|
||||
/* Track primitive symbol instances (initialized in ncgen.y) */
|
||||
Symbol* primsymbols[PRIMNO];
|
||||
|
||||
@ -488,7 +490,6 @@ dlsetalloc(Datalist* dl, size_t newalloc)
|
||||
dl->data = newdata;
|
||||
}
|
||||
|
||||
#define DATALISTINIT 256
|
||||
|
||||
Datalist*
|
||||
builddatalist(int initial)
|
||||
@ -583,30 +584,22 @@ cleanup()
|
||||
reclaimSymbols();
|
||||
}
|
||||
|
||||
/* compute the total n-dimensional size as 1 long array;
|
||||
if stop == 0, then stop = dimset->ndims.
|
||||
*/
|
||||
size_t
|
||||
arraylength(Dimset* dimset)
|
||||
{
|
||||
return subarraylength(dimset,0);
|
||||
}
|
||||
|
||||
/* compute the total n-dimensional size as 1 long array*/
|
||||
/* stop if we encounter an unlimited dimension */
|
||||
size_t
|
||||
subarraylength(Dimset* dimset, int first)
|
||||
crossproduct(Dimset* dimset, int start, int stop)
|
||||
{
|
||||
size_t totalsize = 1;
|
||||
int i,last;
|
||||
last = dimset->ndims;
|
||||
for(i=first;i<last;i++) {
|
||||
if(dimset->dimsyms[i]->dim.declsize == NC_UNLIMITED) break;
|
||||
totalsize = totalsize * MAX(dimset->dimsyms[i]->dim.unlimitedsize,
|
||||
dimset->dimsyms[i]->dim.declsize);
|
||||
int i;
|
||||
if(stop == 0) stop = dimset->ndims;
|
||||
for(i=start;i<stop;i++) {
|
||||
totalsize = totalsize * dimset->dimsyms[i]->dim.declsize;
|
||||
}
|
||||
return totalsize;
|
||||
}
|
||||
|
||||
|
||||
/* Do the "complement" of subarray length;
|
||||
/* Do the "complement" of crossproduct;
|
||||
compute the total n-dimensional size of an array
|
||||
starting at 0 thru the 'last' array index.
|
||||
stop if we encounter an unlimited dimension
|
||||
@ -614,14 +607,7 @@ subarraylength(Dimset* dimset, int first)
|
||||
size_t
|
||||
prefixarraylength(Dimset* dimset, int last)
|
||||
{
|
||||
size_t totalsize = 1;
|
||||
int i;
|
||||
for(i=0;i<=last;i++) {
|
||||
if(dimset->dimsyms[i]->dim.declsize == NC_UNLIMITED) break;
|
||||
totalsize = totalsize * MAX(dimset->dimsyms[i]->dim.unlimitedsize,
|
||||
dimset->dimsyms[i]->dim.declsize);
|
||||
}
|
||||
return totalsize;
|
||||
return crossproduct(dimset,0,last+1);
|
||||
}
|
||||
|
||||
|
||||
@ -643,3 +629,25 @@ check_err(const int stat, const int line, const char* file) {
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
findunlimited(Dimset* dimset, int start)
|
||||
{
|
||||
for(;start<dimset->ndims;start++) {
|
||||
if(dimset->dimsyms[start]->dim.isunlimited)
|
||||
return start;
|
||||
}
|
||||
return dimset->ndims;
|
||||
}
|
||||
|
||||
int
|
||||
findlastunlimited(Dimset* dimset)
|
||||
{
|
||||
int i;
|
||||
for(i=dimset->ndims-1;i>=0;i--) {
|
||||
if(dimset->dimsyms[i]->dim.isunlimited)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,8 +42,12 @@ extern char* poolalloc(size_t);
|
||||
extern char* pooldup(char*);
|
||||
extern char* poolcat(const char* s1, const char* s2);
|
||||
|
||||
extern size_t arraylength(Dimset* dimset);
|
||||
extern size_t subarraylength(Dimset* dimset, int start);
|
||||
/* compute the total n-dimensional size as 1 long array;
|
||||
if stop == 0, then stop = dimset->ndims.
|
||||
*/
|
||||
extern size_t crossproduct(Dimset* dimset, int start, int stop);
|
||||
extern int findunlimited(Dimset* dimset, int start);
|
||||
extern int findlastunlimited(Dimset* dimset);
|
||||
|
||||
extern unsigned char* makebytestring(char* s, size_t* lenp);
|
||||
extern int getpadding(int offset, int alignment);
|
||||
|
Loading…
x
Reference in New Issue
Block a user