2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
25 * All rights reserved.
29 * Open Software Foundation, Inc.
31 * Permission is hereby granted to use, copy, modify and freely distribute
32 * the software in this file and its documentation for any purpose without
33 * fee, provided that the above copyright notice appears in all copies and
34 * that both the copyright notice and this permission notice appear in
35 * supporting documentation. Further, provided that the name of Open
36 * Software Foundation, Inc. ("OSF") not be used in advertising or
37 * publicity pertaining to distribution of the software without prior
38 * written permission from OSF. OSF makes no representations about the
39 * suitability of this software for any purpose. It is provided "as is"
40 * without express or implied warranty.
42 /* ________________________________________________________________________
44 * Module for interactive browsing.
46 * Entry points for this module:
47 * Browse() interactive browser
48 * ________________________________________________________________________
53 "$XConsortium: browse.c /main/3 1996/06/19 17:13:03 drk $";
63 static void PrElemPlusID(Element_t *);
64 static void ls_node(Element_t *, int, char **);
65 static void do_query(Element_t *, char *, char *);
66 static void do_find(Element_t *, char **);
68 /* ______________________________________________________________________ */
70 static char *br_help_msg[] = {
71 " ls List info about current element in tree",
72 " (context, children, attributes, etc.)",
73 " cd N ... Change to Nth elememt child, where N is shown by 'ls'.",
74 " N may also be '/' (top) or '..' (up).",
75 " cd id I Change to elememt whose ID is I",
76 " data N Show data of Nth data node",
77 " where Show current position in the tree",
78 " id I Show path to element with id I",
79 " (using '?' for I will lists all IDs and their paths)",
80 " find S Find elements matching spec S. Recognized syntaxes:",
81 " find attr <name> <value>",
82 " find cont <string>",
83 " find parent <gi-name>",
84 " find child <gi-name>",
86 " q rel gi Query: report if elem 'gi' has relation to current elem",
87 " ('rel' is one of 'child parent ancestor descendant",
88 " sibling sibling+ sibling+1 sibling- sibling-1 cousin')",
90 " tran file [outfile]",
91 " With trans spec in 'file' translate into 'outfile' (stdout)",
92 " sdata file Read SDATA map file (for translations).",
93 " cmap file Read character map file (for translations).",
94 " stat Print statistics (how often elements occur, etc.)",
95 " sum Print elem usage summary (# of children, depth, etc.)",
96 " tree Print document hierarchy as a tree",
97 " cont Print context of each element",
101 /* ______________________________________________________________________ */
106 char buf[256], *cmd, **av, **sv, *cmapfile, *sdatafile;
108 Element_t *ce; /* current element */
112 if (slave) Prompt = "=>\n";
116 while (fputs(Prompt, stdout)) {
117 if (!fgets(buf, 256, stdin)) break;
120 fputs(Prompt, stdout);
124 av = Split(buf, &ac, S_ALVEC);
125 if (ac > 0) cmd = av[0];
126 if (!cmd || !(*cmd)) continue;
128 if (!strcmp(cmd, "ls")) ls_node(ce, ac, av);
130 else if (!strcmp(cmd, "cd")) {
132 if (ac == 3 && !strcmp(av[1], "id")) {
133 if ((e = FindElemByID(av[2]))) ce = e;
134 else printf("Element with ID '%s' not found.\n", av[2]);
137 for (i=1; i<ac; i++) {
138 if (!strcmp(av[i], "..")) {
139 if (ce->parent) ce = ce->parent;
142 if (!strcmp(av[i], "/")) {
143 if (ce->parent) ce = DocTree;
146 if (!isdigit(*av[i])) {
147 printf("Expecting digit, '..', or '/', got '%s'.\n",
152 if (n < ce->necont) ce = ce->econt[n];
154 printf("Must be in range 0 - %d.\n", ce->necont);
161 else if (!strcmp(cmd, "data")) {
162 if (av[1] && isdigit(*av[1])) {
164 if (n < ce->ndcont) {
165 printf("%s", ce->dcont[n]);
168 else if (ce->ndcont == 0)
169 printf("No data at this node.\n");
170 else printf("Must be in range 0 - %d.\n", ce->ndcont);
174 /* show where we are in the tree */
175 else if (!strcmp(cmd, "where")) PrintLocation(ce, stdout);
177 /* show where we are in the tree */
178 else if (!strcmp(cmd, "pwd")) PrElemPlusID(ce);
180 /* perform query with yes/no answer */
181 else if (!strcmp(cmd, "q") && av[1] && av[2])
182 do_query(ce, av[1], av[2]);
184 /* perform query printing paths to matching elements */
185 else if (!strcmp(cmd, "find") && av[1] && av[2])
188 /* list locations where specified ID(s) occur */
189 else if (!strcmp(cmd, "id")) {
190 if (ac <= 1) continue;
191 if (*av[1] == '?') PrintIDList();
193 /* short: "id i1 i2 ...", long: "id -l i1 i2 ..." */
194 if (!strcmp(av[1], "-l")) n = 2;
196 for (i=n; i<ac; i++) {
197 if ((e = FindElemByID(av[i]))) {
198 if (n == 2) { /* long (multiline) format */
199 if (n != i) putchar('\n');
200 PrintLocation(e, stdout);
202 else PrElemPlusID(e);
204 else printf("Element with ID '%s' not found.\n", av[i]);
209 /* show and set variables */
210 else if (!strcmp(cmd, "show") && av[1]) {
211 printf("%s\n", FindMappingVal(Variables, av[1]));
213 else if (!strcmp(cmd, "set") && av[1] && av[2]) {
214 SetMappingNV(Variables, av[1], av[2]);
217 /* print summary of tag usage */
218 else if (!strcmp(cmd, "sum")) {
219 if (ac > 1) PrintElemSummary(ce);
220 else PrintElemSummary(DocTree);
222 /* print element tree */
223 else if (!strcmp(cmd, "tree")) {
224 if (ac > 1) PrintElemTree(ce);
225 else PrintElemTree(DocTree);
227 /* print statistics */
228 else if (!strcmp(cmd, "stat")) {
229 if (ac > 1) PrintStats(ce);
230 else PrintStats(DocTree);
232 /* print context of each element of tree */
233 else if (!strcmp(cmd, "cont")) {
234 if (ac > 1) PrintContext(ce);
235 else PrintContext(DocTree);
237 /* print translation, given transpec */
238 else if (!strcmp(cmd, "tran")) {
241 if (!(fp = fopen(av[2], "w"))) {
242 perror("Can not open output file");
247 DoTranslate(ce, av[1], fp);
248 if (ac > 2) fclose(fp);
250 else if (!strcmp(cmd, "sdata")){
251 sdatafile = strdup(av[1]);
252 ReadSDATA(sdatafile);
254 else if (!strcmp(cmd, "cmap")){
255 cmapfile = strdup(av[1]);
256 ReadCharMap(cmapfile);
259 else if (!strcmp(cmd, "help") || *cmd == '?') {
261 while (*sv) puts(*sv++);
264 /* quit (control-D also works) */
265 else if (!strcmp(cmd, "quit")) break;
268 fprintf(stderr, "Unknown command '%s' - ignored.\n", cmd);
273 /* ______________________________________________________________________ */
274 /* Do the "ls" command.
276 * Pointer to element under consideration.
277 * Arg count from command line (this command, not the shell command).
291 if (ac > 1 && !strcmp(av[1], "-n")) {
292 for(i=0; i<e->ncont; i++) {
293 if (IsContElem(e,i)) printf("%s\n", ContElem(e,i)->gi);
294 else if (IsContData(e,i)) printf("#data %s\n", ContData(e,i));
295 else if (IsContPI(e,i)) printf("#pi %s\n", ContData(e,i));
300 printf("Element: %s\tLineNumber: %d\n", e->gi, e->lineno);
302 printf("Context: %s\n", FindContext(e, 20, buf));
305 printf("%d attributes:\n", e->natts);
306 for (i=0; i<e->natts; i++)
307 printf("\t%2d: %s = '%s'\n", i, e->atts[i].name, e->atts[i].sval);
310 printf("Entity & notation information:\n");
311 if (e->entity->ename)
312 printf("Entity name: %s\n", e->entity->ename);
313 if (e->entity->nname)
314 printf("Notation name: %s\n", e->entity->nname);
315 if (e->entity->sysid)
316 printf("Sys id: %s\n", e->entity->sysid);
317 if (e->entity->pubid)
318 printf("Pub id: %s\n", e->entity->pubid);
319 if (e->entity->fname)
320 printf("Filename: %s\n", e->entity->fname);
323 if (e->my_eorder >= 0)
324 printf("My order among my siblings: %d\n", e->my_eorder);
327 printf("%d child element nodes:\n", e->necont);
328 for(i=0; i<e->necont; i++) printf("\t%2d: %s\n", i, e->econt[i]->gi);
332 printf("%d child data nodes:\n", e->ndcont);
333 for(i=0; i<e->ndcont; i++) {
334 if (strlen(e->dcont[i]) < 40)
335 printf("\t%2d: %s\n", i, e->dcont[i]);
337 printf("\t%2d: %-40.40s...\n", i, e->dcont[i]);
342 /* ______________________________________________________________________ */
343 /* Perform query. Syntax: find relationship gi. Tells whether gi has
344 * given relationship to current element. Result (message) sent to stdout.
346 * Pointer to element under consideration.
347 * Pointer to name of relationship. (see FindRelByName() for names)
348 * Pointer to GI to look for.
362 for (cp=gi; *cp; cp++) if (islower(*cp)) *cp = toupper(*cp);
364 if ((r = FindRelByName(rel)) == REL_Unknown) {
367 ep = QRelation(e, gi, r);
368 printf("%s, '%s' is%s %s of '%s'.\n", (ep ? "Yes" : "No"), gi,
369 (ep ? "" : " not"), rel, e->gi);
372 /* ______________________________________________________________________ */
373 /* Print path to the element and its ID (if it has one) on a single line.
375 * Pointer to element under consideration.
384 if (e->id) printf("%s -- ID=%s\n", FindElementPath(e, buf), e->id);
385 else printf("%s\n", FindElementPath(e, buf));
388 /* ______________________________________________________________________ */
389 /* Print path to the element and its ID (if it has one) on a single line.
391 * Pointer to element under consideration.
400 if (!strcmp(av[1], e->gi)) PrElemPlusID(e);
403 /* Shorthand for defining simple finctions, which are just interfaces to
404 * calling QRelation(). DescendTree() only passes ptr to element. */
405 #define MATCH(Fun,Rel) \
406 static void Fun(Element_t *e, char **av) \
407 { if (QRelation(e, av[1], Rel)) PrElemPlusID(e); }
409 MATCH(match_parent, REL_Parent)
410 MATCH(match_child, REL_Child)
411 MATCH(match_anc, REL_Ancestor)
412 MATCH(match_desc, REL_Descendant)
413 MATCH(match_sib, REL_Sibling)
423 if ((atval = FindAttValByName(e, av[1])) && !strcmp(av[2], atval))
434 for (i=0; i<e->ncont; i++) {
435 if (IsContData(e,i) && strstr(ContData(e,i), av[1])) {
442 /* Find an element, given the criteria on its command line.
444 * Pointer to element under consideration.
453 if (!strcmp(av[0], ".")) av++;
455 if (!strcmp(av[0], "gi")) DescendTree(e, match_gi, 0, 0, av);
456 else if (!strcmp(av[0], "attr")) DescendTree(e, match_attr, 0, 0, av);
457 else if (!strcmp(av[0], "parent")) DescendTree(e, match_parent, 0, 0, av);
458 else if (!strcmp(av[0], "child")) DescendTree(e, match_child, 0, 0, av);
459 else if (!strcmp(av[0], "cont")) DescendTree(e, match_cont, 0, 0, av);
460 else if (!strcmp(av[0], "sib")) DescendTree(e, match_sib, 0, 0, av);
461 else if (!strcmp(av[0], "desc")) DescendTree(e, match_desc, 0, 0, av);
462 else if (!strcmp(av[0], "anc")) DescendTree(e, match_anc, 0, 0, av);
463 else fprintf(stderr, "Unknown find command: %s.\n", av[0]);
466 /* ______________________________________________________________________ */