Spelling fixes
[oweals/cde.git] / cde / programs / dtdocbook / instant / browse.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /*
24  *  Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
25  *  All rights reserved.
26  */
27 /*
28  * Copyright (c) 1994  
29  * Open Software Foundation, Inc. 
30  *  
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. 
41  */
42 /* ________________________________________________________________________
43  *
44  *  Module for interactive browsing.
45  *
46  *  Entry points for this module:
47  *      Browse()                interactive browser
48  * ________________________________________________________________________
49  */
50
51 #ifndef lint
52 static char *RCSid =
53   "$XConsortium: browse.c /main/3 1996/06/19 17:13:03 drk $";
54 #endif
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <ctype.h>
59 #include <string.h>
60
61 #include "general.h"
62
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 **);
67
68 /* ______________________________________________________________________ */
69
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>",
85   "                  find gi <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')",
89   "",
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",
98   NULL
99 };
100
101 /* ______________________________________________________________________ */
102
103 void
104 Browse()
105 {
106     char        buf[256], *cmd, **av, **sv, *cmapfile, *sdatafile;
107     char        *Prompt;
108     Element_t   *ce;    /* current element */
109     Element_t   *e;
110     int         i, n, ac;
111
112     if (slave) Prompt = "=>\n";
113     else Prompt = "=> ";
114
115     ce = DocTree;
116     while (fputs(Prompt, stdout)) {
117         if (!fgets(buf, 256, stdin)) break;
118         stripNL(buf);
119         if (buf[0] == EOS) {
120             fputs(Prompt, stdout);
121             continue;
122         }
123         ac = 20;
124         av = Split(buf, &ac, S_ALVEC);
125         if (ac > 0) cmd = av[0];
126         if (!cmd || !(*cmd)) continue;
127
128         if (!strcmp(cmd, "ls")) ls_node(ce, ac, av);
129
130         else if (!strcmp(cmd, "cd")) {
131             if (av[1]) {
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]);
135                     continue;
136                 }
137                 for (i=1; i<ac; i++) {
138                     if (!strcmp(av[i], "..")) {
139                         if (ce->parent) ce = ce->parent;
140                         continue;
141                     }
142                     if (!strcmp(av[i], "/")) {
143                         if (ce->parent) ce = DocTree;
144                         continue;
145                     }
146                     if (!isdigit(*av[i])) {
147                         printf("Expecting digit, '..', or '/', got '%s'.\n",
148                                     av[i]);
149                         break;
150                     }
151                     n = atoi(av[i]);
152                     if (n < ce->necont) ce = ce->econt[n];
153                     else {
154                         printf("Must be in range 0 - %d.\n", ce->necont);
155                         break;
156                     }
157                 }
158             }
159         }
160
161         else if (!strcmp(cmd, "data")) {
162             if (av[1] && isdigit(*av[1])) {
163                 n = atoi(av[1]);
164                 if (n < ce->ndcont) {
165                     printf("%s", ce->dcont[n]);
166                     fputs("\n", stdout);
167                 }
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);
171             }
172         }
173
174         /* show where we are in the tree */
175         else if (!strcmp(cmd, "where")) PrintLocation(ce, stdout);
176
177         /* show where we are in the tree */
178         else if (!strcmp(cmd, "pwd")) PrElemPlusID(ce);
179
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]);
183
184         /* perform query printing paths to matching elements */
185         else if (!strcmp(cmd, "find") && av[1] && av[2])
186             do_find(ce, av);
187
188         /* list locations where specified ID(s) occur */
189         else if (!strcmp(cmd, "id")) {
190             if (ac <= 1) continue;
191             if (*av[1] == '?') PrintIDList();
192             else {
193                 /* short: "id i1 i2 ...", long: "id -l i1 i2 ..." */
194                 if (!strcmp(av[1], "-l")) n = 2;
195                 else n = 1;
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);
201                         }
202                         else PrElemPlusID(e);
203                     }
204                     else printf("Element with ID '%s' not found.\n", av[i]);
205                 }
206             }
207         }
208
209         /* show and set variables */
210         else if (!strcmp(cmd, "show") && av[1]) {
211             printf("%s\n", FindMappingVal(Variables, av[1]));
212         }
213         else if (!strcmp(cmd, "set") && av[1] && av[2]) {
214             SetMappingNV(Variables, av[1], av[2]);
215         }
216
217         /* print summary of tag usage */
218         else if (!strcmp(cmd, "sum")) {
219             if (ac > 1) PrintElemSummary(ce);
220             else PrintElemSummary(DocTree);
221         }
222         /* print element tree */
223         else if (!strcmp(cmd, "tree")) {
224             if (ac > 1) PrintElemTree(ce);
225             else PrintElemTree(DocTree);
226         }
227         /* print statistics */
228         else if (!strcmp(cmd, "stat")) {
229             if (ac > 1) PrintStats(ce);
230             else PrintStats(DocTree);
231         }
232         /* print context of each element of tree */
233         else if (!strcmp(cmd, "cont")) {
234             if (ac > 1) PrintContext(ce);
235             else PrintContext(DocTree);
236         }
237         /* print translation, given transpec */
238         else if (!strcmp(cmd, "tran")) {
239             FILE *fp;
240             if (ac > 2){
241                 if (!(fp = fopen(av[2], "w"))) {
242                     perror("Can not open output file");
243                     continue;
244                 }
245             }
246             else fp = stdout;
247             DoTranslate(ce, av[1], fp);
248             if (ac > 2) fclose(fp);
249         }
250         else if (!strcmp(cmd, "sdata")){
251             sdatafile = strdup(av[1]);
252             ReadSDATA(sdatafile);
253         }
254         else if (!strcmp(cmd, "cmap")){
255             cmapfile = strdup(av[1]);
256             ReadCharMap(cmapfile);
257         }
258
259         else if (!strcmp(cmd, "help") || *cmd == '?') {
260             sv = br_help_msg;
261             while (*sv) puts(*sv++);
262         }
263
264         /* quit (control-D also works) */
265         else if (!strcmp(cmd, "quit")) break;
266
267         else
268             fprintf(stderr, "Unknown command '%s' - ignored.\n", cmd);
269     }
270     putc(NL, stdout);
271 }
272
273 /* ______________________________________________________________________ */
274 /*  Do the "ls" command.
275  *  Arguments:
276  *      Pointer to element under consideration.
277  *      Arg count from command line (this command, not the shell command).
278  *      Arg vector.
279  */
280
281 static void
282 ls_node(
283     Element_t   *e,
284     int         ac,
285     char        **av
286 )
287 {
288     int i;
289     char buf[LINESIZE];
290
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));
296         }
297         return;
298     }
299
300     printf("Element: %s\tLineNumber: %d\n", e->gi, e->lineno);
301     if (e->parent)
302         printf("Context: %s\n", FindContext(e, 20, buf));
303
304     if (e->natts) {
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);
308     }
309     if (e->entity) {
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);
321     }
322
323     if (e->my_eorder >= 0)
324         printf("My order among my siblings: %d\n", e->my_eorder);
325
326     if (e->necont) {
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);
329     }
330
331     if (e->ndcont) {
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]);
336             else 
337                 printf("\t%2d: %-40.40s...\n", i, e->dcont[i]);
338         }
339     }
340 }
341
342 /* ______________________________________________________________________ */
343 /*  Perform query.  Syntax: find relationship gi.  Tells whether gi has
344  *  given relationship to current element.  Result (message) sent to stdout.
345  *  Args:
346  *      Pointer to element under consideration.
347  *      Pointer to name of relationship. (see FindRelByName() for names)
348  *      Pointer to GI to look for.
349  */
350
351 static void
352 do_query(
353     Element_t   *e,
354     char        *rel,
355     char        *gi
356 )
357 {
358     char        *cp;
359     Relation_t   r;
360     Element_t   *ep;
361
362     for (cp=gi; *cp; cp++) if (islower(*cp)) *cp = toupper(*cp);
363
364     if ((r = FindRelByName(rel)) == REL_Unknown) {
365         return;
366     }
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);
370 }
371
372 /* ______________________________________________________________________ */
373 /* Print path to the element and its ID (if it has one) on a single line.
374  *  Arguments:
375  *      Pointer to element under consideration.
376  */
377 static void
378 PrElemPlusID(
379     Element_t   *e
380 )
381 {
382     char buf[LINESIZE];
383
384     if (e->id) printf("%s -- ID=%s\n", FindElementPath(e, buf), e->id);
385     else printf("%s\n", FindElementPath(e, buf));
386 }
387
388 /* ______________________________________________________________________ */
389 /* Print path to the element and its ID (if it has one) on a single line.
390  *  Arguments:
391  *      Pointer to element under consideration.
392  */
393
394 static void
395 match_gi(
396     Element_t   *e,
397     char        **av
398 )
399 {
400     if (!strcmp(av[1], e->gi)) PrElemPlusID(e);
401 }
402
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);  }
408
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)
414
415 static void
416 match_attr(
417     Element_t   *e,
418     char        **av
419 )
420 {
421     char        *atval;
422
423     if ((atval = FindAttValByName(e, av[1])) && !strcmp(av[2], atval))
424         PrElemPlusID(e);
425 }
426
427 static void
428 match_cont(
429     Element_t   *e,
430     char        **av
431 )
432 {
433     int         i;
434     for (i=0; i<e->ncont; i++) {
435         if (IsContData(e,i) && strstr(ContData(e,i), av[1])) {
436             PrElemPlusID(e);
437             return;
438         }
439     }
440 }
441
442 /*  Find an element, given the criteria on its command line.
443  *  Arguments:
444  *      Pointer to element under consideration.
445  */
446 static void
447 do_find(
448     Element_t   *e,
449     char        **av
450 )
451 {
452     av++;
453     if (!strcmp(av[0], ".")) av++;
454     else e = DocTree;
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]);
464 }
465
466 /* ______________________________________________________________________ */