1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 2003-2011 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Phong Vo <kpv@research.att.com> *
18 * *
19 ***********************************************************************/
20 #include "vchdr.h"
21
22 #include <fnmatch.h>
23
24 /* Collection of functions to translate command line arguments,
25 ** aliases, etc. to list of transforms and arguments suitable for
26 ** data tranformation by vcsfio().
27 **
28 ** The syntax is like this:
29 ** Transformation Method1,Method2,...
30 ** Method method.arg1.arg2....
31 ** arg value
32 ** arg name=value
33 ** method alphanumeric string specifying a transform
34 ** name alphanumeric string specifying an argument
35 ** value any string, quotable with [], C-style chars
36 **
37 ** Written by Kiem-Phong Vo.
38 */
39
40 #ifndef PATH_MAX
41 #define PATH_MAX (4*1024)
42 #endif
43 #define ALIASES "lib/vcodex/aliases"
44 #define VCZIPRC ".vcziprc"
45
46 typedef struct _vcalias_s Vcalias_t;
47 struct _vcalias_s
48 { Vcalias_t* next;
49 char* name; /* name of the alias */
50 char* value; /* what it should expand to */
51 };
52
53 static char *Dfltalias[] =
54 {
55 "tv = ama,table,mtf,rle.0,huffgroup",
56 "tss7 = ss7,table,mtf,rle.0,huffpart",
57 "tnls = ama.nls,rtable,mtf,rle.0,huffgroup",
58 "tnl = ama.nl,table,mtf,rle.0,huffgroup",
59 "tbdw = bdw,ama,table,mtf,rle.0,huffgroup",
60 "t = table,mtf,rle.0,huffgroup",
61 "rte = strip.nl.head=1.tail=1,rdb.pad.plain.whole,table,mtf,rle.0,huffgroup",
62 "rt = rtable,mtf,rle.0,huffgroup",
63 "qv = ama,transpose,rle,huffman",
64 "qnl = ama.nl,transpose,rle,huffman",
65 "q = transpose,rle,huffman",
66 "netflow = netflow,mtf,rle.0,huffgroup",
67 "flatrdb = rdb,bwt,mtf,rle.0,huffgroup",
68 "fixedrdb = rdb.full,table,mtf,rle.0,huffgroup",
69 "dna = sieve.reverse.map=ATGCatgc,huffgroup",
70 "delta = sieve.delta,bwt,mtf,rle.0,huffgroup",
71 "b = bwt,mtf,rle.0,huffgroup",
72 0
73 };
74
75 static Vcalias_t *Alias;
76 static Vcalias_t *Fname;
77
78 /* create aliases, text lines of the form 'name = value' */
79 /* create file name extension mappings, text lines of the form 'pattern : value' */
80 #if __STD_C
zipalias(char * s)81 static void zipalias(char* s)
82 #else
83 static Vcalias_t* zipalias(s)
84 char* s; /* spec of new aliases */
85 #endif
86 {
87 Vcalias_t *al, **list;
88 ssize_t a, v, w, n;
89
90 for(n = s ? strlen(s) : 0; n > 0; )
91 { /* skip starting blanks */
92 while(n > 0 && (isblank(*s) || *s == '\n') )
93 { s += 1; n -= 1; }
94
95 if(!isalnum(*s) ) /* invalid alias specification */
96 goto skip_line;
97
98 /* get the name */
99 for(a = 0; a < n; ++a)
100 if(!isalnum(s[a]))
101 break;
102
103 for(v = a; v < n; ++v)
104 if(!isblank(s[v]) )
105 break;
106 if(s[v] == '=')
107 list = &Alias;
108 else if(s[v] == ':')
109 list = &Fname;
110 else
111 goto skip_line;
112
113 /* get the value */
114 for(v += 1; v < n; ++v)
115 if(!isblank(s[v]) )
116 break;
117 for(w = v; w < n; ++w)
118 if(isblank(s[w]) )
119 break;
120 if(w == v)
121 goto skip_line;
122
123 if(!(al = (Vcalias_t*)malloc(sizeof(Vcalias_t) + a+1 + (w-v)+1)) )
124 break;
125
126 al->name = (char*)(al+1);
127 al->value = al->name + a+1;
128 memcpy(al->name, s, a); al->name[a] = 0;
129 memcpy(al->value, s+v, w-v); al->value[w-v] = 0;
130 al->next = *list;
131 *list = al;
132
133 skip_line:
134 for(; n > 0; --n, ++s)
135 if(*s == '\n')
136 break;
137 }
138 }
139
140 /* initialize a list of aliases */
141 #if __STD_C
vcaddalias(char ** dflt)142 void vcaddalias(char** dflt)
143 #else
144 void vcaddalias(dflt)
145 char** dflt; /* list of default aliases */
146 #endif
147 {
148 ssize_t z;
149 Sfio_t *sf;
150 char *sp, file[PATH_MAX];
151
152 if(!Alias)
153 {
154 #if _PACKAGE_ast /* AST alias convention */
155 if(pathpath(ALIASES, "", PATH_REGULAR, file, sizeof(file)) && (sf = sfopen(0, file, "")) )
156 { while((sp = sfgetr(sf, '\n', 1)) )
157 zipalias(sp);
158 sfclose(sf);
159 }
160 #endif
161
162 /* $HOME/.vcziprc */
163 if((sp = getenv("HOME")) && (z = strlen(sp)) > 0 && (z+1+strlen(VCZIPRC)+1) <= PATH_MAX )
164 { memcpy(file, sp, z);
165 sp[z] = '/';
166 strcpy(file+z+1, VCZIPRC);
167
168 if((sf = sfopen(0, file, "")) )
169 { while((sp = sfgetr(sf, '\n', 1)) )
170 zipalias(sp);
171 sfclose(sf);
172 }
173 }
174 for(z = 0; sp = Dfltalias[z]; ++z)
175 zipalias(sp);
176 }
177
178 /* other default aliases */
179 if(dflt)
180 for(z = 0; (sp = dflt[z]); ++z)
181 zipalias(sp);
182 }
183
184 /* map an alias. Arguments are passed onto the first method of the aliased spec */
185 #if __STD_C
vcgetalias(char * spec,char * meth,ssize_t mtsz)186 char* vcgetalias(char* spec, char* meth, ssize_t mtsz)
187 #else
188 char* vcgetalias(spec, meth, mtsz)
189 char* spec; /* name.arg1.arg2... */
190 char* meth; /* buffer for methods */
191 ssize_t mtsz; /* buffer size */
192 #endif
193 {
194 char *args, *rest, name[1024];
195 ssize_t n, a, r;
196 Vcalias_t *alias;
197
198 if(!Alias)
199 vcaddalias(NIL(char**));
200
201 if(!(alias = Alias) || !spec)
202 return spec;
203
204 /* must be of the form xxx.yyy.zzz... only */
205 if(!(args = vcsubstring(spec, VC_METHSEP, name, sizeof(name), 0)) || *args != 0 )
206 return spec;
207
208 /* find the extent of the alias name */
209 for(n = 0; name[n]; ++n)
210 if(name[n] == 0 || name[n] == VC_ARGSEP)
211 break;
212 args = name[n] ? name+n+1 : name+n;
213 name[n] = 0;
214
215 /* see if that matches an alias */
216 for(; alias; alias = alias->next)
217 if(strcmp(alias->name, name) == 0)
218 break;
219 if(!alias)
220 return spec;
221
222 if(!*args || !meth || !mtsz) /* no new arguments */
223 return alias->value;
224
225 /* copy the spec of the first transform to meth[] */
226 if(!(rest = vcsubstring(alias->value, VC_METHSEP, meth, mtsz, 0)) )
227 return spec;
228
229 n = strlen(meth);
230 a = strlen(args);
231 r = strlen(rest);
232 if(n+1+a+1+r > mtsz) /* not enough room */
233 return spec;
234
235 /* copy additional arguments */
236 meth[n] = VC_ARGSEP;
237 strcpy(meth+n+1, args);
238
239 if(r > 0) /* copy the rest of the alias */
240 { meth[n+1+a] = VC_METHSEP;
241 strcpy(meth+n+1+a+1, rest);
242 }
243
244 return meth;
245 }
246
247 /* match a file name */
248 #if __STD_C
vcgetfname(char * name,char * meth,ssize_t mtsz)249 char* vcgetfname(char* name, char* meth, ssize_t mtsz)
250 #else
251 char* vcgetfname(name, meth, mtsz)
252 char* name; /* file name to match */
253 char* meth; /* buffer for methods */
254 ssize_t mtsz; /* buffer size */
255 #endif
256 {
257 Vcalias_t *al;
258
259 if(!Alias)
260 vcaddalias(NIL(char**));
261
262 for(al = Fname; al; al = al->next)
263 if(fnmatch(al->name, name, FNM_PATHNAME) == 0 )
264 {
265 if(!meth || mtsz <= strlen(al->value))
266 break;
267 strcpy(meth, al->value);
268 return meth;
269 }
270
271 return NIL(char*);
272 }
273
274 /* walk an alias list */
275 #if __STD_C
vcwalklist(Vcalias_t * al,Vcwalk_f walkf,Void_t * disc)276 static int vcwalklist(Vcalias_t* al, Vcwalk_f walkf, Void_t* disc)
277 #else
278 static int vcwalklist(al, walkf, disc)
279 Vcalias_t* al;
280 Vcwalk_f walkf;
281 Void_t* disc;
282 #endif
283 {
284 int rv;
285
286 if(!walkf)
287 return -1;
288 for(; al; al = al->next)
289 if((rv = (*walkf)((Void_t*)0, al->name, al->value, disc)) < 0 )
290 return rv;
291 return 0;
292 }
293
294 /* walk the list of aliases */
295 #if __STD_C
vcwalkalias(Vcwalk_f walkf,Void_t * disc)296 int vcwalkalias(Vcwalk_f walkf, Void_t* disc)
297 #else
298 int vcwalkalias(walkf, disc)
299 Vcwalk_f walkf;
300 Void_t* disc;
301 #endif
302 {
303 if(!Alias)
304 vcaddalias(NIL(char**));
305 return vcwalklist(Alias, walkf, disc);
306 }
307
308 /* walk the list of fnames */
309 #if __STD_C
vcwalkfname(Vcwalk_f walkf,Void_t * disc)310 int vcwalkfname(Vcwalk_f walkf, Void_t* disc)
311 #else
312 int vcwalkfname(walkf, disc)
313 Vcwalk_f walkf;
314 Void_t* disc;
315 #endif
316 {
317 if(!Alias)
318 vcaddalias(NIL(char**));
319 return vcwalklist(Fname, walkf, disc);
320 }
321