/* 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; }
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; }
static NCerror structwrap(NCDAPCOMMON* ncc, CDFnode* node, CDFnode* parent, int parentindex, CDFnode* patterngrid, int gridindex) { CDFnode* newstruct; ASSERT((patterngrid->nctype == NC_Grid)); newstruct = makenewstruct(ncc, node,patterngrid); if(newstruct == NULL) {return THROW(NC_ENOMEM);} /* replace the node with the new structure in the parent's list of children*/ nclistset(parent->subnodes,parentindex,(void*)newstruct); /* Update the list of all nodes in the tree */ nclistpush(node->root->tree->nodes,(void*)newstruct); return NC_NOERR; }
static NCerror builddims(NCDAPCOMMON* dapcomm) { int i; NCerror ncstat = NC_NOERR; int dimid; NClist* dimset = NULL; NC* drno = dapcomm->controller; NC* ncsub; char* definename; /* collect all dimensions from variables */ dimset = dapcomm->cdf.dimnodes; /* Sort by fullname just for the fun of it */ for(;;) { int last = nclistlength(dimset) - 1; int swap = 0; for(i=0;i<last;i++) { CDFnode* dim1 = (CDFnode*)nclistget(dimset,i); CDFnode* dim2 = (CDFnode*)nclistget(dimset,i+1); if(strcmp(dim1->ncfullname,dim2->ncfullname) > 0) { nclistset(dimset,i,(ncelem)dim2); nclistset(dimset,i+1,(ncelem)dim1); swap = 1; break; } } if(!swap) break; } /* Define unlimited only if needed */ if(dapcomm->cdf.recorddim != NULL) { CDFnode* unlimited = dapcomm->cdf.recorddim; definename = getdefinename(unlimited); ncstat = nc_def_dim(drno->substrate, definename, NC_UNLIMITED, &unlimited->ncid); nullfree(definename); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* get the id for the substrate */ ncstat = NC_check_id(drno->substrate,&ncsub); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* Set the effective size of UNLIMITED; note that this cannot be done thru the normal API.*/ NC_set_numrecs(ncsub,unlimited->dim.declsize); } for(i=0;i<nclistlength(dimset);i++) { CDFnode* dim = (CDFnode*)nclistget(dimset,i); if(dim->dim.basedim != NULL) continue; /* handle below */ if(DIMFLAG(dim,CDFDIMRECORD)) continue; /* defined above */ #ifdef DEBUG1 fprintf(stderr,"define: dim: %s=%ld\n",dim->ncfullname,(long)dim->dim.declsize); #endif definename = getdefinename(dim); ncstat = nc_def_dim(drno->substrate,definename,dim->dim.declsize,&dimid); if(ncstat != NC_NOERR) { THROWCHK(ncstat); goto done; } nullfree(definename); dim->ncid = dimid; } /* Make all duplicate dims have same dimid as basedim*/ /* (see computecdfdimnames)*/ for(i=0;i<nclistlength(dimset);i++) { CDFnode* dim = (CDFnode*)nclistget(dimset,i); if(dim->dim.basedim != NULL) { dim->ncid = dim->dim.basedim->ncid; } } done: nclistfree(dimset); return THROW(ncstat); }
/** * @internal * * Construct the provenance information for a newly opened file * Using the specified _NCProperties value. If NULL, then * initialize using dfalt. * * @param file Pointer to file object. * @param propstring The contents of _NCProperties * @param dfalt * * @return ::NC_NOERR No error. * @return ::NC_ENOMEM * @return ::NC_EINVAL * @author Dennis Heimbigner */ int NC4_get_provenance(NC_FILE_INFO_T* file, const char* propstring, const struct NCPROPINFO* dfalt) { int ncstat = NC_NOERR; struct NCPROVENANCE* provenance; char *name = NULL; char *value = NULL; int v = 0; int superblock = -1; LOG((3, "%s: ncid 0x%x propstring %s", __func__, file->root_grp->hdr.id, propstring)); assert(file->provenance == NULL); if((file->provenance = calloc(1,sizeof(struct NCPROVENANCE))) == NULL) {ncstat = NC_ENOMEM; goto done;} provenance = file->provenance; if((provenance->propattr.properties = nclistnew()) == NULL) {ncstat = NC_ENOMEM; goto done;} /* Set the superblock */ if((ncstat = NC4_hdf5get_superblock(file,&superblock))) goto done; provenance->superblockversion = superblock; if(propstring == NULL) { /* Use dfalt */ if((ncstat=propinfo_default(&provenance->propattr,dfalt))) goto done; } else { NClist* list = provenance->propattr.properties; if((ncstat=properties_parse(propstring,list))) goto done; /* Check the version and remove from properties list*/ if(nclistlength(list) < 2) {ncstat = NC_EINVAL; goto done;} /* bad _NCProperties attribute */ /* Extract the purported version=... */ name = nclistremove(list,0); value = nclistremove(list,0); if(strcmp(name,NCPVERSION) == 0) { if(sscanf(value,"%d",&v) != 1) {ncstat = NC_EINVAL; goto done;} /* illegal version */ if(v <= 0 || v > NCPROPS_VERSION) {ncstat = NC_EINVAL; goto done;} /* unknown version */ provenance->propattr.version = v; } else {ncstat = NC_EINVAL; goto done;} /* bad _NCProperties attribute */ /* Now, rebuild from version 1 to version 2 if necessary */ if(provenance->propattr.version == 1) { int i; for(i=0;i<nclistlength(list);i+=2) { char* newname = NULL; name = nclistget(list,i); if(name == NULL) continue; /* ignore */ if(strcmp(name,NCPNCLIB1) == 0) newname = NCPNCLIB2; /* change name */ else if(strcmp(name,NCPHDF5LIB1) == 0) newname = NCPHDF5LIB2; else continue; /* ignore */ /* Do any rename */ nclistset(list,i,strdup(newname)); if(name) {free(name); name = NULL;} } } } done: if(name != NULL) free(name); if(value != NULL) free(value); return ncstat; }
NCerror fixprojections(NClist* list) { int i,j,k; NCerror ncstat = NC_NOERR; NClist* tmp = nclistnew(); /* misc. uses */ #ifdef DEBUG fprintf(stderr,"fixprojection: list = %s\n",dumpprojections(list)); #endif if(nclistlength(list) == 0) goto done; /* Step 1: remove duplicates and complain about slice mismatches */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p1 == p2) continue; if(p2->discrim != CES_VAR) continue; if(p1->var->annotation != p2->var->annotation) continue; /* check for slice mismatches */ if(!slicematch(p1->var->segments,p2->var->segments)) { /* complain */ nclog(NCLOGWARN,"Malformed projection: same variable with different slicing"); } /* remove p32 */ nclistset(list,j,(ncelem)NULL); dcefree((DCEnode*)p2); } } /* Step 2: remove containers when a field is also present */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ if(!iscontainer((CDFnode*)p1->var->annotation)) continue; for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; nclistclear(tmp); collectnodepath3((CDFnode*)p2->var->annotation,tmp,WITHDATASET); for(k=0;k<nclistlength(tmp);k++) { void* candidate = (void*)nclistget(tmp,k); if(candidate == p1->var->annotation) { nclistset(list,i,(ncelem)NULL); dcefree((DCEnode*)p1); goto next; } } } next: continue; } /* Step 3: expand all containers recursively down to the leaf nodes */ for(;;) { nclistclear(tmp); for(i=0;i<nclistlength(list);i++) { DCEprojection* target = (DCEprojection*)nclistget(list,i); CDFnode* leaf; if(target == NULL) continue; if(target->discrim != CES_VAR) continue; /* dont try to unify functions */ leaf = (CDFnode*)target->var->annotation; ASSERT(leaf != NULL); if(iscontainer(leaf)) {/* capture container */ if(!nclistcontains(tmp,(ncelem)target)) nclistpush(tmp,(ncelem)target); nclistset(list,i,(ncelem)NULL); } } if(nclistlength(tmp) == 0) break; /*done*/ /* Now explode the containers */ for(i=0;i<nclistlength(tmp);i++) { DCEprojection* container = (DCEprojection*)nclistget(tmp,i); CDFnode* leaf = (CDFnode*)container->var->annotation; for(j=0;i<nclistlength(leaf->subnodes);j++) { CDFnode* field = (CDFnode*)nclistget(leaf->subnodes,j); /* Convert field node to a proper constraint */ DCEprojection* proj = projectify(field,container); nclistpush(list,(ncelem)proj); } /* reclaim the container */ dcefree((DCEnode*)container); } } /*for(;;)*/ /* remove all NULL elements */ for(i=nclistlength(list)-1;i>=0;i--) { DCEprojection* target = (DCEprojection*)nclistget(list,i); if(target == NULL) nclistremove(list,i); } done: #ifdef DEBUG fprintf(stderr,"fixprojection: exploded = %s\n",dumpprojections(list)); #endif nclistfree(tmp); return ncstat; }
int dapmerge3(NCDRNO* drno, CDFnode* ddsroot, OCobject dasroot) { unsigned int i,j; NCerror ncerr = NC_NOERR; OCerror ocstat = OC_NOERR; OCconnection conn = drno->dap.conn; unsigned int nsubnodes, nobjects; OCobject* dasobjects = NULL; NClist* dasglobals = nclistnew(); NClist* dodsextra = nclistnew(); NClist* dasnodes = nclistnew(); NClist* varnodes = nclistnew(); NClist* allddsnodes = ddsroot->tree->nodes; nobjects = oc_inq_nobjects(conn,dasroot); dasobjects = oc_inq_objects(conn,dasroot); /* 1. collect all the relevant DAS nodes; namely those that contain at least one attribute value. Simultaneously look for potential ambiguities if found; complain but continue: result are indeterminate. also collect globals and DODS_EXTRAs separately*/ for(i=0;i<nobjects;i++) { OCobject das = dasobjects[i]; OCtype octype; char* ocname = NULL; int isglobal = 0; int hasattributes = 0; OCobject* subnodes; OCHECK(oc_inq_class(conn,das,&octype)); if(octype == OC_Attribute) continue; /* ignore these for now*/ OCHECK(oc_inq_name(conn,das,&ocname)); OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes)); isglobal = (ocname == NULL ? 0 : isglobalname3(ocname)); if(ocname == NULL || isglobal) { nclistpush(dasglobals,(ncelem)das); efree(ocname); continue; } if(ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) { nclistpush(dodsextra,(ncelem)das); efree(ocname); continue; } OCHECK(oc_inq_subnodes(conn,das,&subnodes)); for(j=0;j<nsubnodes;j++) { OCobject subnode = subnodes[j]; OCtype ocsubtype; OCHECK(oc_inq_class(conn,subnode,&ocsubtype)); if(ocsubtype == OC_Attribute) {hasattributes = 1; break;} } efree(subnodes); if(hasattributes) { /* Look for previously collected nodes with same name*/ for(j=0;j<nclistlength(dasnodes);j++) { OCobject das2 = (OCobject)nclistget(dasnodes,j); char* ocname2; OCHECK(oc_inq_name(conn,das2,&ocname2)); if(ocname2 == NULL || ocname == NULL) goto loop; if(strcmp(ocname2,"DODS")==0) goto loop; if(strcmp(ocname,ocname2)==0) oc_log(OCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2); loop: efree(ocname2); } nclistpush(dasnodes,(ncelem)das); } efree(ocname); } /* 2. collect all the leaf DDS nodes (of type NC_Primitive)*/ for(i=0;i<nclistlength(allddsnodes);i++) { CDFnode* dds = (CDFnode*)nclistget(allddsnodes,i); if(dds->nctype == NC_Primitive) nclistpush(varnodes,(ncelem)dds); } /* 3. For each das node, lncate matching DDS node(s) and attach attributes to the DDS node(s). Match means: 1. DAS->fullname :: DDS->fullname 2. DAS->name :: DDS->fullname (support DAS names with embedded '.' 3. DAS->name :: DDS->name */ for(i=0;i<nclistlength(dasnodes);i++) { OCobject das = (OCobject)nclistget(dasnodes,i); char* ocfullname; char* ocbasename; if(das == OCNULL) continue; ocfullname = makeocpathstring3(conn,das,"."); OCHECK(oc_inq_name(conn,das,&ocbasename)); for(j=0;j<nclistlength(varnodes);j++) { CDFnode* dds = (CDFnode*)nclistget(varnodes,j); char* ddsfullname = makesimplepathstring3(dds); if(strcmp(ocfullname,ddsfullname)==0 || strcmp(ocbasename,ddsfullname)==0 || strcmp(ocbasename,dds->name)==0) { mergedas1(conn,dds,das); /* remove from dasnodes list*/ nclistset(dasnodes,i,(ncelem)NULL); } efree(ddsfullname); } efree(ocfullname); efree(ocbasename); } /* 4. Assign globals*/ for(i=0;i<nclistlength(dasglobals);i++) { OCobject das = (OCobject)nclistget(dasglobals,i); mergedas1(conn,ddsroot,das); } /* process DOD_EXTRA */ if(nclistlength(dodsextra) > 0) dodsextra3(drno,ddsroot,dodsextra); done: /* cleanup*/ efree(dasobjects); nclistfree(dasglobals); nclistfree(dasnodes); nclistfree(dodsextra); nclistfree(varnodes); if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat); return THROW(ncerr); }
NCerror computevarnodes(NCDAPCOMMON* nccomm, NClist* allnodes, NClist* varnodes) { unsigned int i,len; NClist* allvarnodes = nclistnew(); for(i=0; i<nclistlength(allnodes); i++) { CDFnode* node = (CDFnode*)nclistget(allnodes,i); #if 0 /* If this node has a bad name, repair it */ if(dap_badname(node->ocname)) { char* newname = dap_repairname(node->ocname); nullfree(node->ocname); node->ocname = newname; } #endif if(node->nctype == NC_Atomic) nclistpush(allvarnodes,(void*)node); } /* Further process the variable nodes to get the final set */ /* Use toplevel vars first */ len = nclistlength(allvarnodes); for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; if(daptoplevel(node)) { nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } } /*... then grid arrays and maps. but exclude the coordinate variables if we are trying to exactly mimic nc-dap */ for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; if(dapgridarray(node)) { nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } else if(dapgridmap(node)) { if(!FLAGSET(nccomm->controls,NCF_NCDAP)) nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } } /*... then all others */ for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; nclistpush(varnodes,(void*)node); } nclistfree(allvarnodes); #ifdef DEBUG2 for(i=0; i<nclistlength(varnodes); i++) { CDFnode* node = (CDFnode*)nclistget(varnodes,i); if(node == NULL) continue; fprintf(stderr,"computevarnodes: var: %s\n",makecdfpathstring(node,".")); } #endif return NC_NOERR; }
/* See if we can unify sets of nodes to be projected into larger units. */ static NClist* unifyprojectionnodes3(NClist* varlist) { int i; NClist* nodeset = nclistnew(); NClist* containerset = nclistnew(); NClist* containernodes = nclistnew(); nclistsetalloc(nodeset,nclistlength(varlist)); nclistsetalloc(containerset,nclistlength(varlist)); /* Duplicate the varlist so we can modify it; simultaneously collect unique container set. */ for(i=0;i<nclistlength(varlist);i++) { CDFnode* var = (CDFnode*)nclistget(varlist,i); CDFnode* container = var->container; nclistpush(nodeset,(ncelem)var); switch (container->nctype) { case NC_Sequence: case NC_Structure: case NC_Grid: case NC_Dataset: /* add (uniquely) to container set */ if(!nclistcontains(containerset,(ncelem)container)) nclistpush(containerset,(ncelem)container); break; default: break; } } /* Now, try to find containers whose subnodes are all in the varlist; repeat until no more changes */ for(;;) { int changed = 0; for(i=0;i<nclistlength(containerset);i++) { int j, allfound; CDFnode* container = (CDFnode*)nclistget(containerset,i); if(container == NULL) continue; nclistclear(containernodes); for(allfound=1,j=0;j<nclistlength(container->subnodes);j++) { CDFnode* subnode = (CDFnode*)nclistget(container->subnodes,j); if(!nclistcontains(varlist,(ncelem)subnode)) {allfound=0;break;} nclistpush(containernodes,(ncelem)subnode); } if(allfound) { nclistpush(nodeset,(ncelem)container); nclistset(containerset,i,(ncelem)NULL); /* remove */ for(j=nclistlength(nodeset)-1;j>=0;j--) { /* walk backwards */ CDFnode* testnode = (CDFnode*)nclistget(nodeset,j); if(nclistcontains(containernodes,(ncelem)testnode)) nclistremove(nodeset,j);/* remove */ } changed = 1; } } if(!changed) break; /* apparently we have reached a stable situation */ } /* If there is only the dataset left as a projection, then remove it */ if(nclistlength(nodeset) == 1) { CDFnode* thenode = (CDFnode*)nclistget(nodeset,0); if(thenode->nctype == NC_Dataset) nclistclear(nodeset); } nclistfree(containerset); nclistfree(containernodes); return nodeset; }
int dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot) { unsigned int i,j; NCerror ncerr = NC_NOERR; OCerror ocstat = OC_NOERR; OClink conn = nccomm->oc.conn; size_t nsubnodes; NClist* dasglobals = nclistnew(); NClist* dasnodes = nclistnew(); NClist* dodsextra = nclistnew(); NClist* varnodes = nclistnew(); NClist* alldasnodes = nclistnew(); if(ddsroot == NULL || dasroot == NULL) return NC_NOERR; ocstat = collect_alldasnodes(conn,dasroot,alldasnodes); /* 1. collect all the relevant DAS nodes; namely those that contain at least one attribute value. Simultaneously look for potential ambiguities if found; complain but continue: result are indeterminate. also collect globals and DODS_EXTRA separately. */ for(i=0;i<nclistlength(alldasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(alldasnodes,i); OCtype octype; char* ocname = NULL; int isglobal = 0; int hasattributes = 0; OCCHECK(oc_dds_class(conn,das,&octype)); if(octype == OC_Attribute) continue; /* ignore these for now*/ OCCHECK(oc_dds_name(conn,das,&ocname)); OCCHECK(oc_dds_nsubnodes(conn,das,&nsubnodes)); isglobal = (ocname == NULL ? 0 : isglobalname3(ocname)); /* catch DODS_EXTRA */ if(isglobal && ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) { nclistpush(dodsextra,(void*)das); nullfree(ocname); continue; } if(ocname == NULL || isglobal) { nclistpush(dasglobals,(void*)das); nullfree(ocname); continue; } hasattributes = hasattribute3(conn,das); if(hasattributes) { /* Look for previously collected nodes with same name*/ for(j=0;j<nclistlength(dasnodes);j++) { OCddsnode das2 = (OCddsnode)nclistget(dasnodes,j); char* ocname2; OCCHECK(oc_dds_name(conn,das2,&ocname2)); if(ocname2 == NULL || ocname == NULL) goto loop; if(strcmp(ocname2,"DODS")==0) goto loop; if(strcmp(ocname,ocname2)==0) nclog(NCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2); loop: nullfree(ocname2); } nclistpush(dasnodes,(void*)das); } nullfree(ocname); } /* 2. collect all the leaf DDS nodes (of type NC_Atomic)*/ ocstat = collect_leaves(link,ddsroot,varnodes); /* 3. For each das node, locate matching DDS node(s) and attach attributes to the DDS node(s). Match means: 1. DAS->fullname :: DDS->fullname 2. DAS->name :: DDS->fullname (support DAS names with embedded '.' 3. DAS->name :: DDS->name 4. special case for DODS. Apply 1-3 on DODS parent. */ for(i=0;i<nclistlength(dasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(dasnodes,i); char* ocfullname = NULL; char* ocbasename = NULL; if(das == NULL) continue; OCCHECK(oc_dds_name(conn,das,&ocbasename)); if(strcmp(ocbasename,"DODS")==0) { OCddsnode container; OCCHECK(oc_dds_container(conn,das,&container)); ASSERT(container != NULL); ocfullname = makeocpathstring3(conn,container,"."); } else { ocfullname = makeocpathstring3(conn,das,"."); } for(j=0;j<nclistlength(varnodes);j++) { CDFnode* dds = (CDFnode*)nclistget(varnodes,j); char* ddsfullname = makecdfpathstring3(dds,"."); if(strcmp(ocfullname,ddsfullname)==0 || strcmp(ocbasename,ddsfullname)==0 || strcmp(ocbasename,dds->ocname)==0) { mergedas1(nccomm,conn,dds,das); /* remove from dasnodes list*/ nclistset(dasnodes,i,(void*)NULL); } nullfree(ddsfullname); } nullfree(ocfullname); nullfree(ocbasename); } /* 4. Assign globals */ for(i=0;i<nclistlength(dasglobals);i++) { OCddsnode das = (OCddsnode)nclistget(dasglobals,i); mergedas1(nccomm,conn,ddsroot,das); } /* 5. Assign DOD_EXTRA */ for(i=0;i<nclistlength(dodsextra);i++) { OCddsnode das = (OCddsnode)nclistget(dodsextra,i); mergedas1(nccomm,conn,ddsroot,das); } done: /* cleanup*/ nclistfree(dasglobals); nclistfree(dasnodes); nclistfree(alldasnodes); nclistfree(dodsextra); nclistfree(varnodes); if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat); return THROW(ncerr); }