1 /*
2 * $Id: silo.i,v 1.2 2006-12-17 18:22:03 dhmunro Exp $
3 * support for Silo files, a higher level binary format than PDB
4 */
5 /* Copyright (c) 2005, The Regents of the University of California.
6 * All rights reserved.
7 * This file is part of yorick (http://yorick.sourceforge.net).
8 * Read the accompanying LICENSE file for details.
9 */
10
11 if (is_void(silo_openb)) silo_openb=is_void(basfix_openb)?openb:basfix_openb;
12
silo_open(filename)13 func silo_open(filename)
14 /* DOCUMENT silo_open, filename
15 or silo= silo_open(filename)
16 open FILENAME for later use with silo_... functions
17
18 There is a single current silo file, which is opened and set
19 by the first form. The other silo_... functions normally
20 operate on this current file, but also accept a silo= keyword,
21 which is a list returned by the second calling sequence for
22 silo_open.
23
24 SEE ALSO: silo_cd, silo_ls, silo_var, silo_close
25 */
26 {
27 f= silo_openb(filename);
28 vars= *get_vars(f)(1);
29 nvars= numberof(vars);
30 mask= strpart(vars,0:0)=="/";
31 list= where(mask);
32 ndirs= numberof(list);
33 grow, vars, vars(list)+"\377\377\377"; /* mark end of each dir */
34 grow, mask, array(-1, ndirs);
35 order= sort(vars);
36 vars= vars(order);
37 mask= mask(order);
38 invrs= order;
39 invrs(order)= indgen(nvars+ndirs);
40 list= invrs(list);
41 ends= invrs(nvars+1:nvars+ndirs);
42 lens= array(0,nvars+ndirs);
43 order= (mask<0)(psum);
44 lens(list)= ends - list - order(ends) + order(list);
45 list= where(mask>0);
46 lens= lens(list);
47 depth= mask(psum);
48 depth(list)-= 1;
49 list= where(mask>=0);
50 vars= vars(list);
51 depth= depth(list);
52 list= where(mask(list));
53 list= _lst(f, vars, depth, list, lens, "/");
54 if (am_subroutine()) {
55 extern silo_list;
56 silo_list= list;
57 } else {
58 return list;
59 }
60 }
61
62 func silo_close(void, silo=)
63 /* DOCUMENT silo_close
64 close current silo file
65 SEE ALSO: silo_cd, silo_ls, silo_var, silo_open
66 */
67 {
68 if (is_void(silo)) {
69 close, _car(silo_list, 1, []);
70 silo_list= [];
71 } else {
72 close, _car(silo, 1, []);
73 }
74 }
75
76 func silo_cd(dir, silo=)
77 /* DOCUMENT silo_cd, dirname
78 change current silo directory to DIRNAME, which may contain
79 .. or . constructs as a UNIX pathname
80 accepts silo= keyword to operate on a silo file other than the
81 current silo file
82 SEE ALSO: silo_ls, silo_var, silo_open, silo_close
83 */
84 {
85 list= is_void(silo)? silo_list : silo;
86 if (strpart(dir,0:0)=="/") dir= strpart(dir,1:-1);
87 if (strpart(dir,1:1)!="/") dir= _car(list,6) + dir;
88 dir= silo_simplify(dir) + "/";
89 if (dir=="//") dir= "/";
90 lst= where(dir==_car(list, 2)(_car(list, 4)));
91 if (!numberof(lst)) {
92 if (am_subroutine()) error, "no such directory as: "+dir;
93 return string(0);
94 }
95 _car, list, 6, dir;
96 return dir;
97 }
98
99 func silo_var(var, silo=)
100 /* DOCUMENT var= silo_var(varname)
101 return silo variable VARNAME
102 accepts silo= keyword to operate on a silo file other than the
103 current silo file
104 SEE ALSO: silo_ls, silo_cd, silo_open, silo_close
105 */
106 {
107 list= is_void(silo)? silo_list : silo;
108 if (strpart(var,1:1)!="/") var= _car(list,6) + var;
109 return get_member(_car(list,1),silo_simplify(var));
110 }
111
112 func silo_ls(name, &dirname, silo=)
113 /* DOCUMENT silo_ls
114 or silo_ls, dirname
115 or itemlist= silo_ls(dirname)
116 or itemlist= silo_ls(dirname, fulldirname)
117 list current silo directory or DIRNAME
118 if called as a function, returns a 1D array of strings beginning
119 with ".", and optionally returns FULLDIRNAME, which is the
120 full path name of the directory listed
121 - the individual items in the list do not include the
122 directory path
123 - subdirectory names end with "/", so you can find them
124 using strpart(itemlist,0:0)=="/"
125 accepts silo= keyword to operate on a silo file other than the
126 current silo file
127 SEE ALSO: silo_ls, silo_cd, silo_open, silo_close
128 */
129 {
130 list= is_void(silo)? silo_list : silo;
131 if (is_void(name)) name= ".";
132 if (strpart(name,0:0)=="/") name= strpart(name,1:-1);
133 if (strpart(name,1:1)!="/") name= _car(list,6) + name;
134 name= silo_simplify(name) + "/";
135 if (name=="//") name= "/";
136 local vars, lens;
137 eq_nocopy, vars, _car(list, 2);
138 eq_nocopy, depth, _car(list, 3);
139 eq_nocopy, lens, _car(list, 5);
140 eq_nocopy, list, _car(list, 4);
141 lst= where(name==vars(list));
142 if (!numberof(lst)) {
143 if (am_subroutine()) write, "no such directory as: "+name;
144 return [];
145 }
146 lst= lst(1);
147 lens= lens(lst);
148 list= list(lst);
149 vars= vars(list:list+lens);
150 depth= depth(list:list+lens);
151 dirname= vars(1); /* full directory name */
152 vars(1)= ".";
153 if (numberof(vars)>1) {
154 depth(1)+= 1;
155 vars= vars(where(depth==depth(1)));
156 lens= strlen(dirname);
157 if (numberof(vars)>1) vars(2:0)= strpart(vars(2:0),lens+1:0);
158 }
159 if (am_subroutine()) write, format=" %s\n", vars;
160 return vars;
161 }
162
silo_simplify(dir)163 func silo_simplify(dir)
164 {
165 if (strmatch(dir,"/.")) {
166 parts= array(string, 1000);
167 parse= strtok(dir, "/");
168 for (tok=parse(1),i=0 ; tok ; tok=parse(1)) {
169 if (tok!=".") {
170 if (tok=="..") i= max(0, i-1);
171 else parts(++i)= tok;
172 }
173 parse= strtok(parse(2), "/");
174 }
175 dir= i? "" : "/";
176 for (j=1 ; j<=i ; j++) dir+= "/"+parts(j);
177 }
178 return dir;
179 }
180