xref: /onnv-gate/usr/src/cmd/man/src/util/instant.src/main.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  *  Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
3*0Sstevel@tonic-gate  *  All rights reserved.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate /*
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate  * Copyright (c) 1994
8*0Sstevel@tonic-gate  * Open Software Foundation, Inc.
9*0Sstevel@tonic-gate  *
10*0Sstevel@tonic-gate  * Permission is hereby granted to use, copy, modify and freely distribute
11*0Sstevel@tonic-gate  * the software in this file and its documentation for any purpose without
12*0Sstevel@tonic-gate  * fee, provided that the above copyright notice appears in all copies and
13*0Sstevel@tonic-gate  * that both the copyright notice and this permission notice appear in
14*0Sstevel@tonic-gate  * supporting documentation.  Further, provided that the name of Open
15*0Sstevel@tonic-gate  * Software Foundation, Inc. ("OSF") not be used in advertising or
16*0Sstevel@tonic-gate  * publicity pertaining to distribution of the software without prior
17*0Sstevel@tonic-gate  * written permission from OSF.  OSF makes no representations about the
18*0Sstevel@tonic-gate  * suitability of this software for any purpose.  It is provided "as is"
19*0Sstevel@tonic-gate  * without express or implied warranty.
20*0Sstevel@tonic-gate  */
21*0Sstevel@tonic-gate /*
22*0Sstevel@tonic-gate  * Copyright (c) 1996 X Consortium
23*0Sstevel@tonic-gate  * Copyright (c) 1995, 1996 Dalrymple Consulting
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * Permission is hereby granted, free of charge, to any person obtaining a copy
26*0Sstevel@tonic-gate  * of this software and associated documentation files (the "Software"), to deal
27*0Sstevel@tonic-gate  * in the Software without restriction, including without limitation the rights
28*0Sstevel@tonic-gate  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29*0Sstevel@tonic-gate  * copies of the Software, and to permit persons to whom the Software is
30*0Sstevel@tonic-gate  * furnished to do so, subject to the following conditions:
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  * The above copyright notice and this permission notice shall be included in
33*0Sstevel@tonic-gate  * all copies or substantial portions of the Software.
34*0Sstevel@tonic-gate  *
35*0Sstevel@tonic-gate  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36*0Sstevel@tonic-gate  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37*0Sstevel@tonic-gate  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
38*0Sstevel@tonic-gate  * X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
39*0Sstevel@tonic-gate  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
40*0Sstevel@tonic-gate  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
41*0Sstevel@tonic-gate  * OTHER DEALINGS IN THE SOFTWARE.
42*0Sstevel@tonic-gate  *
43*0Sstevel@tonic-gate  * Except as contained in this notice, the names of the X Consortium and
44*0Sstevel@tonic-gate  * Dalrymple Consulting shall not be used in advertising or otherwise to
45*0Sstevel@tonic-gate  * promote the sale, use or other dealings in this Software without prior
46*0Sstevel@tonic-gate  * written authorization.
47*0Sstevel@tonic-gate  */
48*0Sstevel@tonic-gate /* ________________________________________________________________________
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  *  Program to read an SGML document instance, creating any of several things:
51*0Sstevel@tonic-gate  *
52*0Sstevel@tonic-gate  *	"translated" output for formatting applications (given a trans. spec)
53*0Sstevel@tonic-gate  *	validation report (given a appropriate trans spec)
54*0Sstevel@tonic-gate  *	tree of the document's structure
55*0Sstevel@tonic-gate  *	statistics about the element usage
56*0Sstevel@tonic-gate  *	summary of the elements used
57*0Sstevel@tonic-gate  *	context of each element used
58*0Sstevel@tonic-gate  *	IDs of each element
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *  A C structure is created for each element, which includes:
61*0Sstevel@tonic-gate  *	name, attributes, parent, children, content
62*0Sstevel@tonic-gate  *  The tree is descended, and the desired actions performed.
63*0Sstevel@tonic-gate  *
64*0Sstevel@tonic-gate  *  Takes input from James Clark's "sgmls" program (v. 1.1).
65*0Sstevel@tonic-gate  * ________________________________________________________________________
66*0Sstevel@tonic-gate  */
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #ifndef lint
69*0Sstevel@tonic-gate static char *RCSid =
70*0Sstevel@tonic-gate   "$Header: /usr/src/docbook-to-man/Instant/RCS/main.c,v 1.12 1998/06/28 20:10:39 fld Exp fld $";
71*0Sstevel@tonic-gate #endif
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate #include <stdio.h>
74*0Sstevel@tonic-gate #include <stdlib.h>
75*0Sstevel@tonic-gate #include <ctype.h>
76*0Sstevel@tonic-gate #include <string.h>
77*0Sstevel@tonic-gate #include <memory.h>
78*0Sstevel@tonic-gate #include <errno.h>
79*0Sstevel@tonic-gate #include <sys/types.h>
80*0Sstevel@tonic-gate #include <sys/stat.h>
81*0Sstevel@tonic-gate #include <sys/file.h>
82*0Sstevel@tonic-gate #include <time.h>
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate #define STORAGE
85*0Sstevel@tonic-gate #include "general.h"
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate static int	do_context, do_tree, do_summ, do_stats, do_validate, do_idlist;
88*0Sstevel@tonic-gate static int	do_DATAhack = 0;
89*0Sstevel@tonic-gate static char	*this_prog;
90*0Sstevel@tonic-gate static char	*in_file, *out_file;
91*0Sstevel@tonic-gate static char	*tranfile, *cmapfile, *sdatafile;
92*0Sstevel@tonic-gate static char	*start_id;
93*0Sstevel@tonic-gate static char	*last_file;
94*0Sstevel@tonic-gate static int	last_lineno;
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate extern int	BOFTTextThresh;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate /* forward references */
99*0Sstevel@tonic-gate static void	HandleArgs(int, char *[]);
100*0Sstevel@tonic-gate static void	Initialize1();
101*0Sstevel@tonic-gate static void	Initialize2();
102*0Sstevel@tonic-gate static void	ReadInstance(char *);
103*0Sstevel@tonic-gate static void	DoHelpMessage();
104*0Sstevel@tonic-gate extern void	Browse();
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate /* external reference to version number */
107*0Sstevel@tonic-gate extern char	_HeadVeRsIoN_[];
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate /* ______________________________________________________________________ */
110*0Sstevel@tonic-gate /*  Program entry point.  Look at args, read instance, dispatch to the
111*0Sstevel@tonic-gate  *  correct routines to do the work, and finish.
112*0Sstevel@tonic-gate  */
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate int
main(int ac,char * av[])115*0Sstevel@tonic-gate main(
116*0Sstevel@tonic-gate     int		ac,
117*0Sstevel@tonic-gate     char	*av[]
118*0Sstevel@tonic-gate )
119*0Sstevel@tonic-gate {
120*0Sstevel@tonic-gate     Initialize1(av[0]);
121*0Sstevel@tonic-gate     HandleArgs(ac, av);
122*0Sstevel@tonic-gate     Initialize2();
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate     ReadInstance(in_file);
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate     if (interactive) {
127*0Sstevel@tonic-gate 	Browse();	/* this will handle interactive commands */
128*0Sstevel@tonic-gate     }
129*0Sstevel@tonic-gate     else {
130*0Sstevel@tonic-gate 	/* Perform tasks based on command line flags... */
131*0Sstevel@tonic-gate 	if (tranfile) {
132*0Sstevel@tonic-gate 	    Element_t *e;
133*0Sstevel@tonic-gate 	    /* If user wants to start at a particular ID, point to that
134*0Sstevel@tonic-gate 	     * element.  Else, point to the top of the tree. */
135*0Sstevel@tonic-gate 	    if (start_id) {
136*0Sstevel@tonic-gate 		if (!(e=FindElemByID(start_id))) {
137*0Sstevel@tonic-gate 		    fprintf(stderr, "Error: Can not find element with ID %s\n",
138*0Sstevel@tonic-gate 			start_id);
139*0Sstevel@tonic-gate 		    exit(1);
140*0Sstevel@tonic-gate 		}
141*0Sstevel@tonic-gate 	    }
142*0Sstevel@tonic-gate 	    else e = DocTree;
143*0Sstevel@tonic-gate 	    if (sdatafile) ReadSDATA(sdatafile);
144*0Sstevel@tonic-gate 	    if (cmapfile)  ReadCharMap(cmapfile);
145*0Sstevel@tonic-gate 	    /* If we're doing validation, make output file pointer null.
146*0Sstevel@tonic-gate 	     * This means that we generate no output, except error messages. */
147*0Sstevel@tonic-gate 	    if (do_validate) outfp = NULL;
148*0Sstevel@tonic-gate 	    DoTranslate(e, tranfile, outfp);
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 	if (do_summ)		PrintElemSummary(DocTree);
151*0Sstevel@tonic-gate 	if (do_tree)		PrintElemTree(DocTree);
152*0Sstevel@tonic-gate 	if (do_stats)		PrintStats(DocTree);
153*0Sstevel@tonic-gate 	if (do_context)		PrintContext(DocTree);
154*0Sstevel@tonic-gate 	if (do_idlist)		PrintIDList();
155*0Sstevel@tonic-gate     }
156*0Sstevel@tonic-gate     if (out_file && outfp) fclose(outfp);
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate     return 0;
159*0Sstevel@tonic-gate }
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate /* ______________________________________________________________________ */
162*0Sstevel@tonic-gate /* Initialization stuff done before dealing with args.
163*0Sstevel@tonic-gate  *  Arguments:
164*0Sstevel@tonic-gate  *	Name of program (string).
165*0Sstevel@tonic-gate  */
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate static void
Initialize1(char * myname)168*0Sstevel@tonic-gate Initialize1(
169*0Sstevel@tonic-gate     char	*myname
170*0Sstevel@tonic-gate )
171*0Sstevel@tonic-gate {
172*0Sstevel@tonic-gate     time_t	tnow;
173*0Sstevel@tonic-gate     struct tm	*nowtm;
174*0Sstevel@tonic-gate     char	*cp, buf[100];
175*0Sstevel@tonic-gate     extern	int gethostname(char *, int);	/* not in a system .h file... */
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate     /* where we try to find data/library files */
178*0Sstevel@tonic-gate     if (!(tpt_lib=getenv(TPT_LIB))) tpt_lib = DEF_TPT_LIB;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate     /* set some global variables */
181*0Sstevel@tonic-gate     warnings  = 1;
182*0Sstevel@tonic-gate     fold_case = 1;
183*0Sstevel@tonic-gate     this_prog = myname;
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate     /* setup global variable mapping */
186*0Sstevel@tonic-gate     Variables = NewMap(IMS_variables);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate     /* set some pre-defined variables */
189*0Sstevel@tonic-gate     SetMappingNV(Variables, "user", (cp=getenv("USER")) ? cp : "UnknownUser" );
190*0Sstevel@tonic-gate     time(&tnow);
191*0Sstevel@tonic-gate     nowtm = localtime(&tnow);
192*0Sstevel@tonic-gate     strftime(buf, 100, "%a %d %b %Y, %R", nowtm);
193*0Sstevel@tonic-gate     SetMappingNV(Variables, "date", buf);
194*0Sstevel@tonic-gate     if (gethostname(buf, 100) < 0) strcpy(buf, "unknown-host");
195*0Sstevel@tonic-gate     SetMappingNV(Variables, "host", buf);
196*0Sstevel@tonic-gate     SetMappingNV(Variables, "transpec", tranfile ? tranfile : "??");
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate /* Initialization stuff done after dealing with args. */
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate static void
Initialize2()202*0Sstevel@tonic-gate Initialize2()
203*0Sstevel@tonic-gate {
204*0Sstevel@tonic-gate     SetMappingNV(Variables, "transpec", tranfile ? tranfile : "??");
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate     /* If user wants to send output to a file, open the file, and set
207*0Sstevel@tonic-gate      * the file pointer.  Else we send output to standard out. */
208*0Sstevel@tonic-gate     if (out_file) {
209*0Sstevel@tonic-gate 	if (!(outfp = fopen(out_file, "w"))) {
210*0Sstevel@tonic-gate 	    fprintf(stderr, "Could not open output '%s' file for writing.\n%s",
211*0Sstevel@tonic-gate 		out_file, strerror(errno));
212*0Sstevel@tonic-gate 	    exit(1);
213*0Sstevel@tonic-gate 	}
214*0Sstevel@tonic-gate     }
215*0Sstevel@tonic-gate     else outfp = stdout;
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /* ______________________________________________________________________ */
219*0Sstevel@tonic-gate /*  Set a variable.  If it is one of the "known" variables, set the
220*0Sstevel@tonic-gate  *  variable in the C code (this program).
221*0Sstevel@tonic-gate  *  Arguments:
222*0Sstevel@tonic-gate  *	Variable name/value string - separated by an '=' (eg, "myname=Sally").
223*0Sstevel@tonic-gate  */
224*0Sstevel@tonic-gate static void
CmdLineSetVariable(char * var)225*0Sstevel@tonic-gate CmdLineSetVariable(
226*0Sstevel@tonic-gate     char	*var
227*0Sstevel@tonic-gate )
228*0Sstevel@tonic-gate {
229*0Sstevel@tonic-gate     char	*cp, buf[100], **tok;
230*0Sstevel@tonic-gate     int		n;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate     /* Turn '=' into a space, to isolate the name.  Then set variable. */
233*0Sstevel@tonic-gate     strcpy(buf, var);
234*0Sstevel@tonic-gate     if ((cp=strchr(buf, '='))) {
235*0Sstevel@tonic-gate 	/* we have "var=value" */
236*0Sstevel@tonic-gate 	*cp = ' ';
237*0Sstevel@tonic-gate 	n = 2;
238*0Sstevel@tonic-gate 	tok = Split(buf, &n, 0);
239*0Sstevel@tonic-gate 	/* see if variable name matches one of our internal ones */
240*0Sstevel@tonic-gate 	if (!strcmp(tok[0], "verbose"))		verbose   = atoi(tok[1]);
241*0Sstevel@tonic-gate 	else if (!strcmp(tok[0], "warnings"))	warnings  = atoi(tok[1]);
242*0Sstevel@tonic-gate 	else if (!strcmp(tok[0], "foldcase"))	fold_case = atoi(tok[1]);
243*0Sstevel@tonic-gate 	else SetMappingNV(Variables, tok[0], tok[1]);
244*0Sstevel@tonic-gate     }
245*0Sstevel@tonic-gate     else {
246*0Sstevel@tonic-gate 	fprintf(stderr, "Expected an '=' in variable assignment: %s. Ignored\n",
247*0Sstevel@tonic-gate 		var);
248*0Sstevel@tonic-gate     }
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate /* ______________________________________________________________________ */
252*0Sstevel@tonic-gate /*  Bounce through arguments, setting variables and flags.
253*0Sstevel@tonic-gate  *  Arguments:
254*0Sstevel@tonic-gate  *	Argc and Argv, as passed to main().
255*0Sstevel@tonic-gate  */
256*0Sstevel@tonic-gate static void
HandleArgs(int ac,char * av[])257*0Sstevel@tonic-gate HandleArgs(
258*0Sstevel@tonic-gate     int		ac,
259*0Sstevel@tonic-gate     char	*av[]
260*0Sstevel@tonic-gate )
261*0Sstevel@tonic-gate {
262*0Sstevel@tonic-gate     int		c, errflag=0;
263*0Sstevel@tonic-gate     extern char	*optarg;
264*0Sstevel@tonic-gate     extern int	optind;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate     while ((c=getopt(ac, av, "df:t:vc:s:o:huSxIl:bHVWi:D:Z")) != EOF) {
267*0Sstevel@tonic-gate 	switch (c) {
268*0Sstevel@tonic-gate 	    case 't': tranfile		= optarg;	break;
269*0Sstevel@tonic-gate 	    case 'v': do_validate	= 1;		break;
270*0Sstevel@tonic-gate 	    case 's': sdatafile		= optarg;	break;
271*0Sstevel@tonic-gate 	    case 'c': cmapfile		= optarg;	break;
272*0Sstevel@tonic-gate 	    case 'h': do_tree		= 1;		break;
273*0Sstevel@tonic-gate 	    case 'u': do_summ		= 1;		break;
274*0Sstevel@tonic-gate 	    case 'S': do_stats		= 1;		break;
275*0Sstevel@tonic-gate 	    case 'x': do_context	= 1;		break;
276*0Sstevel@tonic-gate 	    case 'I': do_idlist		= 1;		break;
277*0Sstevel@tonic-gate 	    case 'l': tpt_lib		= optarg;	break;
278*0Sstevel@tonic-gate 	    case 'i': start_id		= optarg;	break;
279*0Sstevel@tonic-gate 	    case 'o': out_file		= optarg;	break;
280*0Sstevel@tonic-gate 	    case 'd': do_DATAhack	= 1;		break;
281*0Sstevel@tonic-gate 	    case 'f': BOFTTextThresh	= atoi(optarg);	break;
282*0Sstevel@tonic-gate 	    case 'b': interactive	= 1;		break;
283*0Sstevel@tonic-gate 	    case 'W': warnings		= 0;		break;
284*0Sstevel@tonic-gate 	    case 'V': verbose		= 1;		break;
285*0Sstevel@tonic-gate 	    case 'Z': slave		= 1;		break;
286*0Sstevel@tonic-gate 	    case 'H': DoHelpMessage();	exit(0);	break;
287*0Sstevel@tonic-gate 	    case 'D': CmdLineSetVariable(optarg);	break;
288*0Sstevel@tonic-gate 	    case '?': errflag		= 1;		break;
289*0Sstevel@tonic-gate 	}
290*0Sstevel@tonic-gate 	if (errflag) {
291*0Sstevel@tonic-gate 	    fprintf(stderr, "Try '%s -H' for help.\n", this_prog);
292*0Sstevel@tonic-gate 	    exit(1);
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate     }
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate     /* input (ESIS) file name */
297*0Sstevel@tonic-gate     if (optind < ac) in_file = av[optind];
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate     /* If doing interactive/browsing, we can't take ESIS from stdin. */
300*0Sstevel@tonic-gate     if (interactive && !in_file) {
301*0Sstevel@tonic-gate 	fprintf(stderr,
302*0Sstevel@tonic-gate 	    "You must specify ESIS file on cmd line for browser mode.\n");
303*0Sstevel@tonic-gate 	exit(1);
304*0Sstevel@tonic-gate     }
305*0Sstevel@tonic-gate }
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate /* ______________________________________________________________________ */
308*0Sstevel@tonic-gate /*  Simply print out a help/usage message.
309*0Sstevel@tonic-gate  */
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate static char *help_msg[] = {
312*0Sstevel@tonic-gate   "",
313*0Sstevel@tonic-gate   "  -t file   Print translated output using translation spec in <file>",
314*0Sstevel@tonic-gate   "  -s file   <file> contains a list of SDATA entity mappings",
315*0Sstevel@tonic-gate   "  -c file   <file> contains a list of character mappings",
316*0Sstevel@tonic-gate   "  -v        Validate using translation spec specified with -t",
317*0Sstevel@tonic-gate   "  -i id     Consider only subtree starting at element with ID <id>",
318*0Sstevel@tonic-gate   "  -b        Interactive browser",
319*0Sstevel@tonic-gate   "  -S        Print statistics (how often elements occur, etc.)",
320*0Sstevel@tonic-gate   "  -u        Print element usage summary (# of children, depth, etc.)",
321*0Sstevel@tonic-gate   "  -x        Print context of each element",
322*0Sstevel@tonic-gate   "  -h        Print document hierarchy as a tree",
323*0Sstevel@tonic-gate   "  -o file   Write output to <file>.  Default is standard output.",
324*0Sstevel@tonic-gate   "  -l dir    Set library directory to <dir>. (or env. variable TPT_LIB)",
325*0Sstevel@tonic-gate   "  -I        List all IDs used in the instance",
326*0Sstevel@tonic-gate   "  -W        Do not print warning messages",
327*0Sstevel@tonic-gate   "  -H        Print this help message",
328*0Sstevel@tonic-gate   "  -Dvar=val Set variable 'var' to value 'val'",
329*0Sstevel@tonic-gate   "  file      Take input from named file.  If not specified, assume stdin.",
330*0Sstevel@tonic-gate   "            File should be output from the 'sgmls' program (ESIS).",
331*0Sstevel@tonic-gate   NULL
332*0Sstevel@tonic-gate };
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate static void
DoHelpMessage()335*0Sstevel@tonic-gate DoHelpMessage()
336*0Sstevel@tonic-gate {
337*0Sstevel@tonic-gate     char	**s = help_msg;
338*0Sstevel@tonic-gate     printf("usage: %s [option ...] [file]", this_prog);
339*0Sstevel@tonic-gate     while (*s) puts(*s++);
340*0Sstevel@tonic-gate     printf("\nVersion: %s\n", _HeadVeRsIoN_);
341*0Sstevel@tonic-gate }
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate /* ______________________________________________________________________ */
344*0Sstevel@tonic-gate /*  Remember an external entity for future reference.
345*0Sstevel@tonic-gate  *  Arguments:
346*0Sstevel@tonic-gate  *	Pointer to entity structure to remember.
347*0Sstevel@tonic-gate  */
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate static void
AddEntity(Entity_t * ent)350*0Sstevel@tonic-gate AddEntity(
351*0Sstevel@tonic-gate     Entity_t	*ent
352*0Sstevel@tonic-gate )
353*0Sstevel@tonic-gate {
354*0Sstevel@tonic-gate     static Entity_t *last_ent;
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate     if (!Entities) {
357*0Sstevel@tonic-gate         Malloc(1, Entities, Entity_t);
358*0Sstevel@tonic-gate         last_ent = Entities;
359*0Sstevel@tonic-gate     }
360*0Sstevel@tonic-gate     else {
361*0Sstevel@tonic-gate         Malloc(1, last_ent->next, Entity_t);
362*0Sstevel@tonic-gate         last_ent = last_ent->next;
363*0Sstevel@tonic-gate     }
364*0Sstevel@tonic-gate     *last_ent = *ent;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate /*  Find an entity, given its entity name.
369*0Sstevel@tonic-gate  *  Arguments:
370*0Sstevel@tonic-gate  *	Name of entity to retrieve.
371*0Sstevel@tonic-gate  */
372*0Sstevel@tonic-gate Entity_t *
FindEntity(char * ename)373*0Sstevel@tonic-gate FindEntity(
374*0Sstevel@tonic-gate     char	*ename
375*0Sstevel@tonic-gate )
376*0Sstevel@tonic-gate {
377*0Sstevel@tonic-gate     Entity_t	*n;
378*0Sstevel@tonic-gate     for (n=Entities; n; n=n->next)
379*0Sstevel@tonic-gate 	if (StrEq(ename, n->ename)) return n;
380*0Sstevel@tonic-gate     return 0;
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate /*  Accumulate lines up to the open tag.  Attributes, line number,
384*0Sstevel@tonic-gate  *  entity info, notation info, etc., all come before the open tag.
385*0Sstevel@tonic-gate  */
386*0Sstevel@tonic-gate static Element_t *
AccumElemInfo(FILE * fp)387*0Sstevel@tonic-gate AccumElemInfo(
388*0Sstevel@tonic-gate     FILE	*fp
389*0Sstevel@tonic-gate )
390*0Sstevel@tonic-gate {
391*0Sstevel@tonic-gate     char	buf[LINESIZE+1];
392*0Sstevel@tonic-gate     int		c;
393*0Sstevel@tonic-gate     int		i, na;
394*0Sstevel@tonic-gate     char	*cp, *atval;
395*0Sstevel@tonic-gate     Mapping_t	a[100];
396*0Sstevel@tonic-gate     Element_t	*e;
397*0Sstevel@tonic-gate     Entity_t	ent, *ent2;
398*0Sstevel@tonic-gate     char	**tok;
399*0Sstevel@tonic-gate     static int	Index=0;
400*0Sstevel@tonic-gate     static Element_t	*last_e;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate     Calloc(1, e, Element_t);
404*0Sstevel@tonic-gate     memset(&ent, 0, sizeof ent);	/* clean space for entity info */
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate     /* Also, keep a linked list of elements, so we can easily scan through */
407*0Sstevel@tonic-gate     if (last_e) last_e->next = e;
408*0Sstevel@tonic-gate     last_e = e;
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate     e->index = Index++;		/* just a unique number for identification */
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate     /* in case these are not set for this element in the ESIS */
413*0Sstevel@tonic-gate     e->lineno = last_lineno;
414*0Sstevel@tonic-gate     e->infile = last_file;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate     na = 0;
417*0Sstevel@tonic-gate     while (1) {
418*0Sstevel@tonic-gate 	if ((c = getc(fp)) == EOF) break;
419*0Sstevel@tonic-gate 	fgets(buf, LINESIZE, fp);
420*0Sstevel@tonic-gate 	stripNL(buf);
421*0Sstevel@tonic-gate 	switch (c) {
422*0Sstevel@tonic-gate 	    case EOF:		/* End of input */
423*0Sstevel@tonic-gate 		fprintf(stderr, "Error: Unexpectedly reached end of ESIS.\n");
424*0Sstevel@tonic-gate 		exit(1);
425*0Sstevel@tonic-gate 		break;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	    case CMD_OPEN:	/* (gi */
428*0Sstevel@tonic-gate 		e->gi = AddElemName(buf);
429*0Sstevel@tonic-gate 		if (na > 0) {
430*0Sstevel@tonic-gate 		    Malloc(na, e->atts, Mapping_t);
431*0Sstevel@tonic-gate 		    memcpy(e->atts, a, na*sizeof(Mapping_t));
432*0Sstevel@tonic-gate 		    e->natts = na;
433*0Sstevel@tonic-gate 		    na = 0;
434*0Sstevel@tonic-gate 		}
435*0Sstevel@tonic-gate 		/*  Check if this elem has a notation attr.  If yes, and there
436*0Sstevel@tonic-gate 		    is no notation specified, recall the previous one. (feature
437*0Sstevel@tonic-gate 		    of sgmls - it does not repeat notation stuff if we the same
438*0Sstevel@tonic-gate 		    is used twice in a row) */
439*0Sstevel@tonic-gate 		if (((atval=FindAttValByName(e, "NAME")) ||
440*0Sstevel@tonic-gate 		     (atval=FindAttValByName(e, "ENTITYREF")) ||
441*0Sstevel@tonic-gate 		     (atval=FindAttValByName(e, "EXTERNAL"))) &&   /* HACK */
442*0Sstevel@tonic-gate 					(ent2=FindEntity(atval))) {
443*0Sstevel@tonic-gate 		    e->entity = ent2;
444*0Sstevel@tonic-gate 		}
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 		return e;
447*0Sstevel@tonic-gate 		break;
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	    case CMD_ATT:	/* Aname val */
450*0Sstevel@tonic-gate 		i = 3;
451*0Sstevel@tonic-gate 		tok = Split(buf, &i, 0);
452*0Sstevel@tonic-gate 		if (!strcmp(tok[1], "IMPLIED")) break;	/* skip IMPLIED atts. */
453*0Sstevel@tonic-gate 		if (!strcmp(tok[1], "CDATA") || !strcmp(tok[1], "TOKEN") ||
454*0Sstevel@tonic-gate 		    !strcmp(tok[1], "ENTITY") ||!strcmp(tok[1], "NOTATION"))
455*0Sstevel@tonic-gate 		{
456*0Sstevel@tonic-gate 		    a[na].name = AddAttName(tok[0]);
457*0Sstevel@tonic-gate 		    a[na].sval = AddAttName(tok[2]);
458*0Sstevel@tonic-gate 		    na++;
459*0Sstevel@tonic-gate 		}
460*0Sstevel@tonic-gate 		else {
461*0Sstevel@tonic-gate 		    fprintf(stderr, "Error: Bad attr line (%d): A%s %s...\n",
462*0Sstevel@tonic-gate 			e->lineno, tok[0], tok[1]);
463*0Sstevel@tonic-gate 		}
464*0Sstevel@tonic-gate 		break;
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	    case CMD_LINE:	/* Llineno */
467*0Sstevel@tonic-gate 		/* These lines come in 2 forms: "L123" and "L123 file.sgml".
468*0Sstevel@tonic-gate 		 * Filename is given only at 1st occurance. Remember it.
469*0Sstevel@tonic-gate 		 */
470*0Sstevel@tonic-gate 		if ((cp = strchr(buf, ' '))) {
471*0Sstevel@tonic-gate 		    cp++;
472*0Sstevel@tonic-gate 		    last_file = strdup(cp);
473*0Sstevel@tonic-gate 		}
474*0Sstevel@tonic-gate 		last_lineno = e->lineno = atoi(buf);
475*0Sstevel@tonic-gate 		e->infile = last_file;
476*0Sstevel@tonic-gate 		break;
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	    case CMD_DATA:	/* -data */
479*0Sstevel@tonic-gate 		fprintf(stderr, "Error: Data in AccumElemInfo, line %d:\n%c%s\n",
480*0Sstevel@tonic-gate 			e->lineno, c,buf);
481*0Sstevel@tonic-gate 		/*return e;*/
482*0Sstevel@tonic-gate 		exit(1);
483*0Sstevel@tonic-gate 		break;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 	    case CMD_D_ATT:	/* Dename name val */
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate 	    case CMD_NOTATION:	/* Nnname */
488*0Sstevel@tonic-gate 	    case CMD_PI:	/* ?pi */
489*0Sstevel@tonic-gate 				/* This should be reworked soon, as it
490*0Sstevel@tonic-gate 				   forces all PI's before the first GI
491*0Sstevel@tonic-gate 				   to be ignored. -CSS */
492*0Sstevel@tonic-gate 		break;
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 	    case CMD_EXT_ENT:	/* Eename typ nname */
495*0Sstevel@tonic-gate 		i = 3;
496*0Sstevel@tonic-gate 		tok = Split(buf, &i, 0);
497*0Sstevel@tonic-gate 		ent.ename = strdup(tok[0]);
498*0Sstevel@tonic-gate 		ent.type  = strdup(tok[1]);
499*0Sstevel@tonic-gate 		ent.nname = strdup(tok[2]);
500*0Sstevel@tonic-gate 		AddEntity(&ent);
501*0Sstevel@tonic-gate 		break;
502*0Sstevel@tonic-gate 	    case CMD_INT_ENT:	/* Iename typ text */
503*0Sstevel@tonic-gate 		fprintf(stderr, "Error: Got CMD_INT_ENT in AccumElemInfo: %s\n", buf);
504*0Sstevel@tonic-gate 		break;
505*0Sstevel@tonic-gate 	    case CMD_SYSID:	/* ssysid */
506*0Sstevel@tonic-gate 		ent.sysid = strdup(buf);
507*0Sstevel@tonic-gate 		break;
508*0Sstevel@tonic-gate 	    case CMD_PUBID:	/* ppubid */
509*0Sstevel@tonic-gate 		ent.pubid = strdup(buf);
510*0Sstevel@tonic-gate 		break;
511*0Sstevel@tonic-gate 	    case CMD_FILENAME:	/* ffilename */
512*0Sstevel@tonic-gate 		ent.fname = strdup(buf);
513*0Sstevel@tonic-gate 		break;
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	    case CMD_CLOSE:	/* )gi */
516*0Sstevel@tonic-gate 	    case CMD_SUBDOC:	/* Sename */
517*0Sstevel@tonic-gate 	    case CMD_SUBDOC_S:	/* {ename */
518*0Sstevel@tonic-gate 	    case CMD_SUBDOC_E:	/* }ename */
519*0Sstevel@tonic-gate 	    case CMD_EXT_REF:	/* &name */
520*0Sstevel@tonic-gate 	    case CMD_APPINFO:	/* #text */
521*0Sstevel@tonic-gate 	    case CMD_CONFORM:	/* C */
522*0Sstevel@tonic-gate 	    default:
523*0Sstevel@tonic-gate 		fprintf(stderr, "Error: Unexpected input in AccumElemInfo, %d:\n%c%s\n",
524*0Sstevel@tonic-gate 			e->lineno, c,buf);
525*0Sstevel@tonic-gate 		exit(1);
526*0Sstevel@tonic-gate 		break;
527*0Sstevel@tonic-gate 	}
528*0Sstevel@tonic-gate     }
529*0Sstevel@tonic-gate     if ( e && e->gi )
530*0Sstevel@tonic-gate     	fprintf(stderr, "Error: End of AccumElemInfo - should not be here: %s\n", e->gi);
531*0Sstevel@tonic-gate     else
532*0Sstevel@tonic-gate     	fprintf(stderr, "Invalid SGML. File cannot be formatted\n");
533*0Sstevel@tonic-gate /*    return e;*/
534*0Sstevel@tonic-gate     exit(1);
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate /*  Read ESIS lines.
538*0Sstevel@tonic-gate  */
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate #define BASECONTSIZE	500	/* starting size for number of children */
541*0Sstevel@tonic-gate #define GROWCONTSIZE	500	/* if we need to grow that, by this much */
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate static Element_t *
ReadESIS(FILE * fp,int depth)544*0Sstevel@tonic-gate ReadESIS(
545*0Sstevel@tonic-gate     FILE	*fp,
546*0Sstevel@tonic-gate     int		depth
547*0Sstevel@tonic-gate )
548*0Sstevel@tonic-gate {
549*0Sstevel@tonic-gate     char	*buf;
550*0Sstevel@tonic-gate     int		i, c, ncont, contsize;
551*0Sstevel@tonic-gate     Element_t	*e;
552*0Sstevel@tonic-gate     Content_t	*cont;
553*0Sstevel@tonic-gate 
554*0Sstevel@tonic-gate     Malloc( LINESIZE+1, buf, char );
555*0Sstevel@tonic-gate     contsize = BASECONTSIZE;			/* starting content size */
556*0Sstevel@tonic-gate     Malloc( contsize, cont, Content_t );
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate     /* Read input stream - the output of "sgmls", called "ESIS".  */
559*0Sstevel@tonic-gate     e = AccumElemInfo(fp);
560*0Sstevel@tonic-gate     e->depth = depth;
561*0Sstevel@tonic-gate 
562*0Sstevel@tonic-gate     ncont = 0;
563*0Sstevel@tonic-gate     while (1) {
564*0Sstevel@tonic-gate 	if ((c = getc(fp)) == EOF) break;
565*0Sstevel@tonic-gate 	if ( ncont >= contsize )	{
566*0Sstevel@tonic-gate 		contsize += GROWCONTSIZE;
567*0Sstevel@tonic-gate 		Realloc( contsize, cont, Content_t );
568*0Sstevel@tonic-gate 	}
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 	switch (c) {
571*0Sstevel@tonic-gate 	    case EOF:		/* End of input */
572*0Sstevel@tonic-gate 		break;
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 	    case CMD_DATA:	/* -data */
575*0Sstevel@tonic-gate 		fgets(buf, LINESIZE, fp);
576*0Sstevel@tonic-gate 		stripNL(buf);
577*0Sstevel@tonic-gate 		if (do_DATAhack && (buf[0] == '\\') && (buf[1] == 'n') )	{
578*0Sstevel@tonic-gate 			buf[0] = -1;		/* simulate "^" command */
579*0Sstevel@tonic-gate 			memcpy(&buf[1], &buf[2], strlen(buf)-1);
580*0Sstevel@tonic-gate 		}
581*0Sstevel@tonic-gate 		cont[ncont].ch.data = strdup(buf);
582*0Sstevel@tonic-gate 		cont[ncont].type = CMD_DATA;
583*0Sstevel@tonic-gate 		ncont++;
584*0Sstevel@tonic-gate 		break;
585*0Sstevel@tonic-gate 
586*0Sstevel@tonic-gate 	    case CMD_PI:	/* ?pi */
587*0Sstevel@tonic-gate 		fgets(buf, LINESIZE, fp);
588*0Sstevel@tonic-gate 		stripNL(buf);
589*0Sstevel@tonic-gate 		cont[ncont].type = CMD_PI;
590*0Sstevel@tonic-gate 		cont[ncont].ch.data = strdup(buf);
591*0Sstevel@tonic-gate 		ncont++;
592*0Sstevel@tonic-gate 		break;
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 	    case CMD_CLOSE:	/* )gi */
595*0Sstevel@tonic-gate 		fgets(buf, LINESIZE, fp);
596*0Sstevel@tonic-gate 		stripNL(buf);
597*0Sstevel@tonic-gate 		if (ncont) {
598*0Sstevel@tonic-gate 		    e->ncont = ncont;
599*0Sstevel@tonic-gate 		    Malloc(ncont, e->cont, Content_t);
600*0Sstevel@tonic-gate 		    for (i=0; i<ncont; i++) e->cont[i] = cont[i];
601*0Sstevel@tonic-gate 		}
602*0Sstevel@tonic-gate 		free(buf);
603*0Sstevel@tonic-gate 		free(cont);
604*0Sstevel@tonic-gate 		return e;
605*0Sstevel@tonic-gate 		break;
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 	    case CMD_OPEN:	/* (gi */
608*0Sstevel@tonic-gate /*fprintf(stderr, "+++++ OPEN +++\n");*/
609*0Sstevel@tonic-gate /*		break;*/
610*0Sstevel@tonic-gate 
611*0Sstevel@tonic-gate 	    case CMD_ATT:	/* Aname val */
612*0Sstevel@tonic-gate 	    case CMD_D_ATT:	/* Dename name val */
613*0Sstevel@tonic-gate 	    case CMD_NOTATION:	/* Nnname */
614*0Sstevel@tonic-gate 	    case CMD_EXT_ENT:	/* Eename typ nname */
615*0Sstevel@tonic-gate 	    case CMD_INT_ENT:	/* Iename typ text */
616*0Sstevel@tonic-gate 	    case CMD_SYSID:	/* ssysid */
617*0Sstevel@tonic-gate 	    case CMD_PUBID:	/* ppubid */
618*0Sstevel@tonic-gate 	    case CMD_FILENAME:	/* ffilename */
619*0Sstevel@tonic-gate 		ungetc(c, fp);
620*0Sstevel@tonic-gate 		cont[ncont].ch.elem = ReadESIS(fp, depth+1);
621*0Sstevel@tonic-gate 		cont[ncont].type = CMD_OPEN;
622*0Sstevel@tonic-gate 		cont[ncont].ch.elem->parent = e;
623*0Sstevel@tonic-gate 		ncont++;
624*0Sstevel@tonic-gate 		break;
625*0Sstevel@tonic-gate 
626*0Sstevel@tonic-gate 	    case CMD_LINE:	/* Llineno */
627*0Sstevel@tonic-gate 		fgets(buf, LINESIZE, fp);
628*0Sstevel@tonic-gate 		break;		/* ignore these here */
629*0Sstevel@tonic-gate 
630*0Sstevel@tonic-gate 	    case CMD_SUBDOC:	/* Sename */
631*0Sstevel@tonic-gate 	    case CMD_SUBDOC_S:	/* {ename */
632*0Sstevel@tonic-gate 	    case CMD_SUBDOC_E:	/* }ename */
633*0Sstevel@tonic-gate 	    case CMD_EXT_REF:	/* &name */
634*0Sstevel@tonic-gate 	    case CMD_APPINFO:	/* #text */
635*0Sstevel@tonic-gate 	    case CMD_CONFORM:	/* C */
636*0Sstevel@tonic-gate 	    default:
637*0Sstevel@tonic-gate 		fgets(buf, LINESIZE, fp);
638*0Sstevel@tonic-gate 		fprintf(stderr, "Error: Unexpected input at %d: '%c%s'\n",
639*0Sstevel@tonic-gate 			e->lineno, c, buf);
640*0Sstevel@tonic-gate 		exit(1);
641*0Sstevel@tonic-gate 		break;
642*0Sstevel@tonic-gate 	}
643*0Sstevel@tonic-gate     }
644*0Sstevel@tonic-gate 		if( e && e->gi)
645*0Sstevel@tonic-gate     		fprintf(stderr, "Error: End of ReadESIS - should not be here: %s\n", e->gi);
646*0Sstevel@tonic-gate     	else
647*0Sstevel@tonic-gate     		fprintf(stderr, "Error: Invalid SGML: End of ReadESIS - should not be here:\n");
648*0Sstevel@tonic-gate 
649*0Sstevel@tonic-gate     free(buf);
650*0Sstevel@tonic-gate     free(cont);
651*0Sstevel@tonic-gate     return NULL;
652*0Sstevel@tonic-gate }
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate /* ______________________________________________________________________ */
655*0Sstevel@tonic-gate /*  Read input stream, creating a tree in memory of the elements and data.
656*0Sstevel@tonic-gate  *  Arguments:
657*0Sstevel@tonic-gate  *	Filename where instance's ESIS is.
658*0Sstevel@tonic-gate  */
659*0Sstevel@tonic-gate static void
ReadInstance(char * filename)660*0Sstevel@tonic-gate ReadInstance(
661*0Sstevel@tonic-gate     char	*filename
662*0Sstevel@tonic-gate )
663*0Sstevel@tonic-gate {
664*0Sstevel@tonic-gate     int		i, n;
665*0Sstevel@tonic-gate     FILE	*fp;
666*0Sstevel@tonic-gate     Element_t	*e;
667*0Sstevel@tonic-gate     char	*idatt;
668*0Sstevel@tonic-gate 
669*0Sstevel@tonic-gate     if (filename) {	/* if we specified input file.  else stdin */
670*0Sstevel@tonic-gate 	if ((fp=fopen(filename, "r")) == NULL) {
671*0Sstevel@tonic-gate 	    perror(filename);
672*0Sstevel@tonic-gate 	    exit(1);
673*0Sstevel@tonic-gate 	}
674*0Sstevel@tonic-gate     }
675*0Sstevel@tonic-gate     else fp = stdin;
676*0Sstevel@tonic-gate     last_file = filename;
677*0Sstevel@tonic-gate     DocTree = ReadESIS(fp, 0);
678*0Sstevel@tonic-gate     if (filename) fclose(fp);
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate     /* Traverse tree, filling in econt and figuring out which child
681*0Sstevel@tonic-gate      * (ie. what birth order) each element is. */
682*0Sstevel@tonic-gate     DocTree->my_eorder = -1;
683*0Sstevel@tonic-gate     for (e=DocTree; e; e=e->next) {
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 	/* count element children */
686*0Sstevel@tonic-gate 	for (i=0,n=0; i<e->ncont; i++) if (IsContElem(e,i)) n++;
687*0Sstevel@tonic-gate 	if (n > 0) Calloc(n, e->econt, Element_t *);
688*0Sstevel@tonic-gate 	for (i=0; i<e->ncont; i++)
689*0Sstevel@tonic-gate 	    if (IsContElem(e,i)) e->econt[e->necont++] = ContElem(e,i);
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 	/* count data children */
692*0Sstevel@tonic-gate 	for (i=0,n=0; i<e->ncont; i++) if (IsContData(e,i)) n++;
693*0Sstevel@tonic-gate 	if (n > 0) Calloc(n, e->dcont, char *);
694*0Sstevel@tonic-gate 	for (i=0; i<e->ncont; i++)
695*0Sstevel@tonic-gate 	    if (IsContData(e,i)) e->dcont[e->ndcont++] = ContData(e,i);
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	/* where in child order order */
698*0Sstevel@tonic-gate 	for (i=0; i<e->necont; i++)
699*0Sstevel@tonic-gate 	    e->econt[i]->my_eorder = i;
700*0Sstevel@tonic-gate 
701*0Sstevel@tonic-gate 	/* Does this element have an ID? */
702*0Sstevel@tonic-gate 	for (i=0; i<e->natts; i++) {
703*0Sstevel@tonic-gate 	    if ((idatt=FindAttValByName(e, "ID"))) {
704*0Sstevel@tonic-gate 		AddID(e, idatt);
705*0Sstevel@tonic-gate 		/* remember ID value for quick reference */
706*0Sstevel@tonic-gate 		e->id = idatt;
707*0Sstevel@tonic-gate 		break;
708*0Sstevel@tonic-gate 	    }
709*0Sstevel@tonic-gate 	}
710*0Sstevel@tonic-gate     }
711*0Sstevel@tonic-gate     return;
712*0Sstevel@tonic-gate }
713*0Sstevel@tonic-gate 
714*0Sstevel@tonic-gate /* ______________________________________________________________________ */
715