0
|
1 /*
|
|
2 * Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
|
3 * All rights reserved.
|
|
4 */
|
|
5 /*
|
|
6 #pragma ident "@(#)browse.c 1.3 00/07/17 SMI"
|
|
7 * Copyright (c) 1994
|
|
8 * Open Software Foundation, Inc.
|
|
9 *
|
|
10 * Permission is hereby granted to use, copy, modify and freely distribute
|
|
11 * the software in this file and its documentation for any purpose without
|
|
12 * fee, provided that the above copyright notice appears in all copies and
|
|
13 * that both the copyright notice and this permission notice appear in
|
|
14 * supporting documentation. Further, provided that the name of Open
|
|
15 * Software Foundation, Inc. ("OSF") not be used in advertising or
|
|
16 * publicity pertaining to distribution of the software without prior
|
|
17 * written permission from OSF. OSF makes no representations about the
|
|
18 * suitability of this software for any purpose. It is provided "as is"
|
|
19 * without express or implied warranty.
|
|
20 */
|
|
21 /*
|
|
22 * Copyright (c) 1996 X Consortium
|
|
23 * Copyright (c) 1995, 1996 Dalrymple Consulting
|
|
24 *
|
|
25 * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
26 * of this software and associated documentation files (the "Software"), to deal
|
|
27 * in the Software without restriction, including without limitation the rights
|
|
28 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
29 * copies of the Software, and to permit persons to whom the Software is
|
|
30 * furnished to do so, subject to the following conditions:
|
|
31 *
|
|
32 * The above copyright notice and this permission notice shall be included in
|
|
33 * all copies or substantial portions of the Software.
|
|
34 *
|
|
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
38 * X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
39 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
40 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
41 * OTHER DEALINGS IN THE SOFTWARE.
|
|
42 *
|
|
43 * Except as contained in this notice, the names of the X Consortium and
|
|
44 * Dalrymple Consulting shall not be used in advertising or otherwise to
|
|
45 * promote the sale, use or other dealings in this Software without prior
|
|
46 * written authorization.
|
|
47 */
|
|
48
|
|
49 /* ________________________________________________________________________
|
|
50 *
|
|
51 * Module for interactive browsing.
|
|
52 *
|
|
53 * Entry points for this module:
|
|
54 * Browse() interactive browser
|
|
55 * ________________________________________________________________________
|
|
56 */
|
|
57
|
|
58 #ifndef lint
|
|
59 static char *RCSid =
|
|
60 "$Header: /usr/src/docbook-to-man/Instant/RCS/browse.c,v 1.2 1996/06/02 21:46:10 fld Exp $";
|
|
61 #endif
|
|
62
|
|
63 #include <stdio.h>
|
|
64 #include <stdlib.h>
|
|
65 #include <ctype.h>
|
|
66 #include <string.h>
|
|
67
|
|
68 #include "general.h"
|
|
69
|
|
70 static void PrElemPlusID(Element_t *);
|
|
71 static void ls_node(Element_t *, int, char **);
|
|
72 static void do_query(Element_t *, char *, char *);
|
|
73 static void do_find(Element_t *, char **);
|
|
74
|
|
75 /* ______________________________________________________________________ */
|
|
76
|
|
77 static char *br_help_msg[] = {
|
|
78 " ls List info about current element in tree",
|
|
79 " (context, children, attributes, etc.)",
|
|
80 " cd N ... Change to Nth elememt child, where N is shown by 'ls'.",
|
|
81 " N may also be '/' (top) or '..' (up).",
|
|
82 " cd id I Change to elememt whose ID is I",
|
|
83 " data N Show data of Nth data node",
|
|
84 " where Show current position in the tree",
|
|
85 " id I Show path to element with id I",
|
|
86 " (using '?' for I will lists all IDs and their paths)",
|
|
87 " find S Find elements matching spec S. Recognized syntaxes:",
|
|
88 " find attr <name> <value>",
|
|
89 " find cont <string>",
|
|
90 " find parent <gi-name>",
|
|
91 " find child <gi-name>",
|
|
92 " find gi <gi-name>",
|
|
93 " q rel gi Query: report if elem 'gi' has relation to current elem",
|
|
94 " ('rel' is one of 'child parent ancestor descendant",
|
|
95 " sibling sibling+ sibling+1 sibling- sibling-1 cousin')",
|
|
96 "",
|
|
97 " tran file [outfile]",
|
|
98 " With trans spec in 'file' translate into 'outfile' (stdout)",
|
|
99 " sdata file Read SDATA map file (for translations).",
|
|
100 " cmap file Read character map file (for translations).",
|
|
101 " stat Print statistics (how often elements occur, etc.)",
|
|
102 " sum Print elem usage summary (# of children, depth, etc.)",
|
|
103 " tree Print document hierarchy as a tree",
|
|
104 " cont Print context of each element",
|
|
105 NULL
|
|
106 };
|
|
107
|
|
108 /* ______________________________________________________________________ */
|
|
109
|
|
110 void
|
|
111 Browse()
|
|
112 {
|
|
113 char buf[256], *cmd, **av, **sv, *cmapfile, *sdatafile;
|
|
114 char *Prompt;
|
|
115 Element_t *ce; /* current element */
|
|
116 Element_t *e;
|
|
117 int i, n, ac;
|
|
118
|
|
119 if (slave) Prompt = "=>\n";
|
|
120 else Prompt = "=> ";
|
|
121
|
|
122 ce = DocTree;
|
|
123 while (fputs(Prompt, stdout)) {
|
|
124 if (!fgets(buf, 256, stdin)) break;
|
|
125 stripNL(buf);
|
|
126 if (buf[0] == EOS) {
|
|
127 fputs(Prompt, stdout);
|
|
128 continue;
|
|
129 }
|
|
130 ac = 20;
|
|
131 av = Split(buf, &ac, S_ALVEC);
|
|
132 if (ac > 0) cmd = av[0];
|
|
133 if (!cmd || !(*cmd)) continue;
|
|
134
|
|
135 if (!strcmp(cmd, "ls")) ls_node(ce, ac, av);
|
|
136
|
|
137 else if (!strcmp(cmd, "cd")) {
|
|
138 if (av[1]) {
|
|
139 if (ac == 3 && !strcmp(av[1], "id")) {
|
|
140 if ((e = FindElemByID(av[2]))) ce = e;
|
|
141 else printf("Element with ID '%s' not found.\n", av[2]);
|
|
142 continue;
|
|
143 }
|
|
144 for (i=1; i<ac; i++) {
|
|
145 if (!strcmp(av[i], "..")) {
|
|
146 if (ce->parent) ce = ce->parent;
|
|
147 continue;
|
|
148 }
|
|
149 if (!strcmp(av[i], "/")) {
|
|
150 if (ce->parent) ce = DocTree;
|
|
151 continue;
|
|
152 }
|
|
153 if (!isdigit(*av[i])) {
|
|
154 printf("Expecting digit, '..', or '/', got '%s'.\n",
|
|
155 av[i]);
|
|
156 break;
|
|
157 }
|
|
158 n = atoi(av[i]);
|
|
159 if (n < ce->necont) ce = ce->econt[n];
|
|
160 else {
|
|
161 printf("Must be in range 0 - %d.\n", ce->necont);
|
|
162 break;
|
|
163 }
|
|
164 }
|
|
165 }
|
|
166 }
|
|
167
|
|
168 else if (!strcmp(cmd, "data")) {
|
|
169 if (av[1] && isdigit(*av[1])) {
|
|
170 n = atoi(av[1]);
|
|
171 if (n < ce->ndcont) {
|
|
172 printf(ce->dcont[n]);
|
|
173 fputs("\n", stdout);
|
|
174 }
|
|
175 else if (ce->ndcont == 0)
|
|
176 printf("No data at this node.\n");
|
|
177 else printf("Must be in range 0 - %d.\n", ce->ndcont);
|
|
178 }
|
|
179 }
|
|
180
|
|
181 /* show where we are in the tree */
|
|
182 else if (!strcmp(cmd, "where")) PrintLocation(ce, stdout);
|
|
183
|
|
184 /* show where we are in the tree */
|
|
185 else if (!strcmp(cmd, "pwd")) PrElemPlusID(ce);
|
|
186
|
|
187 /* perform query with yes/no answer */
|
|
188 else if (!strcmp(cmd, "q") && av[1] && av[2])
|
|
189 do_query(ce, av[1], av[2]);
|
|
190
|
|
191 /* perform query printing paths to matching elements */
|
|
192 else if (!strcmp(cmd, "find") && av[1] && av[2])
|
|
193 do_find(ce, av);
|
|
194
|
|
195 /* list locations where specified ID(s) occur */
|
|
196 else if (!strcmp(cmd, "id")) {
|
|
197 if (ac <= 1) continue;
|
|
198 if (*av[1] == '?') PrintIDList();
|
|
199 else {
|
|
200 /* short: "id i1 i2 ...", long: "id -l i1 i2 ..." */
|
|
201 if (!strcmp(av[1], "-l")) n = 2;
|
|
202 else n = 1;
|
|
203 for (i=n; i<ac; i++) {
|
|
204 if ((e = FindElemByID(av[i]))) {
|
|
205 if (n == 2) { /* long (multiline) format */
|
|
206 if (n != i) putchar('\n');
|
|
207 PrintLocation(e, stdout);
|
|
208 }
|
|
209 else PrElemPlusID(e);
|
|
210 }
|
|
211 else printf("Element with ID '%s' not found.\n", av[i]);
|
|
212 }
|
|
213 }
|
|
214 }
|
|
215
|
|
216 /* show and set variables */
|
|
217 else if (!strcmp(cmd, "show") && av[1]) {
|
|
218 printf("%s\n", FindMappingVal(Variables, av[1]));
|
|
219 }
|
|
220 else if (!strcmp(cmd, "set") && av[1] && av[2]) {
|
|
221 SetMappingNV(Variables, av[1], av[2]);
|
|
222 }
|
|
223
|
|
224 /* print summary of tag usage */
|
|
225 else if (!strcmp(cmd, "sum")) {
|
|
226 if (ac > 1) PrintElemSummary(ce);
|
|
227 else PrintElemSummary(DocTree);
|
|
228 }
|
|
229 /* print element tree */
|
|
230 else if (!strcmp(cmd, "tree")) {
|
|
231 if (ac > 1) PrintElemTree(ce);
|
|
232 else PrintElemTree(DocTree);
|
|
233 }
|
|
234 /* print statistics */
|
|
235 else if (!strcmp(cmd, "stat")) {
|
|
236 if (ac > 1) PrintStats(ce);
|
|
237 else PrintStats(DocTree);
|
|
238 }
|
|
239 /* print context of each element of tree */
|
|
240 else if (!strcmp(cmd, "cont")) {
|
|
241 if (ac > 1) PrintContext(ce);
|
|
242 else PrintContext(DocTree);
|
|
243 }
|
|
244 /* print translation, given transpec */
|
|
245 else if (!strcmp(cmd, "tran")) {
|
|
246 FILE *fp;
|
|
247 if (ac > 2){
|
|
248 if (!(fp = fopen(av[2], "w"))) {
|
|
249 perror("Can not open output file");
|
|
250 continue;
|
|
251 }
|
|
252 }
|
|
253 else fp = stdout;
|
|
254 DoTranslate(ce, av[1], fp);
|
|
255 if (ac > 2) fclose(fp);
|
|
256 }
|
|
257 else if (!strcmp(cmd, "sdata")){
|
|
258 sdatafile = strdup(av[1]);
|
|
259 ReadSDATA(sdatafile);
|
|
260 }
|
|
261 else if (!strcmp(cmd, "cmap")){
|
|
262 cmapfile = strdup(av[1]);
|
|
263 ReadCharMap(cmapfile);
|
|
264 }
|
|
265
|
|
266 else if (!strcmp(cmd, "help") || *cmd == '?') {
|
|
267 sv = br_help_msg;
|
|
268 while (*sv) puts(*sv++);
|
|
269 }
|
|
270
|
|
271 /* quit (control-D also works) */
|
|
272 else if (!strcmp(cmd, "quit")) break;
|
|
273
|
|
274 else
|
|
275 fprintf(stderr, "Unknown command '%s' - ingored.\n", cmd);
|
|
276 }
|
|
277 putc(NL, stdout);
|
|
278 }
|
|
279
|
|
280 /* ______________________________________________________________________ */
|
|
281 /* Do the "ls" command.
|
|
282 * Arguments:
|
|
283 * Pointer to element under consideration.
|
|
284 * Arg count from command line (this command, not the shell command).
|
|
285 * Arg vector.
|
|
286 */
|
|
287
|
|
288 static void
|
|
289 ls_node(
|
|
290 Element_t *e,
|
|
291 int ac,
|
|
292 char **av
|
|
293 )
|
|
294 {
|
|
295 int i;
|
|
296 char buf[LINESIZE];
|
|
297
|
|
298 if (ac > 1 && !strcmp(av[1], "-n")) {
|
|
299 for(i=0; i<e->ncont; i++) {
|
|
300 if (IsContElem(e,i)) printf("%s\n", ContElem(e,i)->gi);
|
|
301 else if (IsContData(e,i)) printf("#data %s\n", ContData(e,i));
|
|
302 else if (IsContPI(e,i)) printf("#pi %s\n", ContData(e,i));
|
|
303 }
|
|
304 return;
|
|
305 }
|
|
306
|
|
307 printf("Element: %s\tLineNumber: %d\n", e->gi, e->lineno);
|
|
308 if (e->parent)
|
|
309 printf("Context: %s\n", FindContext(e, 20, buf));
|
|
310
|
|
311 if (e->natts) {
|
|
312 printf("%d attributes:\n", e->natts);
|
|
313 for (i=0; i<e->natts; i++)
|
|
314 printf("\t%2d: %s = '%s'\n", i, e->atts[i].name, e->atts[i].sval);
|
|
315 }
|
|
316 if (e->entity) {
|
|
317 printf("Entity & notation information:\n");
|
|
318 if (e->entity->ename)
|
|
319 printf("Entity name: %s\n", e->entity->ename);
|
|
320 if (e->entity->nname)
|
|
321 printf("Notation name: %s\n", e->entity->nname);
|
|
322 if (e->entity->sysid)
|
|
323 printf("Sys id: %s\n", e->entity->sysid);
|
|
324 if (e->entity->pubid)
|
|
325 printf("Pub id: %s\n", e->entity->pubid);
|
|
326 if (e->entity->fname)
|
|
327 printf("Filename: %s\n", e->entity->fname);
|
|
328 }
|
|
329
|
|
330 if (e->my_eorder >= 0)
|
|
331 printf("My order among my siblings: %d\n", e->my_eorder);
|
|
332
|
|
333 if (e->necont) {
|
|
334 printf("%d child element nodes:\n", e->necont);
|
|
335 for(i=0; i<e->necont; i++) printf("\t%2d: %s\n", i, e->econt[i]->gi);
|
|
336 }
|
|
337
|
|
338 if (e->ndcont) {
|
|
339 printf("%d child data nodes:\n", e->ndcont);
|
|
340 for(i=0; i<e->ndcont; i++) {
|
|
341 if (strlen(e->dcont[i]) < 40)
|
|
342 printf("\t%2d: %s\n", i, e->dcont[i]);
|
|
343 else
|
|
344 printf("\t%2d: %-40.40s...\n", i, e->dcont[i]);
|
|
345 }
|
|
346 }
|
|
347 }
|
|
348
|
|
349 /* ______________________________________________________________________ */
|
|
350 /* Perform query. Syntax: find relationship gi. Tells whether gi has
|
|
351 * given relationship to current element. Result (message) sent to stdout.
|
|
352 * Args:
|
|
353 * Pointer to element under consideration.
|
|
354 * Pointer to name of relationship. (see FindRelByName() for names)
|
|
355 * Pointer to GI to look for.
|
|
356 */
|
|
357
|
|
358 static void
|
|
359 do_query(
|
|
360 Element_t *e,
|
|
361 char *rel,
|
|
362 char *gi
|
|
363 )
|
|
364 {
|
|
365 char *cp;
|
|
366 Relation_t r;
|
|
367 Element_t *ep;
|
|
368
|
|
369 for (cp=gi; *cp; cp++) if (islower(*cp)) *cp = toupper(*cp);
|
|
370
|
|
371 if ((r = FindRelByName(rel)) == REL_Unknown) {
|
|
372 return;
|
|
373 }
|
|
374 ep = QRelation(e, gi, r);
|
|
375 printf("%s, '%s' is%s %s of '%s'.\n", (ep ? "Yes" : "No"), gi,
|
|
376 (ep ? "" : " not"), rel, e->gi);
|
|
377 }
|
|
378
|
|
379 /* ______________________________________________________________________ */
|
|
380 /* Print path to the element and its ID (if it has one) on a single line.
|
|
381 * Arguments:
|
|
382 * Pointer to element under consideration.
|
|
383 */
|
|
384 static void
|
|
385 PrElemPlusID(
|
|
386 Element_t *e
|
|
387 )
|
|
388 {
|
|
389 char buf[LINESIZE];
|
|
390
|
|
391 if (e->id) printf("%s -- ID=%s\n", FindElementPath(e, buf), e->id);
|
|
392 else printf("%s\n", FindElementPath(e, buf));
|
|
393 }
|
|
394
|
|
395 /* ______________________________________________________________________ */
|
|
396 /* Print path to the element and its ID (if it has one) on a single line.
|
|
397 * Arguments:
|
|
398 * Pointer to element under consideration.
|
|
399 */
|
|
400
|
|
401 static void
|
|
402 match_gi(
|
|
403 Element_t *e,
|
|
404 char **av
|
|
405 )
|
|
406 {
|
|
407 if (!strcmp(av[1], e->gi)) PrElemPlusID(e);
|
|
408 }
|
|
409
|
|
410 /* Shorthand for defining simple finctions, which are just interfaces to
|
|
411 * calling QRelation(). DescendTree() only passes ptr to element. */
|
|
412 #define MATCH(Fun,Rel) \
|
|
413 static void Fun(Element_t *e, char **av) \
|
|
414 { if (QRelation(e, av[1], Rel)) PrElemPlusID(e); }
|
|
415
|
|
416 MATCH(match_parent, REL_Parent)
|
|
417 MATCH(match_child, REL_Child)
|
|
418 MATCH(match_anc, REL_Ancestor)
|
|
419 MATCH(match_desc, REL_Descendant)
|
|
420 MATCH(match_sib, REL_Sibling)
|
|
421
|
|
422 static void
|
|
423 match_attr(
|
|
424 Element_t *e,
|
|
425 char **av
|
|
426 )
|
|
427 {
|
|
428 char *atval;
|
|
429
|
|
430 if ((atval = FindAttValByName(e, av[1])) && !strcmp(av[2], atval))
|
|
431 PrElemPlusID(e);
|
|
432 }
|
|
433
|
|
434 static void
|
|
435 match_cont(
|
|
436 Element_t *e,
|
|
437 char **av
|
|
438 )
|
|
439 {
|
|
440 int i;
|
|
441 for (i=0; i<e->ncont; i++) {
|
|
442 if (IsContData(e,i) && strstr(ContData(e,i), av[1])) {
|
|
443 PrElemPlusID(e);
|
|
444 return;
|
|
445 }
|
|
446 }
|
|
447 }
|
|
448
|
|
449 /* Find an element, given the criteria on its command line.
|
|
450 * Arguments:
|
|
451 * Pointer to element under consideration.
|
|
452 */
|
|
453 static void
|
|
454 do_find(
|
|
455 Element_t *e,
|
|
456 char **av
|
|
457 )
|
|
458 {
|
|
459 av++;
|
|
460 if (!strcmp(av[0], ".")) av++;
|
|
461 else e = DocTree;
|
|
462 if (!strcmp(av[0], "gi")) DescendTree(e, match_gi, 0, 0, av);
|
|
463 else if (!strcmp(av[0], "attr")) DescendTree(e, match_attr, 0, 0, av);
|
|
464 else if (!strcmp(av[0], "parent")) DescendTree(e, match_parent, 0, 0, av);
|
|
465 else if (!strcmp(av[0], "child")) DescendTree(e, match_child, 0, 0, av);
|
|
466 else if (!strcmp(av[0], "cont")) DescendTree(e, match_cont, 0, 0, av);
|
|
467 else if (!strcmp(av[0], "sib")) DescendTree(e, match_sib, 0, 0, av);
|
|
468 else if (!strcmp(av[0], "desc")) DescendTree(e, match_desc, 0, 0, av);
|
|
469 else if (!strcmp(av[0], "anc")) DescendTree(e, match_anc, 0, 0, av);
|
|
470 else fprintf(stderr, "Unknown find command: %s.\n", av[0]);
|
|
471 }
|
|
472
|
|
473 /* ______________________________________________________________________ */
|