Commit 94522eb0 authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

Expr: added support for temporary variables (starting with underscore)

parent 5247b989
......@@ -41,27 +41,58 @@ Constansts: M_PI, M_E
#include "expr.h"
void *Expr(void *argument)
static
char *exprs_from_arg(const char *arg)
{
char *exprs = NULL;
size_t slen = strlen(arg);
exprs = (char*) Malloc(slen+2);
strcpy(exprs, operatorArgv()[0]);
if ( exprs[slen-1] != ';' )
{
exprs[slen] = ';';
exprs[slen+1] = 0;
}
return exprs;
}
static
char *exprs_from_file(const char *exprf)
{
char *exprs = NULL;
const char *exprf = NULL;
int offset;
int nrecs, nvars;
int gridID, zaxisID;
int recID, varID, levelID;
int vlistID2;
int gridsize;
int nlevel;
int nmiss;
//int lwarn = TRUE;
double missval;
double *single1, *single2;
/* Open expr script file for reading */
FILE *fp = fopen(exprf, "r");
if( fp == NULL ) cdoAbort("Open failed on %s", exprf);
struct stat filestat;
if ( stat(exprf, &filestat) != 0 ) cdoAbort("Stat failed on %s", exprf);
size_t fsize = (size_t) filestat.st_size;
exprs = (char*) Malloc(fsize+1);
int ichar, ipos = 0;
while ( (ichar = fgetc(fp)) != EOF ) exprs[ipos++] = ichar;
exprs[ipos] = 0;
if ( ipos == 0 ) cdoAbort("%s is empty!", exprf);
fclose(fp);
return exprs;
}
void *Expr(void *argument)
{
cdoInitialize(argument);
parse_parm_t parse_arg;
void *scanner;
int yy_scan_string(const char *str, void *scanner);
cdoInitialize(argument);
yylex_init(&scanner);
yyset_extra(&parse_arg, scanner);
......@@ -78,49 +109,21 @@ void *Expr(void *argument)
operatorInputArg(cdoOperatorEnter(operatorID));
char *exprs = NULL;
if ( READS_COMMAND_LINE(operatorID) )
{
size_t slen = strlen(operatorArgv()[0]);
exprs = (char*) Malloc(slen+2);
strcpy(exprs, operatorArgv()[0]);
if ( exprs[slen-1] != ';' )
{
exprs[slen] = ';';
exprs[slen+1] = 0;
}
}
exprs = exprs_from_arg(operatorArgv()[0]);
else
{
exprf = operatorArgv()[0];
/* Open script file for reading */
FILE *fp = fopen(exprf, "r");
if( fp == NULL ) cdoAbort("Open failed on %s", exprf);
struct stat filestat;
if ( stat(exprf, &filestat) != 0 ) cdoAbort("Stat failed on %s", exprf);
size_t fsize = (size_t) filestat.st_size;
exprs = (char*) Malloc(fsize+1);
int ichar, ipos = 0;
while ( (ichar = fgetc(fp)) != EOF ) exprs[ipos++] = ichar;
exprs[ipos] = 0;
if ( ipos == 0 ) cdoAbort("%s is empty!", exprf);
fclose(fp);
}
exprs = exprs_from_file(operatorArgv()[0]);
if ( cdoVerbose ) cdoPrint(exprs);
int streamID1 = streamOpenRead(cdoStreamName(0));
int vlistID1 = streamInqVlist(streamID1);
int nvars1 = vlistNvars(vlistID1);
int vlistID2 = -1;
int nvars = 0;
if ( REPLACES_VARIABLES(operatorID) )
{
vlistID2 = vlistCreate();
......@@ -132,9 +135,12 @@ void *Expr(void *argument)
nvars = nvars1;
}
int vlisttmp = vlistCreate();
parse_arg.init = 1;
parse_arg.vlistID1 = vlistID1;
parse_arg.vlistID2 = vlistID2;
parse_arg.vlisttmp = vlisttmp;
parse_arg.nvars1 = 0;
parse_arg.debug = 0;
if ( cdoVerbose ) parse_arg.debug = 1;
......@@ -143,7 +149,7 @@ void *Expr(void *argument)
parse_arg.tsteptype2 = -1;
/* Set all input variables to 'needed' if replacing is switched off */
for ( varID = 0; varID < nvars1; varID++ )
for ( int varID = 0; varID < nvars1; varID++ )
parse_arg.var_needed[varID] = ! REPLACES_VARIABLES(operatorID);
yy_scan_string(exprs, scanner);
......@@ -157,7 +163,7 @@ void *Expr(void *argument)
if ( cdoVerbose ) vlistPrint(vlistID2);
if ( cdoVerbose )
for ( varID = 0; varID < nvars1; varID++ )
for ( int varID = 0; varID < nvars1; varID++ )
if ( parse_arg.var_needed[varID] )
printf("Needed var: %d %s\n", varID, parse_arg.var[varID]);
......@@ -172,38 +178,39 @@ void *Expr(void *argument)
parse_arg.vardata1 = (double**) Malloc(nvars1*sizeof(double*));
parse_arg.vardata2 = (double**) Malloc(nvars2*sizeof(double*));
for ( varID = 0; varID < nvars1; varID++ )
for ( int varID = 0; varID < nvars1; varID++ )
{
gridID = vlistInqVarGrid(vlistID1, varID);
zaxisID = vlistInqVarZaxis(vlistID1, varID);
int gridID = vlistInqVarGrid(vlistID1, varID);
int zaxisID = vlistInqVarZaxis(vlistID1, varID);
/* parse_arg.missval[varID] = vlistInqVarMissval(vlistID1, varID); */
gridsize = gridInqSize(gridID);
nlevel = zaxisInqSize(zaxisID);
int gridsize = gridInqSize(gridID);
int nlevel = zaxisInqSize(zaxisID);
if ( parse_arg.var_needed[varID] )
parse_arg.vardata1[varID] = (double*) Malloc(gridsize*nlevel*sizeof(double));
else
parse_arg.vardata1[varID] = NULL;
}
for ( varID = 0; varID < nvars; varID++ )
for ( int varID = 0; varID < nvars; varID++ )
{
parse_arg.vardata2[varID] = parse_arg.vardata1[varID];
}
for ( varID = nvars; varID < nvars2; varID++ )
for ( int varID = nvars; varID < nvars2; varID++ )
{
gridID = vlistInqVarGrid(vlistID2, varID);
zaxisID = vlistInqVarZaxis(vlistID2, varID);
int gridID = vlistInqVarGrid(vlistID2, varID);
int zaxisID = vlistInqVarZaxis(vlistID2, varID);
gridsize = gridInqSize(gridID);
nlevel = zaxisInqSize(zaxisID);
int gridsize = gridInqSize(gridID);
int nlevel = zaxisInqSize(zaxisID);
parse_arg.vardata2[varID] = (double*) Malloc(gridsize*nlevel*sizeof(double));
}
gridsize = vlistGridsizeMax(vlistID1);
int gridsize = vlistGridsizeMax(vlistID1);
double *array = (double*) Malloc(gridsize*sizeof(double));
int nrecs;
int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
......@@ -211,34 +218,29 @@ void *Expr(void *argument)
streamDefTimestep(streamID2, tsID);
for ( varID = 0; varID < nvars1; varID++ ) parse_arg.nmiss[varID] = 0;
for ( int varID = 0; varID < nvars1; varID++ ) parse_arg.nmiss[varID] = 0;
for ( recID = 0; recID < nrecs; recID++ )
for ( int recID = 0; recID < nrecs; recID++ )
{
int varID, levelID;
streamInqRecord(streamID1, &varID, &levelID);
if ( parse_arg.var_needed[varID] )
{
gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
offset = gridsize*levelID;
single1 = parse_arg.vardata1[varID] + offset;
streamReadRecord(streamID1, single1, &nmiss);
int gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
int offset = gridsize*levelID;
int nmiss;
double *vardata = parse_arg.vardata1[varID] + offset;
streamReadRecord(streamID1, vardata, &nmiss);
parse_arg.nmiss[varID] += nmiss;
/*
if ( nmiss && lwarn )
{
cdoWarning("Missing values unsupported for this operator!");
lwarn = FALSE;
}
*/
}
}
for ( varID = nvars; varID < nvars2; varID++ )
for ( int varID = nvars; varID < nvars2; varID++ )
{
gridID = vlistInqVarGrid(vlistID2, varID);
zaxisID = vlistInqVarZaxis(vlistID2, varID);
gridsize = gridInqSize(gridID);
nlevel = zaxisInqSize(zaxisID);
int gridID = vlistInqVarGrid(vlistID2, varID);
int zaxisID = vlistInqVarZaxis(vlistID2, varID);
int gridsize = gridInqSize(gridID);
int nlevel = zaxisInqSize(zaxisID);
memset(parse_arg.vardata2[varID], 0, gridsize*nlevel*sizeof(double));
}
......@@ -246,26 +248,25 @@ void *Expr(void *argument)
yy_scan_string(exprs, scanner);
yyparse(&parse_arg, scanner);
for ( varID = 0; varID < nvars2; varID++ )
for ( int varID = 0; varID < nvars2; varID++ )
{
gridID = vlistInqVarGrid(vlistID2, varID);
zaxisID = vlistInqVarZaxis(vlistID2, varID);
missval = vlistInqVarMissval(vlistID2, varID);
int gridID = vlistInqVarGrid(vlistID2, varID);
int zaxisID = vlistInqVarZaxis(vlistID2, varID);
double missval = vlistInqVarMissval(vlistID2, varID);
gridsize = gridInqSize(gridID);
nlevel = zaxisInqSize(zaxisID);
for ( levelID = 0; levelID < nlevel; levelID++ )
int gridsize = gridInqSize(gridID);
int nlevel = zaxisInqSize(zaxisID);
for ( int levelID = 0; levelID < nlevel; levelID++ )
{
long i;
offset = gridsize*levelID;
single2 = parse_arg.vardata2[varID] + offset;
int offset = gridsize*levelID;
double *vardata = parse_arg.vardata2[varID] + offset;
nmiss = 0;
for ( i = 0; i < gridsize; i++ )
if ( DBL_IS_EQUAL(single2[i], missval) ) nmiss++;
int nmiss = 0;
for ( int i = 0; i < gridsize; i++ )
if ( DBL_IS_EQUAL(vardata[i], missval) ) nmiss++;
streamDefRecord(streamID2, varID, levelID);
streamWriteRecord(streamID2, single2, nmiss);
streamWriteRecord(streamID2, vardata, nmiss);
}
}
......
......@@ -943,22 +943,32 @@ nodeType *expr_run(nodeType *p, parse_parm_t *parse_arg)
vlistID = parse_arg->vlistID1;
int nvars = vlistNvars(vlistID);
for ( varID = 0; varID < nvars; varID++ )
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(vlistID, varID, varname);
if ( strcmp(varname, p->u.var.nm) == 0 ) break;
}
if ( varID == nvars )
if ( varID < 0 )
{
vlistID = parse_arg->vlistID2;
nvars = vlistNvars(vlistID);
for ( varID = 0; varID < nvars; varID++ )
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(vlistID, varID, varname);
if ( strcmp(varname, p->u.var.nm) == 0 ) break;
}
if ( varID < 0 )
{
vlistID = parse_arg->vlisttmp;
nvars = vlistNvars(vlistID);
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(vlistID, varID, varname);
if ( strcmp(varname, p->u.var.nm) == 0 ) break;
}
}
}
if ( varID == nvars )
if ( varID == -1 )
{
cdoAbort("Variable >%s< not found!", p->u.var.nm);
}
......@@ -1050,31 +1060,57 @@ nodeType *expr_run(nodeType *p, parse_parm_t *parse_arg)
if ( parse_arg->gridID2 == -1 || parse_arg->zaxisID2 == -1 || parse_arg->tsteptype2 == -1 )
cdoAbort("Operand not variable!");
varID = vlistDefVar(parse_arg->vlistID2, parse_arg->gridID2, parse_arg->zaxisID2, parse_arg->tsteptype2);
const char *varname = p->u.opr.op[0]->u.var.nm;
vlistDefVarName(parse_arg->vlistID2, varID, varname);
vlistDefVarMissval(parse_arg->vlistID2, varID, parse_arg->missval2);
if ( memcmp(varname, "var", 3) == 0 )
{
if ( strlen(varname) > 3 && isdigit(varname[3]) )
{
int code = atoi(varname+3);
vlistDefVarCode(parse_arg->vlistID2, varID, code);
}
}
const char *varname2 = p->u.opr.op[0]->u.var.nm;
int vlistID2 = parse_arg->vlistID2;
if ( *varname2 == '_' ) vlistID2 = parse_arg->vlisttmp;
int nvars = vlistNvars(vlistID2);
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(vlistID2, varID, varname);
if ( strcmp(varname, varname2) == 0 ) break;
}
if ( varID >= 0 )
{
cdoWarning("Variable %s already defined!", varname2);
}
else
{
varID = vlistDefVar(vlistID2, parse_arg->gridID2, parse_arg->zaxisID2, parse_arg->tsteptype2);
vlistDefVarName(vlistID2, varID, varname2);
vlistDefVarMissval(vlistID2, varID, parse_arg->missval2);
if ( memcmp(varname2, "var", 3) == 0 )
{
if ( strlen(varname2) > 3 && isdigit(varname2[3]) )
{
int code = atoi(varname2+3);
vlistDefVarCode(vlistID2, varID, code);
}
}
}
}
else
{
if ( parse_arg->debug )
printf("\tpop var\t%s\t%s\n", p->u.opr.op[0]->u.var.nm, rnode->u.var.nm);
int nvars = vlistNvars(parse_arg->vlistID2);
for ( varID = nvars-1; varID >= 0; varID-- )
int vlistID2 = parse_arg->vlistID2;
int nvars = vlistNvars(vlistID2);
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(parse_arg->vlistID2, varID, varname);
vlistInqVarName(vlistID2, varID, varname);
if ( strcmp(varname, p->u.opr.op[0]->u.var.nm) == 0 ) break;
}
if ( varID < 0 )
{
int vlistID2 = parse_arg->vlisttmp;
int nvars = vlistNvars(vlistID2);
for ( varID = nvars-1; varID >= 0; --varID )
{
vlistInqVarName(vlistID2, varID, varname);
if ( strcmp(varname, p->u.opr.op[0]->u.var.nm) == 0 ) break;
}
}
if ( varID < 0 )
{
cdoAbort("Variable >%s< not found!", p->u.opr.op[0]->u.var.nm);
......
......@@ -12,27 +12,27 @@ int fileno(FILE *stream);
typedef enum { typeCon, typeVar, typeFun, typeOpr } nodeEnum;
/* constants */
// constants
typedef struct {
double value; /* value of constant */
double value; // value of constant
} conNodeType;
/* variables */
// variables
typedef struct {
char *nm; /* variable name */
char *nm; // variable name
} varNodeType;
/* functions */
// functions
typedef struct {
char *name; /* function name */
struct nodeTypeTag *op; /* operand */
char *name; // function name
struct nodeTypeTag *op; // operand
} funNodeType;
/* operators */
// operators
typedef struct {
int oper; /* operator */
int nops; /* number of operands */
struct nodeTypeTag *op[1]; /* operands (expandable) */
int oper; // operator
int nops; // number of operands
struct nodeTypeTag *op[1]; // operands (expandable)
} oprNodeType;
typedef struct nodeTypeTag {
......@@ -41,22 +41,22 @@ typedef struct nodeTypeTag {
int nmiss;
double missval;
double *data;
nodeEnum type; /* type of node */
nodeEnum type; // type of node
/* union must be last entry in nodeType */
/* because operNodeType may dynamically increase */
// union must be last entry in nodeType
// because operNodeType may dynamically increase
union {
conNodeType con; /* constants */
varNodeType var; /* variables */
funNodeType fun; /* functions */
oprNodeType opr; /* operators */
conNodeType con; // constants
varNodeType var; // variables
funNodeType fun; // functions
oprNodeType opr; // operators
} u;
} nodeType;
#define MAX_VARS 1024
typedef struct{ /* prs_sct */
int vlistID1, vlistID2;
typedef struct {
int vlistID1, vlistID2, vlisttmp;
int nvars1, nvars2;
int nmiss[MAX_VARS];
int varID[MAX_VARS];
......@@ -73,10 +73,10 @@ typedef struct{ /* prs_sct */
typedef union{
double cvalue; /* constant value */
char *varnm; /* variable name */
char *fname; /* function name */
nodeType *nPtr; /* node pointer */
double cvalue; // constant value
char *varnm; // variable name
char *fname; // function name
nodeType *nPtr; // node pointer
} stype_t;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment