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