/* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc. See the COPYRIGHT file for more information. */ /* Parser actions for constraint expressions */ /* Since oc does not use the constraint parser, they functions all just abort if called. */ #include "config.h" #include #include #include #include #include #include "netcdf.h" #include "nclist.h" #include "ncbytes.h" #include "dceconstraints.h" #include "dceparselex.h" static Object collectlist(Object list0, Object decl); void projections(DCEparsestate* state, Object list0) { NClist* list = (NClist*)list0; if(list != NULL) { nclistfree(state->constraint->projections); state->constraint->projections = list; } #ifdef DEBUG fprintf(stderr," ce.projections: %s\n", dcetostring((DCEnode*)state->constraint->projections)); #endif } void selections(DCEparsestate* state, Object list0) { NClist* list = (NClist*)list0; if(list != NULL) { nclistfree(state->constraint->selections); state->constraint->selections = list; } #ifdef DEBUG fprintf(stderr," ce.selections: %s\n", dcetostring((DCEnode*)state->constraint->selections)); #endif } Object projectionlist(DCEparsestate* state, Object list0, Object decl) { return collectlist(list0,decl); } Object projection(DCEparsestate* state, Object varorfcn) { DCEprojection* p = (DCEprojection*)dcecreate(CES_PROJECT); CEsort tag = *(CEsort*)varorfcn; if(tag == CES_FCN) p->fcn = varorfcn; else p->var = varorfcn; p->discrim = tag; #ifdef DEBUG fprintf(stderr," ce.projection: %s\n", dcetostring((DCEnode*)p)); #endif return p; } Object segmentlist(DCEparsestate* state, Object var0, Object decl) { /* watch out: this is non-standard */ NClist* list; DCEvar* v = (DCEvar*)var0; if(v==NULL) v = (DCEvar*)dcecreate(CES_VAR); list = v->segments; if(list == NULL) list = nclistnew(); nclistpush(list,(void*)decl); v->segments = list; return v; } Object segment(DCEparsestate* state, Object name, Object slices0) { size_t i; DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT); NClist* slices = (NClist*)slices0; segment->name = strdup((char*)name); if(slices != NULL && nclistlength(slices) > 0) { segment->rank = nclistlength(slices); segment->slicesdefined = 1; /* but not declsizes */ for(i=0;islices[i] = *slice; free(slice); } nclistfree(slices); } else segment->slicesdefined = 0; #ifdef DEBUG fprintf(stderr," ce.segment: %s\n", dumpsegment(segment)); #endif return segment; } Object rangelist(DCEparsestate* state, Object list0, Object decl) { return collectlist(list0,decl); } Object range(DCEparsestate* state, Object sfirst, Object sstride, Object slast) { DCEslice* slice = (DCEslice*)dcecreate(CES_SLICE); unsigned long first=0,stride=0,last=0; /* Note: that incoming arguments are strings; we must convert to size_t; but we do know they are legal integers or NULL */ if(sscanf((char*)sfirst,"%lu",&first) != 1) /* always defined */ return NULL; if(slast != NULL) { if(sscanf((char*)slast,"%lu",&last) != 1) return NULL; } else last = first; if(sstride != NULL) { if(sscanf((char*)sstride,"%lu",&stride) != 1) return NULL; } else stride = 1; /* default */ if(stride == 0) dceerror(state,"Illegal index for range stride"); if(last < first) dceerror(state,"Illegal index for range last index"); slice->first = first; slice->stride = (stride == 0 ? 1 : stride); slice->last = last; slice->length = (slice->last - slice->first) + 1; slice->count = slice->length / slice->stride; #ifdef DEBUG fprintf(stderr," ce.slice: %s\n", dumpslice(slice)); #endif return slice; } Object range1(DCEparsestate* state, Object rangenumber) { int range = -1; if(sscanf((char*)rangenumber,"%u",&range) != 1) range = -1; if(range < 0) { dceerror(state,"Illegal range index"); } return rangenumber; } Object clauselist(DCEparsestate* state, Object list0, Object decl) { return collectlist(list0,decl); } Object sel_clause(DCEparsestate* state, int selcase, Object lhs, Object relop0, Object values) { DCEselection* sel = (DCEselection*)dcecreate(CES_SELECT); sel->operator = (CEsort)relop0; sel->lhs = (DCEvalue*)lhs; if(selcase == 2) {/*singleton value*/ sel->rhs = nclistnew(); nclistpush(sel->rhs,(void*)values); } else sel->rhs = (NClist*)values; return sel; } Object indexpath(DCEparsestate* state, Object list0, Object index) { return collectlist(list0,index); } Object array_indices(DCEparsestate* state, Object list0, Object indexno) { DCEslice* slice; long long start = -1; NClist* list = (NClist*)list0; if(list == NULL) list = nclistnew(); if(sscanf((char*)indexno,"%lld",&start) != 1) start = -1; if(start < 0) { dceerror(state,"Illegal array index"); start = 1; } slice = (DCEslice*)dcecreate(CES_SLICE); slice->first = start; slice->stride = 1; slice->length = 1; slice->last = start; slice->count = 1; nclistpush(list,(void*)slice); return list; } Object indexer(DCEparsestate* state, Object name, Object indices) { size_t i; NClist* list = (NClist*)indices; DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT); seg->name = strdup((char*)name); for(i=0;islices[i] = *slice; free(slice); } nclistfree(indices); return seg; } Object function(DCEparsestate* state, Object fcnname, Object args) { DCEfcn* fcn = (DCEfcn*)dcecreate(CES_FCN); fcn->name = nulldup((char*)fcnname); fcn->args = args; return fcn; } Object arg_list(DCEparsestate* state, Object list0, Object decl) { return collectlist(list0,decl); } Object value_list(DCEparsestate* state, Object list0, Object decl) { return collectlist(list0,decl); } Object value(DCEparsestate* state, Object val) { DCEvalue* ncvalue = (DCEvalue*)dcecreate(CES_VALUE); CEsort tag = *(CEsort*)val; switch (tag) { case CES_VAR: ncvalue->var = (DCEvar*)val; break; case CES_FCN: ncvalue->fcn = (DCEfcn*)val; break; case CES_CONST: ncvalue->constant = (DCEconstant*)val; break; default: abort(); break; } ncvalue->discrim = tag; return ncvalue; } Object var(DCEparsestate* state, Object indexpath) { DCEvar* v = (DCEvar*)dcecreate(CES_VAR); v->segments = (NClist*)indexpath; return v; } Object constant(DCEparsestate* state, Object val, int tag) { DCEconstant* con = (DCEconstant*)dcecreate(CES_CONST); char* text = (char*)val; char* endpoint = NULL; switch (tag) { case SCAN_STRINGCONST: con->discrim = CES_STR; con->text = nulldup(text); break; case SCAN_NUMBERCONST: con->intvalue = strtoll(text,&endpoint,10); if(*text != '\0' && *endpoint == '\0') { con->discrim = CES_INT; } else { con->floatvalue = strtod(text,&endpoint); if(*text != '\0' && *endpoint == '\0') con->discrim = CES_FLOAT; else abort(); } break; default: abort(); break; } return con; } static Object collectlist(Object list0, Object decl) { NClist* list = (NClist*)list0; if(list == NULL) list = nclistnew(); nclistpush(list,(void*)decl); return list; } Object makeselectiontag(CEsort tag) { return (Object) tag; } int dceerror(DCEparsestate* state, char* msg) { strncpy(state->errorbuf,msg,1023); state->errorcode=NC_EDAPCONSTRAINT; return 0; } static void dce_parse_cleanup(DCEparsestate* state) { if(state == NULL) return; dcelexcleanup(&state->lexstate); /* will free */ /* Free up the state */ free(state); } static DCEparsestate* ce_parse_init(char* input, DCEconstraint* constraint) { DCEparsestate* state = (DCEparsestate*)calloc(1,sizeof(DCEparsestate));; if(state==NULL) return (DCEparsestate*)NULL; if(input==NULL) { dceerror(state,"ce_parse_init: no input buffer"); } else { state->errorbuf[0] = '\0'; state->errorcode = 0; dcelexinit(input,&state->lexstate); state->constraint = constraint; } return state; } #ifdef PARSEDEBUG extern int dcedebug; #endif /* Wrapper for ceparse */ int dapceparse(char* input, DCEconstraint* constraint, char** errmsgp) { DCEparsestate* state; int errcode = 0; #ifdef PARSEDEBUG dcedebug = 1; #endif if(input != NULL) { #ifdef DEBUG fprintf(stderr,"dceeparse: input=%s\n",input); #endif state = ce_parse_init(input,constraint); if(dceparse(state) == 0) { #ifdef DEBUG if(nclistlength(constraint->projections) > 0) fprintf(stderr,"dceeparse: projections=%s\n", dcetostring((DCEnode*)constraint->projections)); #endif #ifdef DEBUG if(nclistlength(constraint->selections) > 0) fprintf(stderr,"dceeparse: selections=%s\n", dumpselections(constraint->selections)); #endif } else { if(errmsgp) *errmsgp = nulldup(state->errorbuf); } errcode = state->errorcode; dce_parse_cleanup(state); } return errcode; } #ifdef PARSEDEBUG Object debugobject(Object o) { return o; } #endif