/* convert all names in selections to be fully qualified */ static NCerror qualifyselectionnames3(DCEselection* sel) { NCerror ncstat = NC_NOERR; int i; NClist* segments = NULL; NClist* fullpath = nclistnew(); ASSERT(sel->lhs->discrim == CES_VAR); collectnodepath3((CDFnode*)sel->lhs->var->annotation,fullpath,!WITHDATASET); #ifdef DEBUG fprintf(stderr,"qualify.sel: %s -> ", dumpselection(sel)); #endif /* Now add path nodes to create full path */ completesegments3(fullpath,sel->lhs->var->segments); for(i=0;i<nclistlength(sel->rhs);i++) { DCEvalue* value = (DCEvalue*)nclistget(sel->rhs,i); if(value->discrim != CES_VAR) continue; nclistclear(fullpath); collectnodepath3((CDFnode*)value->var->annotation,fullpath,!WITHDATASET); completesegments3(fullpath,value->var->segments); } nclistfree(segments); nclistfree(fullpath); return THROW(ncstat); }
/* Suppress variables not in usable sequences*/ NCerror suppressunusablevars3(NCDAPCOMMON* dapcomm) { int i,j; int found = 1; NClist* path = nclistnew(); while(found) { found = 0; /* Walk backwards to aid removal semantics */ for(i=nclistlength(dapcomm->cdf.ddsroot->tree->varnodes)-1;i>=0;i--) { CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.ddsroot->tree->varnodes,i); /* See if this var is under an unusable sequence */ nclistclear(path); collectnodepath3(var,path,WITHOUTDATASET); for(j=0;j<nclistlength(path);j++) { CDFnode* node = (CDFnode*)nclistget(path,j); if(node->nctype == NC_Sequence && !node->usesequence) { #ifdef DEBUG fprintf(stderr,"suppressing var in unusable sequence: %s.%s\n",node->ncfullname,var->ncbasename); #endif found = 1; break; } } if(found) break; } if(found) nclistremove(dapcomm->cdf.ddsroot->tree->varnodes,i); } nclistfree(path); return NC_NOERR; }
NCerror freeNCDAPCOMMON(NCDAPCOMMON* dapcomm) { /* abort the metadata file */ (void)nc_abort(getncid(dapcomm)); freenccache(dapcomm,dapcomm->cdf.cache); nclistfree(dapcomm->cdf.projectedvars); nullfree(dapcomm->cdf.recorddimname); /* free the trees */ freecdfroot34(dapcomm->cdf.ddsroot); dapcomm->cdf.ddsroot = NULL; freecdfroot34(dapcomm->cdf.fullddsroot); dapcomm->cdf.fullddsroot = NULL; if(dapcomm->oc.ocdasroot != NULL) oc_root_free(dapcomm->oc.conn,dapcomm->oc.ocdasroot); dapcomm->oc.ocdasroot = NULL; oc_close(dapcomm->oc.conn); /* also reclaims remaining OC trees */ ncurifree(dapcomm->oc.url); nullfree(dapcomm->oc.urltext); nullfree(dapcomm->oc.rawurltext); dcefree((DCEnode*)dapcomm->oc.dapconstraint); dapcomm->oc.dapconstraint = NULL; free(dapcomm); return NC_NOERR; }
/* Accumulate useful node sets */ NCerror computecdfnodesets3(NCDAPCOMMON* nccomm, CDFtree* tree) { unsigned int i; NClist* varnodes; NClist* allnodes; allnodes = tree->nodes; varnodes = nclistnew(); if(tree->seqnodes == NULL) tree->seqnodes = nclistnew(); if(tree->gridnodes == NULL) tree->gridnodes = nclistnew(); nclistclear(tree->seqnodes); nclistclear(tree->gridnodes); computevarnodes3(nccomm,allnodes,varnodes); nclistfree(tree->varnodes); tree->varnodes = varnodes; varnodes = NULL; /* Now compute other sets of interest */ for(i=0;i<nclistlength(allnodes);i++) { CDFnode* node = (CDFnode*)nclistget(allnodes,i); switch (node->nctype) { case NC_Sequence: nclistpush(tree->seqnodes,(void*)node); break; case NC_Grid: nclistpush(tree->gridnodes,(void*)node); break; default: break; } } return NC_NOERR; }
static NCerror moveto(NCDAPCOMMON* nccomm, Getvara* xgetvar, CDFnode* xrootnode, void* memory) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = nccomm->oc.conn; OCdatanode xrootcontent; OCddsnode ocroot; NClist* path = nclistnew(); struct NCMEMORY memstate; memstate.next = (memstate.memory = memory); /* Get the root content*/ ocroot = xrootnode->tree->ocroot; ocstat = oc_data_getroot(conn,ocroot,&xrootcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} /* Remember: xgetvar->target is in DATADDS tree */ collectnodepath3(xgetvar->target,path,WITHDATASET); ncstat = movetor(nccomm,xrootcontent, path,0,xgetvar,0,&memstate, xgetvar->varaprojection->var->segments); done: nclistfree(path); oc_data_free(conn,xrootcontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
/* Compute the set of variables referenced in the projections of the input constraint. */ NCerror computeprojectedvars(NCDAPCOMMON* dapcomm, DCEconstraint* constraint) { NCerror ncstat = NC_NOERR; NClist* vars = NULL; int i; vars = nclistnew(); if(dapcomm->cdf.projectedvars != NULL) nclistfree(dapcomm->cdf.projectedvars); dapcomm->cdf.projectedvars = vars; if(constraint == NULL || constraint->projections == NULL) goto done; for(i=0;i<nclistlength(constraint->projections);i++) { CDFnode* node; DCEprojection* proj = (DCEprojection*)nclistget(constraint->projections,i); if(proj->discrim == CES_FCN) continue; /* ignore these */ node = (CDFnode*)proj->var->annotation; if(!nclistcontains(vars,(void*)node)) { nclistpush(vars,(void*)node); } } done: return ncstat; }
static char* getdefinename(CDFnode* node) { char* spath = NULL; NClist* path = NULL; switch (node->nctype) { case NC_Primitive: /* The define name is same as the fullname with elided nodes */ path = nclistnew(); collectnodepath3(node,path,!WITHDATASET); spath = makepathstring3(path,".",PATHNC|PATHELIDE); nclistfree(path); break; case NC_Dimension: /* Return just the node's ncname */ spath = nulldup(node->ncbasename); break; default: PANIC("unexpected nctype"); } return spath; }
static NCerror fillsegmentpath(DCEprojection* p, NClist* nodes) { int i; NCerror ncstat = NC_NOERR; NClist* path = nclistnew(); ASSERT(p->discrim == CES_VAR); collectsegmentnames3(p->var->segments,path); ncstat = matchpartialname3(nodes,path,&p->var->cdfleaf); if(ncstat) goto done; /* Now complete the segment path */ nclistclear(path); collectnodepath3(p->var->cdfleaf,path,!WITHDATASET); if(nclistlength(path) != nclistlength(p->var->segments)) { ncstat = NC_EINVAL; goto done; } for(i=0;i<nclistlength(p->var->segments);i++) { DCEsegment* seg = (DCEsegment*)nclistget(p->var->segments,i); CDFnode* node = (CDFnode*)nclistget(path,i); seg->cdfnode = node; #ifdef DEBUG fprintf(stderr,"reref: %s -> %s\n",seg->name,node->name); #endif } done: nclistfree(path); return ncstat; }
/* Given the arguments to vara construct a corresponding projection with any pseudo dimensions removed */ NCerror buildvaraprojection3(Getvara* getvar, const size_t* startp, const size_t* countp, const ptrdiff_t* stridep, DCEprojection** projectionp) { int i,j; NCerror ncstat = NC_NOERR; CDFnode* var = getvar->target; DCEprojection* projection = NULL; NClist* path = nclistnew(); NClist* segments = NULL; int dimindex; ncstat = dapvar2projection(var,&projection); #ifdef DEBUG fprintf(stderr,"buildvaraprojection: %s\n",dumpprojection(projection)); #endif /* We need to assign the start/count/stride info to each segment; declsize will have been set */ segments = projection->var->segments; dimindex = 0; for(i=0;i<nclistlength(segments);i++) { DCEsegment* segment = (DCEsegment*)nclistget(segments,i); for(j=0;j<segment->rank;j++) { DCEslice* slice = &segment->slices[j]; /* make each slice represent the corresponding start/count/stride */ slice->first = startp[dimindex+j]; slice->stride = stridep[dimindex+j]; slice->count = countp[dimindex+j]; slice->length = slice->count * slice->stride; if(slice->length > slice->declsize) slice->length = slice->declsize; slice->stop = (slice->first + slice->length); if(slice->stop > slice->declsize) slice->stop = slice->declsize; } dimindex += segment->rank; } #ifdef DEBUG fprintf(stderr,"buildvaraprojection.final: %s\n",dumpprojection(projection)); #endif #ifdef IGNORE removepseudodims3(projection); #endif #ifdef DEBUG fprintf(stderr,"buildvaraprojection3: projection=%s\n", dumpprojection(projection)); #endif if(projectionp) *projectionp = projection; nclistfree(path); if(ncstat) dcefree((DCEnode*)projection); return ncstat; }
/* Convert a CDFnode var to a projection; include pseudodimensions; always whole variable. */ int dapvar2projection(CDFnode* var, DCEprojection** projectionp) { int i,j; int ncstat = NC_NOERR; NClist* path = nclistnew(); NClist* segments; DCEprojection* projection = NULL; int dimindex; /* Collect the nodes needed to construct the projection segment */ collectnodepath3(var,path,!WITHDATASET); segments = nclistnew(); dimindex = 0; /* point to next subset of slices */ nclistsetalloc(segments,nclistlength(path)); for(i=0;i<nclistlength(path);i++) { DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT); CDFnode* n = (CDFnode*)nclistget(path,i); int localrank; NClist* dimset; segment->annotation = (void*)n; segment->name = nulldup(n->ocname); /* We need to assign whole slices to each segment */ localrank = nclistlength(n->array.dimsetplus); segment->rank = localrank; dimset = n->array.dimsetplus; for(j=0;j<localrank;j++) { DCEslice* slice; CDFnode* dim; slice = &segment->slices[j]; dim = (CDFnode*)nclistget(dimset,j); ASSERT(dim->dim.declsize0 > 0); dcemakewholeslice(slice,dim->dim.declsize0); } segment->slicesdefined = 1; segment->slicesdeclized = 1; dimindex += localrank; nclistpush(segments,(ncelem)segment); } projection = (DCEprojection*)dcecreate(CES_PROJECT); projection->discrim = CES_VAR; projection->var = (DCEvar*)dcecreate(CES_VAR); projection->var->annotation = (void*)var; projection->var->segments = segments; #ifdef DEBUG1 fprintf(stderr,"dapvar2projection: projection=%s\n", dumpprojection(projection)); #endif nclistfree(path); if(ncstat) dcefree((DCEnode*)projection); else if(projectionp) *projectionp = projection; return ncstat; }
/* Extract data for a netcdf variable that has a string dimension. */ static int extractstring( NCDAPCOMMON* nccomm, Getvara* xgetvar, CDFnode* xnode, DCEsegment* segment, size_t dimindex, /*notused*/ OClink conn, OCdatanode currentcontent, struct NCMEMORY* memory ) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; int i; size_t rank0; NClist* strings = NULL; Dapodometer* odom = NULL; ASSERT(xnode->etype == NC_STRING || xnode->etype == NC_URL); /* Compute rank minus string dimension */ rank0 = nclistlength(xnode->array.dimset0); /* keep whole extracted strings stored in an NClist */ strings = nclistnew(); if(rank0 == 0) {/*=> scalar*/ char* value = NULL; ocstat = oc_data_readscalar(conn,currentcontent,sizeof(value),&value); if(ocstat != OC_NOERR) goto done; nclistpush(strings,(void*)value); } else { /* Use the odometer to walk to the appropriate fields*/ odom = dapodom_fromsegment(segment,0,rank0); while(dapodom_more(odom)) { char* value = NULL; ocstat = oc_data_readn(conn,currentcontent,odom->index,1,sizeof(value),&value); if(ocstat != OC_NOERR) goto done; nclistpush(strings,(void*)value); dapodom_next(odom); } dapodom_free(odom); } /* Get each string in turn, slice it by applying the string dimm and store in user supplied memory */ for(i=0;i<nclistlength(strings);i++) { char* s = (char*)nclistget(strings,i); slicestring(conn,s,&segment->slices[rank0],memory); free(s); } nclistfree(strings); done: if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
/* Free up a single node, but not any nodes it points to. */ static void free1cdfnode(CDFnode* node) { unsigned int j,k; if(node == NULL) return; nullfree(node->ocname); nullfree(node->ncbasename); nullfree(node->ncfullname); if(node->attributes != NULL) { for(j=0;j<nclistlength(node->attributes);j++) { NCattribute* att = (NCattribute*)nclistget(node->attributes,j); nullfree(att->name); for(k=0;k<nclistlength(att->values);k++) nullfree((char*)nclistget(att->values,k)); nclistfree(att->values); nullfree(att); } } nullfree(node->dodsspecial.dimname); nclistfree(node->subnodes); nclistfree(node->attributes); nclistfree(node->array.dimsetplus); nclistfree(node->array.dimsetall); nclistfree(node->array.dimset0); nclistfree(node->array.dimsettrans); /* Clean up the ncdap4 fields also */ nullfree(node->typename); nullfree(node->vlenname); nullfree(node); }
static void nc_urlparamfree(NClist* params) { int i,j; NClist* values; if(params == NULL) return; for(i=0;i<nclistlength(params);i+=2) { char* s = (char*)nclistget(params,i); if(s != NULL) free((void*)s); values = (NClist*)nclistget(params,i+1); for(j=0;j<nclistlength(values);j++) { s = (char*)nclistget(values,j); if(s != NULL) free((void*)s); } nclistfree(values); } nclistfree(params); }
/* convert path to string using the ncname field */ char* makecdfpathstring(CDFnode* var, const char* separator) { char* spath; NClist* path = nclistnew(); collectnodepath(var,path,WITHDATASET); /* <= note */ spath = makepathstring(path,separator,PATHNC); nclistfree(path); return spath; }
void freenccachenode(NCDAPCOMMON* nccomm, NCcachenode* node) { if(node == NULL) return; oc_data_free(nccomm->oc.conn,node->content); oc_data_free(nccomm->oc.conn,node->content); freencconstraint(node->constraint); freecdfroot34(node->datadds); nclistfree(node->vars); efree(node); }
void dcefreelist(NClist* list) { int i; if(list == NULL) return; for(i=0;i<nclistlength(list);i++) { DCEnode* node = (DCEnode*)nclistget(list,i); dcefree((DCEnode*)node); } nclistfree(list); }
void freenccache(NCDAPCOMMON* nccomm, NCcache* cache) { int i; if(cache == NULL) return; freenccachenode(nccomm,cache->prefetch); for(i=0;i<nclistlength(cache->nodes);i++) { freenccachenode(nccomm,(NCcachenode*)nclistget(cache->nodes,i)); } nclistfree(cache->nodes); nullfree(cache); }
static void freestringlist(NClist* list) { if(list != NULL) { int i; for(i=0;i<nclistlength(list);i++) { void* p = nclistget(list,i); nullfree(p); } nclistfree(list); } }
/* Given two projection lists, merge src into dst taking overlapping projections into acct. Assume that name qualification has occured. Dst will be modified. */ NCerror mergeprojections3(NClist* dst, NClist* src) { int i; NClist* cat = nclistnew(); NCerror ncstat = NC_NOERR; #ifdef DEBUG fprintf(stderr,"mergeprojection: dst = %s\n",dumpprojections(dst)); fprintf(stderr,"mergeprojection: src = %s\n",dumpprojections(src)); #endif ASSERT(dst != NULL); /* get dst concat clone(src) */ nclistsetalloc(cat,nclistlength(dst)+nclistlength(src)); for(i=0;i<nclistlength(dst);i++) { DCEprojection* p = (DCEprojection*)nclistget(dst,i); nclistpush(cat,(ncelem)p); } if(src != NULL) for(i=0;i<nclistlength(src);i++) { DCEprojection* p = (DCEprojection*)nclistget(src,i); nclistpush(cat,(ncelem)dceclone((DCEnode*)p)); } nclistclear(dst); /* Repeatedly pull elements from the concat, merge with all duplicates, and stick into the dst */ while(nclistlength(cat) > 0) { DCEprojection* target = (DCEprojection*)nclistremove(cat,0); if(target == NULL) continue; if(target->discrim != CES_VAR) continue; for(i=0;i<nclistlength(cat);i++) { DCEprojection* p2 = (DCEprojection*)nclistget(cat,i); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; if(target->var->cdfleaf != p2->var->cdfleaf) continue; /* This entry matches our current target; merge */ ncstat = mergeprojection31(target,p2); /* null out this merged entry and release it */ nclistset(cat,i,(ncelem)NULL); dcefree((DCEnode*)p2); } /* Capture the clone */ nclistpush(dst,(ncelem)target); } nclistfree(cat); return ncstat; }
void freenccachenode(NCDAPCOMMON* nccomm, NCcachenode* node) { if(node == NULL) return; oc_data_free(nccomm->oc.conn,node->content); #ifdef IGNORE oc_root_free(nccomm->oc.conn,node->ocroot); #endif dcefree((DCEnode*)node->constraint); freecdfroot34(node->datadds); nclistfree(node->vars); nullfree(node); }
int nchashfree(NChashmap* hm) { if(hm) { int i; for(i=0;i<hm->alloc;i++) { if(hm->table[i] != NULL) nclistfree(hm->table[i]); } free(hm->table); free(hm); } return TRUE; }
static void projections(CCEparsestate* 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", ccetostring((CCEnode*)state->constraint)); #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 }
int dcemergeprojectionlists(NClist* dst, NClist* src) { int i; NClist* cat = nclistnew(); int ncstat = NC_NOERR; #ifdef DEBUG fprintf(stderr,"dapmergeprojection: dst = %s\n",dcetostring((DCEnode*)dst)); fprintf(stderr,"dapmergeprojection: src = %s\n",dcetostring((DCEnode*)src)); #endif /* get dst concat clone(src) */ nclistsetalloc(cat,nclistlength(dst)+nclistlength(src)); for(i=0;i<nclistlength(dst);i++) { DCEprojection* p = (DCEprojection*)nclistget(dst,i); nclistpush(cat,(void*)p); } for(i=0;i<nclistlength(src);i++) { DCEprojection* p = (DCEprojection*)nclistget(src,i); nclistpush(cat,(void*)dceclone((DCEnode*)p)); } nclistclear(dst); /* Repeatedly pull elements from the concat, merge with all duplicates, and stick into the dst */ while(nclistlength(cat) > 0) { DCEprojection* target = (DCEprojection*)nclistremove(cat,0); if(target == NULL) continue; if(target->discrim != CES_VAR) continue; for(i=0;i<nclistlength(cat);i++) { DCEprojection* p2 = (DCEprojection*)nclistget(cat,i); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; if(dcesamepath(target->var->segments, p2->var->segments)!=0) continue; /* This entry matches our current target; merge */ ncstat = dcemergeprojections(target,p2); /* null out this merged entry and release it */ nclistset(cat,i,(void*)NULL); dcefree((DCEnode*)p2); } /* Capture the clone */ nclistpush(dst,(void*)target); } nclistfree(cat); return ncstat; }
void freecdfroot(CDFnode* root) { int i; CDFtree* tree; NCDAPCOMMON* nccomm; if(root == NULL) return; tree = root->tree; ASSERT((tree != NULL)); /* Explicitly FREE the ocroot */ nccomm = tree->owner; oc_root_free(nccomm->oc.conn,tree->ocroot); tree->ocroot = NULL; for(i=0;i<nclistlength(tree->nodes);i++) { CDFnode* node = (CDFnode*)nclistget(tree->nodes,i); free1cdfnode(node); } nclistfree(tree->nodes); nclistfree(tree->varnodes); nclistfree(tree->seqnodes); nclistfree(tree->gridnodes); nullfree(tree); }
void freenccachenode(NCDAPCOMMON* nccomm, NCcachenode* node) { if(node == NULL) return; #ifdef DEBUG fprintf(stderr,"freecachenode: %s\n", dumpcachenode(node)); #endif oc_data_free(nccomm->oc.conn,node->content); dcefree((DCEnode*)node->constraint); freecdfroot34(node->datadds); nclistfree(node->vars); nullfree(node); }
Object indexer(DCEparsestate* state, Object name, Object indices) { int i; NClist* list = (NClist*)indices; DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT); seg->name = strdup((char*)name); for(i=0;i<nclistlength(list);i++) { DCEslice* slice = (DCEslice*)nclistget(list,i); seg->slices[i] = *slice; free(slice); } nclistfree(indices); return seg; }
NCerror restruct(NCDAPCOMMON* ncc, CDFnode* ddsroot, CDFnode* templateroot, NClist* projections) { NCerror ncstat = NC_NOERR; NClist* repairs = nclistnew(); /* The current restruct assumes that the ddsroot tree has missing grids compared to the template. It is also assumed that order of the nodes in the ddsroot is the same as in the template. */ if(ddsroot->tree->restructed) { nclistfree(repairs); return NC_NOERR; } #ifdef DEBUG fprintf(stderr,"restruct: ddsroot=%s\n",dumptree(ddsroot)); fprintf(stderr,"restruct: templateroot=%s\n",dumptree(templateroot)); #endif /* Match roots */ if(!simplenodematch(ddsroot,templateroot)) ncstat = NC_EDATADDS; else if(!restructr(ncc,ddsroot,templateroot,repairs)) ncstat = NC_EDATADDS; else if(nclistlength(repairs) > 0) { /* Do the repairs */ ncstat = repairgrids(ncc, repairs); } if(repairs) nclistfree(repairs); return THROW(ncstat); }
static NCerror computeseqcountconstraints3(NCDAPCOMMON* dapcomm, CDFnode* seq, NCbytes* seqcountconstraints) { int i,j; NClist* path = NULL; CDFnode* var = NULL; ASSERT(seq->nctype == NC_Sequence); computeseqcountconstraints3r(dapcomm,seq,&var); ASSERT((var != NULL)); /* Compute var path */ path = nclistnew(); collectnodepath3(var,path,WITHOUTDATASET); /* construct the projection path using minimal index values */ for(i=0;i<nclistlength(path);i++) { CDFnode* node = (CDFnode*)nclistget(path,i); if(i > 0) ncbytescat(seqcountconstraints,"."); ncbytescat(seqcountconstraints,node->ocname); if(node == seq) { /* Use the limit */ if(node->sequencelimit > 0) { char tmp[64]; snprintf(tmp,sizeof(tmp),"[0:%lu]", (unsigned long)(node->sequencelimit - 1)); ncbytescat(seqcountconstraints,tmp); } } else if(nclistlength(node->array.dimset0) > 0) { int ndims = nclistlength(node->array.dimset0); for(j=0;j<ndims;j++) { CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j); if(DIMFLAG(dim,CDFDIMSTRING)) { ASSERT((j == (ndims - 1))); break; } ncbytescat(seqcountconstraints,"[0]"); } } } /* Finally, add in any selection from the original URL */ if(dapcomm->oc.url->selection != NULL) ncbytescat(seqcountconstraints,dapcomm->oc.url->selection); nclistfree(path); return NC_NOERR; }
void dcelexcleanup(DCElexstate** lexstatep) { DCElexstate* lexstate = *lexstatep; if(lexstate == NULL) return; if(lexstate->input != NULL) free(lexstate->input); if(lexstate->reclaim != NULL) { while(nclistlength(lexstate->reclaim) > 0) { char* word = (char*)nclistpop(lexstate->reclaim); if(word) free(word); } nclistfree(lexstate->reclaim); } ncbytesfree(lexstate->yytext); free(lexstate); *lexstatep = NULL; }