/* * silo.i - $Id$ * support for Silo files, a higher level binary format than PDB */ func silo_open (filename) /* DOCUMENT silo_open, filename or silo= silo_open(filename) open FILENAME for later use with silo_... functions There is a single current silo file, which is opened and set by the first form. The other silo_... functions normally operate on this current file, but also accept a silo= keyword, which is a list returned by the second calling sequence for silo_open. SEE ALSO: silo_cd, silo_ls, silo_var, silo_close */ { f= openb(filename); vars= *get_vars(f)(1); nvars= numberof(vars); mask= strpart(vars,0:0)=="/"; list= where(mask); ndirs= numberof(list); grow, vars, vars(list)+"\377\377\377"; /* mark end of each dir */ grow, mask, array(-1, ndirs); order= sort(vars); vars= vars(order); mask= mask(order); invrs= order; invrs(order)= indgen(nvars+ndirs); list= invrs(list); ends= invrs(nvars+1:nvars+ndirs); lens= array(0,nvars+ndirs); order= (mask<0)(psum); lens(list)= ends - list - order(ends) + order(list); list= where(lens); lens= lens(list); depth= mask(psum); depth(list)-= 1; list= where(mask>=0); vars= vars(list); depth= depth(list); list= where(mask(list)); list= _lst(f, vars, depth, list, lens, "/"); if (am_subroutine()) { extern silo_list; silo_list= list; } else { return list; } } func silo_close (void, silo=) /* DOCUMENT silo_close close current silo file SEE ALSO: silo_cd, silo_ls, silo_var, silo_open */ { if (is_void(silo)) { close, _car(silo_list, 1, []); silo_list= []; } else { close, _car(silo, 1, []); } } func silo_cd (dir, silo=) /* DOCUMENT silo_cd, dirname change current silo directory to DIRNAME, which may contain .. or . constructs as a UNIX pathname accepts silo= keyword to operate on a silo file other than the current silo file SEE ALSO: silo_ls, silo_var, silo_open, silo_close */ { list= is_void(silo)? silo_list : silo; if (strpart(dir,0:0)=="/") dir= strpart(dir,1:-1); if (strpart(dir,1:1)!="/") dir= _car(list,6) + dir; dir= silo_simplify(dir) + "/"; if (dir=="//") dir= "/"; lst= where(dir==_car(list, 2)(_car(list, 4))); if (!numberof(lst)) { if (am_subroutine()) error, "no such directory as: "+dir; return string(0); } _car, list, 6, dir; return dir; } func silo_var (var, silo=) /* DOCUMENT var= silo_var(varname) return silo variable VARNAME accepts silo= keyword to operate on a silo file other than the current silo file SEE ALSO: silo_ls, silo_cd, silo_open, silo_close */ { list= is_void(silo)? silo_list : silo; if (strpart(var,1:1)!="/") var= _car(list,6) + var; return get_member(_car(list,1),silo_simplify(var)); } func silo_ls (name, &dirname, silo=) /* DOCUMENT silo_ls or silo_ls, dirname or itemlist= silo_ls(dirname) or itemlist= silo_ls(dirname, fulldirname) list current silo directory or DIRNAME if called as a function, returns a 1D array of strings beginning with ".", and optionally returns FULLDIRNAME, which is the full path name of the directory listed - the individual items in the list do not include the directory path - subdirectory names end with "/", so you can find them using strpart(itemlist,0:0)=="/" accepts silo= keyword to operate on a silo file other than the current silo file SEE ALSO: silo_ls, silo_cd, silo_open, silo_close */ { list= is_void(silo)? silo_list : silo; if (is_void(name)) name= "."; if (strpart(name,0:0)=="/") name= strpart(name,1:-1); if (strpart(name,1:1)!="/") name= _car(list,6) + name; name= silo_simplify(name) + "/"; if (name=="//") name= "/"; local vars, lens; eq_nocopy, vars, _car(list, 2); eq_nocopy, depth, _car(list, 3); eq_nocopy, lens, _car(list, 5); eq_nocopy, list, _car(list, 4); lst= where(name==vars(list)); if (!numberof(lst)) { if (am_subroutine()) write, "no such directory as: "+name; return []; } lst= lst(1); lens= lens(lst); list= list(lst); vars= vars(list:list+lens); depth= depth(list:list+lens); dirname= vars(1); /* full directory name */ vars(1)= "."; if (numberof(vars)>1) { depth(1)+= 1; vars= vars(where(depth==depth(1))); lens= strlen(dirname); if (numberof(vars)>1) vars(2:0)= strpart(vars(2:0),lens+1:0); } if (am_subroutine()) write, format=" %s\n", vars; return vars; } func silo_simplify (dir) { if (strmatch(dir,"/.")) { parts= array(string, 1000); parse= strtok(dir, "/"); for (tok=parse(1),i=0 ; tok ; tok=parse(1)) { if (tok!=".") { if (tok=="..") i= max(0, i-1); else parts(++i)= tok; } parse= strtok(parse(2), "/"); } dir= i? "" : "/"; for (j=1 ; j<=i ; j++) dir+= "/"+parts(j); } return dir; }