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