1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 2002-2012 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 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * dss optget() support
23  */
24 
25 #include "dsshdr.h"
26 
27 /*
28  * format optget(3) description item on sp given plain text and item name
29  * you're in unless you optout
30  */
31 
32 static int
optout(register Sfio_t * sp,const char * name,const char * type,const char * map,const char * ret,const char * s,const char * x)33 optout(register Sfio_t* sp, const char* name, const char* type, const char* map, const char* ret, const char* s, const char* x)
34 {
35 	register const char*	t;
36 	register int		c;
37 
38 	sfputc(sp, '[');
39 	sfputc(sp, '+');
40 	if (name)
41 	{
42 		if (ret)
43 			sfprintf(sp, "%s ", ret);
44 		for (t = name; c = *t++;)
45 		{
46 			if (c == ':')
47 				sfputc(sp, c);
48 			sfputc(sp, c);
49 		}
50 		if (type && !ret)
51 			sfputc(sp, ' ');
52 	}
53 	if (type)
54 	{
55 		sfprintf(sp, "(%s", type);
56 		if (map)
57 			sfprintf(sp, "::::%s", map);
58 		sfputc(sp, ')');
59 	}
60 	sfputc(sp, '?');
61 	if (s)
62 	{
63 		if (*s == '[')
64 			sfputr(sp, s + 1, -1);
65 		else if (optesc(sp, s, 0))
66 			return -1;
67 		if (x)
68 		{
69 			sfputc(sp, ' ');
70 			if (optesc(sp, x, 0))
71 				return -1;
72 		}
73 	}
74 	else
75 		sfputc(sp, ' ');
76 	if (!s || *s != '[')
77 		sfputc(sp, ']');
78 	return 0;
79 }
80 
81 /*
82  * structure type info output
83  */
84 
85 static int
optmem(register Sfio_t * sp,Cxtype_t * type)86 optmem(register Sfio_t* sp, Cxtype_t* type)
87 {
88 	register Cxvariable_t*	mp;
89 
90 	sfprintf(sp, "{\n");
91 	for (mp = (Cxvariable_t*)dtfirst(type->member->members); mp; mp = (Cxvariable_t*)dtnext(type->member->members, mp))
92 	{
93 		if (optout(sp, mp->name, mp->type->name, NiL, NiL, mp->description, mp->type->member ? "This structure type has the following members:" : (char*)0))
94 			return -1;
95 		if (mp->type->member && optmem(sp, mp->type))
96 			return -1;
97 	}
98 	sfprintf(sp, "}\n");
99 	return 0;
100 }
101 
102 /*
103  * type info output
104  */
105 
106 static int
opttype(Sfio_t * sp,register Cxtype_t * tp,int members)107 opttype(Sfio_t* sp, register Cxtype_t* tp, int members)
108 {
109 	register const char*	x;
110 	register const char*	b;
111 	register const char*	d;
112 	register int		i;
113 	Sfio_t*			tmp = 0;
114 
115 	if (tp->member)
116 		x = "This structure type has the following members:";
117 	else if (tp->match)
118 		x = tp->match->description;
119 	else
120 		x = 0;
121 	if (tp->format.description)
122 	{
123 		b = !x ? "" : x[0] == '[' && x[1] == '+' && x[2] == '?' ? (x + 3) : x;
124 		if (tp->format.details)
125 			x = sfprints("%s The default value is \b%s\b. %s", tp->format.description, tp->format.details, b);
126 		else if (x)
127 			x = sfprints("%s %s", tp->format.description, b);
128 		else
129 			x = tp->format.description;
130 	}
131 	if (!(d = tp->description) && tp->generic && (tmp = sfstropen()))
132 	{
133 		sfprintf(tmp, "A generic type that maps to %s", tp->generic[0]->name);
134 		for (i = 1; tp->generic[i]; i++)
135 			sfprintf(tmp, "%s%s", tp->generic[i + 1] ? ", " : " or ", tp->generic[i]->name);
136 		sfprintf(tmp, " at runtime.");
137 		d = sfstruse(tmp);
138 	}
139 	i = optout(sp, tp->name, tp->base ? tp->base->name : (const char*)0, NiL, NiL, d, x);
140 	if (tmp)
141 		sfstrclose(tmp);
142 	if (i)
143 		return -1;
144 	if (tp->member && optmem(sp, tp))
145 		return -1;
146 	else if (tp->base && tp->base->member && !(tp->base->header.flags & CX_REFERENCED) && opttype(sp, tp->base, 0))
147 		return -1;
148 	if (tp->generic)
149 		for (i = 0; tp->generic[i]; i++)
150 			if (!(tp->generic[i]->header.flags & CX_REFERENCED) && opttype(sp, tp->generic[i], 0))
151 				return -1;
152 	return 0;
153 }
154 
155 /*
156  * data map output
157  */
158 
159 static int
optmap(register Sfio_t * sp,Cxmap_t * map)160 optmap(register Sfio_t* sp, Cxmap_t* map)
161 {
162 	size_t		n;
163 	Cxpart_t*	part;
164 	Cxitem_t*	item;
165 
166 	sfprintf(sp, "{\n");
167 	if (map->shift)
168 		sfprintf(sp, "[+SHIFT=%u]", map->shift);
169 	if (~map->mask)
170 		sfprintf(sp, "[+MASK=0x%016llx]", map->mask);
171 	if (map->num2str)
172 	{
173 		if ((n = dtsize(map->num2str)) > 16)
174 			sfprintf(sp, "[+----- %u entries omitted -----]", n);
175 		else
176 			for (item = (Cxitem_t*)dtfirst(map->num2str); item; item = (Cxitem_t*)dtnext(map->num2str, item))
177 				if (item->mask == item->value)
178 					sfprintf(sp, "[+%s?0x%016llx]", item->name, item->value);
179 				else
180 					sfprintf(sp, "[+%s?%llu]", item->name, item->value);
181 	}
182 	else
183 		for (part = map->part; part; part = part->next)
184 		{
185 			if (part->shift)
186 				sfprintf(sp, "[+SHIFT=%u]", part->shift);
187 			if (~part->mask)
188 				sfprintf(sp, "[+MASK=0x%016llx]", part->mask);
189 			for (item = part->item; item; item = item->next)
190 			{
191 				if (item->mask == item->value)
192 					sfprintf(sp, "[+%s?0x%016llx]", item->name, item->value);
193 				else
194 					sfprintf(sp, "[+%s?%llu]", item->name, item->value);
195 				if (item->map && optmap(sp, item->map))
196 					return -1;
197 			}
198 		}
199 	sfprintf(sp, "}\n");
200 	return 0;
201 }
202 
203 /*
204  * optget() info discipline function
205  */
206 
207 int
dssoptinfo(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)208 dssoptinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
209 {
210 	Dssdisc_t*	disc = ((Dssoptdisc_t*)dp)->disc;
211 	Dssstate_t*	state = dssstate(disc);
212 	Dsslib_t*	lib;
213 	Dssmeth_t*	meth;
214 	Dssformat_t*	format;
215 	Cxmap_t*	mp;
216 	Cxtype_t*	tp;
217 	Cxvariable_t*	vp;
218 	long		pos;
219 	int		all;
220 	int		head;
221 	char		name[64];
222 
223 	switch (*s)
224 	{
225 	case 'd':
226 		if (*(s + 1) == 'e' && *(s + 2) == 't')
227 		{
228 			/* details */
229 			tp = (Cxtype_t*)((Dssoptdisc_t*)dp)->header;
230 			if (tp->format.description && optesc(sp, tp->format.description, 0))
231 				return -1;
232 		}
233 		else
234 		{
235 			/* description */
236 			sfprintf(sp, "%s", state->cx->header ? state->cx->header->description : "unknown-description");
237 		}
238 		return 0;
239 	case 'i':
240 		/* ident|index */
241 		if (state->cx->header)
242 			sfprintf(sp, "%s - %s", state->cx->header->name, state->cx->header->description);
243 		else
244 			sfprintf(sp, "unknown - description");
245 		return 0;
246 	case 'm':
247 		if (*(s + 1) == 'a')
248 		{
249 			/* match */
250 			tp = (Cxtype_t*)((Dssoptdisc_t*)dp)->header;
251 			if (tp->match && optesc(sp, tp->match->description, 0))
252 				return -1;
253 		}
254 		else
255 		{
256 			/* methods */
257 			for (lib = dsslib(NiL, DSS_VERBOSE, disc); lib; lib = (Dsslib_t*)dtnext(state->cx->libraries, lib))
258 				if (lib->meth && optout(sp, lib->meth->name, NiL, NiL, NiL, lib->meth->description, NiL))
259 					return -1;
260 		}
261 		return 0;
262 	case 'n':
263 		/* name */
264 		sfprintf(sp, "%s", state->cx->header ? state->cx->header->name : "unknown-name");
265 		return 0;
266 	case 'p':
267 		/* default print format */
268 		if (state->meth && state->meth->print)
269 			sfprintf(sp, "\"%s\"", state->meth->print);
270 		else
271 			sfprintf(sp, "undefined");
272 		return 0;
273 	case 't':
274 		/* type */
275 		sfputc(sp, '{');
276 		if (opttype(sp, (Cxtype_t*)((Dssoptdisc_t*)dp)->header, 1))
277 			return -1;
278 		sfputc(sp, '}');
279 		return 0;
280 	}
281 	if (!(meth = state->meth) && !(meth = state->global))
282 	{
283 		sfprintf(sp, "[+NOTE::?Specify \b--method\b=\amethod\a for a list of supported \b%s\b.]", s);
284 		return 0;
285 	}
286 	pos = sfstrtell(sp);
287 	head = 0;
288 	switch (*s)
289 	{
290 	case 'f':
291 		if (*(s + 1) != 'i')
292 		{
293 			/* formats */
294 			if ((head = !!strchr(s, ' ')) && meth->description && optout(sp, meth->name, NiL, NiL, NiL, meth->description, NiL))
295 				return -1;
296 			if (meth->formats && dtsize(meth->formats))
297 			{
298 				if (optout(sp, "----- formats -----", NiL, NiL, NiL, NiL, NiL))
299 					return -1;
300 				for (format = (Dssformat_t*)dtfirst(meth->formats); format; format = (Dssformat_t*)dtnext(meth->formats, format))
301 					if (optout(sp, format->name, NiL, NiL, NiL, format->description, NiL))
302 						return -1;
303 			}
304 			if (!head)
305 				break;
306 		}
307 		/*FALLTHROUGH*/
308 	case 'v':
309 		/* fields|variables */
310 		all = !state->meth || meth->cx && (!meth->cx->fields || !dtsize(meth->cx->fields));
311 		if (head)
312 			head = 0;
313 		else if (meth->description && optout(sp, meth->name, NiL, NiL, NiL, meth->description, NiL))
314 			return -1;
315 		for (tp = (Cxtype_t*)dtfirst(state->cx->types); tp; tp = (Cxtype_t*)dtnext(state->cx->types, tp))
316 			if (all || (tp->base || tp->match) && (tp->header.flags & CX_REFERENCED))
317 			{
318 				if (!head)
319 				{
320 					if (optout(sp, "----- data types -----", NiL, NiL, NiL, NiL, NiL))
321 						return -1;
322 					head = 1;
323 				}
324 				if (opttype(sp, tp, 0))
325 					return -1;
326 			}
327 		head = 0;
328 		for (mp = (Cxmap_t*)dtfirst(state->cx->maps); mp; mp = (Cxmap_t*)dtnext(state->cx->maps, mp))
329 			if (all || (mp->header.flags & CX_REFERENCED))
330 			{
331 				if (!head)
332 				{
333 					if (optout(sp, "----- data maps -----", NiL, NiL, NiL, NiL, NiL))
334 						return -1;
335 					head = 1;
336 				}
337 				if (optout(sp, mp->name, NiL, NiL, NiL, mp->description, NiL))
338 					return -1;
339 				if (optmap(sp, mp))
340 					return -1;
341 			}
342 		if (all && meth->cx && meth->cx->variables)
343 		{
344 			head = 0;
345 			for (vp = (Cxvariable_t*)dtfirst(meth->cx->variables); vp; vp = (Cxvariable_t*)dtnext(meth->cx->variables, vp))
346 				if (vp->prototype)
347 				{
348 					if (!head)
349 					{
350 						if (optout(sp, "----- functions -----", NiL, NiL, NiL, NiL, NiL))
351 							return -1;
352 						head = 1;
353 					}
354 					if (optout(sp, vp->name, vp->prototype, NiL, vp->type->name, vp->description, NiL))
355 						return -1;
356 				}
357 		}
358 		head = 0;
359 		if (!all)
360 			for (vp = (Cxvariable_t*)dtfirst(meth->cx->fields); vp; vp = (Cxvariable_t*)dtnext(meth->cx->fields, vp))
361 			{
362 				if (!head)
363 				{
364 					if (optout(sp, "----- data fields -----", NiL, NiL, NiL, NiL, NiL))
365 						return -1;
366 					head = 1;
367 				}
368 				if (optout(sp, vp->name, vp->type->name, vp->format.map ? vp->format.map->name : (char*)0, NiL, vp->description, NiL))
369 					return -1;
370 			}
371 		else if (meth->data)
372 			for (vp = (Cxvariable_t*)meth->data; vp->name; vp++)
373 			{
374 				if (!head)
375 				{
376 					if (optout(sp, "----- data fields -----", NiL, NiL, NiL, NiL, NiL))
377 						return -1;
378 					head = 1;
379 				}
380 				sfsprintf(name, sizeof(name), ".%s", vp->name);
381 				if (optout(sp, name, (char*)vp->type, vp->format.map ? vp->format.map->name : (char*)0, NiL, vp->description, NiL))
382 					return -1;
383 			}
384 		break;
385 	}
386 	if (sfstrtell(sp) == pos)
387 		sfprintf(sp, "[+NOTE::?Specify a method schema to list the %s.]", s);
388 	return 0;
389 }
390 
391 /*
392  * generate lib info usage
393  */
394 
395 int
dssoptlib(Sfio_t * sp,Dsslib_t * lib,const char * usage,Dssdisc_t * disc)396 dssoptlib(Sfio_t* sp, Dsslib_t* lib, const char* usage, Dssdisc_t* disc)
397 {
398 	register int	i;
399 	register char*	s;
400 	Dssstate_t*	state = dssstate(disc);
401 
402 	if (lib->libraries)
403 		for (i = 0; lib->libraries[i]; i++)
404 			if (!dssload(lib->libraries[i], disc))
405 				return -1;
406 	if (dssadd(lib, disc))
407 		return -1;
408 	if (lib->description && (s = strchr(lib->description, '[')))
409 	{
410 		sfprintf(sp, "%s[+PLUGIN?%s - %-.*s]\n", s, lib->name, s - lib->description, lib->description);
411 	}
412 	else
413 		sfprintf(sp, "[-1ls5Pp0?][+PLUGIN?%s - %s]\n", lib->name, lib->description ? lib->description : "support library");
414 	if (usage)
415 		sfprintf(sp, "%s", usage);
416 	if (lib->meth)
417 	{
418 		if (!state->meth)
419 			state->meth = lib->meth;
420 		if (!usage || strncmp(usage, "[+DESCRIPTION?", 13))
421 			sfprintf(sp, "[+DESCRIPTION?The %s method handles %s.]\n", lib->meth->name, lib->meth->description);
422 		sfprintf(sp, "{\fformats and variables\f}\n\n--method=%s[,option...]\n\n", lib->meth->name);
423 	}
424 	if (lib->types)
425 	{
426 		sfprintf(sp, "[+TYPES]{\n");
427 		for (i = 0; lib->types[i].name; i++)
428 			if (opttype(sp, &lib->types[i], 1))
429 				return -1;
430 		sfprintf(sp, "}\n");
431 	}
432 	if (lib->maps)
433 	{
434 		sfprintf(sp, "[+MAPS]{\n");
435 		for (i = 0; lib->maps[i]; i++)
436 			if (optout(sp, lib->maps[i]->name, NiL, NiL, NiL, lib->maps[i]->description, NiL))
437 				return -1;
438 			else if (optmap(sp, lib->maps[i]))
439 				return -1;
440 		sfprintf(sp, "}\n");
441 	}
442 	if (lib->callouts)
443 	{
444 		sfprintf(sp, "[+CALLOUTS]{\n");
445 		for (i = 0; lib->callouts[i].callout; i++)
446 			if (optout(sp, cxopname(lib->callouts[i].op.code, lib->callouts[i].op.type1, lib->callouts[i].op.type2), NiL, NiL, NiL, lib->callouts[i].description, NiL))
447 				return -1;
448 		sfprintf(sp, "}\n");
449 	}
450 	if (lib->recodes)
451 	{
452 		sfprintf(sp, "[+RECODES]{\n");
453 		for (i = 0; lib->recodes[i].recode; i++)
454 			if (optout(sp, cxopname(lib->recodes[i].op.code, lib->recodes[i].op.type1, lib->recodes[i].op.type2), NiL, NiL, NiL, lib->recodes[i].description, NiL))
455 				return -1;
456 		sfprintf(sp, "}\n");
457 	}
458 	if (lib->queries)
459 	{
460 		sfprintf(sp, "[+QUERIES]{\n");
461 		for (i = 0; lib->queries[i].name; i++)
462 			if (optout(sp, lib->queries[i].name, NiL, NiL, NiL, lib->queries[i].description, lib->queries[i].method ? sfprints("Limited to methods matching \"%s\".", lib->queries[i].method) : (char*)0))
463 				return -1;
464 		sfprintf(sp, "}\n");
465 	}
466 	if (lib->constraints)
467 	{
468 		sfprintf(sp, "[+CONSTRAINTS]{\n");
469 		for (i = 0; lib->constraints[i].name; i++)
470 			if (optout(sp, lib->constraints[i].name, NiL, NiL, NiL, lib->constraints[i].description, NiL))
471 				return -1;
472 		sfprintf(sp, "}\n");
473 	}
474 	if (lib->edits)
475 	{
476 		sfprintf(sp, "[+EDITS]{\n");
477 		for (i = 0; lib->edits[i].name; i++)
478 			if (optout(sp, lib->edits[i].name, NiL, NiL, NiL, lib->edits[i].description, NiL))
479 				return -1;
480 		sfprintf(sp, "}\n");
481 	}
482 	if (lib->functions)
483 	{
484 		sfprintf(sp, "[+FUNCTIONS]{\n");
485 		for (i = 0; lib->functions[i].name; i++)
486 			if (optout(sp, lib->functions[i].name, lib->functions[i].prototype, NiL, (lib->functions[i].header.flags & CX_INITIALIZED) ? lib->functions[i].type->name : (char*)lib->functions[i].type, lib->functions[i].description, NiL))
487 				return -1;
488 		sfprintf(sp, "}\n");
489 	}
490 	return 0;
491 }
492