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