xref: /titanic_52/usr/src/tools/stabs/main.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1996-2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <unistd.h>
30*7c478bd9Sstevel@tonic-gate #include <math.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include "stabs.h"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate int debug_level = 0;
35*7c478bd9Sstevel@tonic-gate int line;
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate boolean_t error = B_FALSE;
38*7c478bd9Sstevel@tonic-gate char *program = NULL;
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate extern void forth_do_sou(struct tdesc *, struct node *);
41*7c478bd9Sstevel@tonic-gate extern void forth_do_enum(struct tdesc *, struct node *);
42*7c478bd9Sstevel@tonic-gate extern void forth_do_intrinsic(struct tdesc *, struct node *);
43*7c478bd9Sstevel@tonic-gate extern void genassym_do_sou(struct tdesc *, struct node *);
44*7c478bd9Sstevel@tonic-gate extern void genassym_do_enum(struct tdesc *, struct node *);
45*7c478bd9Sstevel@tonic-gate extern void genassym_do_intrinsic(struct tdesc *, struct node *);
46*7c478bd9Sstevel@tonic-gate extern void squander_do_sou(struct tdesc *, struct node *);
47*7c478bd9Sstevel@tonic-gate extern void squander_do_enum(struct tdesc *, struct node *);
48*7c478bd9Sstevel@tonic-gate extern void squander_do_intrinsic(struct tdesc *, struct node *);
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate struct model_info models[] = {
51*7c478bd9Sstevel@tonic-gate 	{ "ilp32", 4, 1, 2, 4, 4 },
52*7c478bd9Sstevel@tonic-gate 	{ "lp64",  8, 1, 2, 4, 8 },
53*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, 0, 0 }
54*7c478bd9Sstevel@tonic-gate };
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate struct stab_ops {
57*7c478bd9Sstevel@tonic-gate 	char *type;
58*7c478bd9Sstevel@tonic-gate 	void (*do_sou)(struct tdesc *, struct node *);
59*7c478bd9Sstevel@tonic-gate 	void (*do_enum)(struct tdesc *, struct node *);
60*7c478bd9Sstevel@tonic-gate 	void (*do_intrinsic)(struct tdesc *, struct node *);
61*7c478bd9Sstevel@tonic-gate } ops_table[] = {
62*7c478bd9Sstevel@tonic-gate 	{ "forth",
63*7c478bd9Sstevel@tonic-gate 	    forth_do_sou, forth_do_enum, forth_do_intrinsic },
64*7c478bd9Sstevel@tonic-gate 	{ "genassym",
65*7c478bd9Sstevel@tonic-gate 	    genassym_do_sou, genassym_do_enum, genassym_do_intrinsic },
66*7c478bd9Sstevel@tonic-gate 	{ "squander",
67*7c478bd9Sstevel@tonic-gate 	    squander_do_sou, squander_do_enum, squander_do_intrinsic },
68*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL, NULL }
69*7c478bd9Sstevel@tonic-gate };
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static void get_dbgs(int argc, char **argv);
72*7c478bd9Sstevel@tonic-gate static void parse_dbg(FILE *sp);
73*7c478bd9Sstevel@tonic-gate static void printnode(struct node *np);
74*7c478bd9Sstevel@tonic-gate static struct tdesc *find_member(struct tdesc *tdp, char *name);
75*7c478bd9Sstevel@tonic-gate static char *namex(char *cp, char **w);
76*7c478bd9Sstevel@tonic-gate static void addchild(char *cp, struct node *np);
77*7c478bd9Sstevel@tonic-gate static struct node *getnode(char *cp);
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate struct stab_ops *ops;
80*7c478bd9Sstevel@tonic-gate struct model_info *model;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate int
83*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	char *output_type = NULL;
86*7c478bd9Sstevel@tonic-gate 	char *model_name = NULL;
87*7c478bd9Sstevel@tonic-gate 	int c;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	program = strrchr(argv[0], '/');
90*7c478bd9Sstevel@tonic-gate 	if (program != NULL)
91*7c478bd9Sstevel@tonic-gate 		program++;
92*7c478bd9Sstevel@tonic-gate 	else
93*7c478bd9Sstevel@tonic-gate 		program = argv[0];
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	/* defaults */
96*7c478bd9Sstevel@tonic-gate 	output_type = "forth";
97*7c478bd9Sstevel@tonic-gate 	model_name = "ilp32";
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	while (!error && ((c = getopt(argc, argv, "dt:m:")) != EOF)) {
100*7c478bd9Sstevel@tonic-gate 		switch (c) {
101*7c478bd9Sstevel@tonic-gate 		case 't':
102*7c478bd9Sstevel@tonic-gate 			output_type = optarg;
103*7c478bd9Sstevel@tonic-gate 			break;
104*7c478bd9Sstevel@tonic-gate 		case 'm':
105*7c478bd9Sstevel@tonic-gate 			model_name = optarg;
106*7c478bd9Sstevel@tonic-gate 			break;
107*7c478bd9Sstevel@tonic-gate 		case 'd':
108*7c478bd9Sstevel@tonic-gate 			debug_level++;
109*7c478bd9Sstevel@tonic-gate 			break;
110*7c478bd9Sstevel@tonic-gate 		case '?':
111*7c478bd9Sstevel@tonic-gate 		default:
112*7c478bd9Sstevel@tonic-gate 			error = B_TRUE;
113*7c478bd9Sstevel@tonic-gate 			break;
114*7c478bd9Sstevel@tonic-gate 		}
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	if (!error) {
118*7c478bd9Sstevel@tonic-gate 		/*
119*7c478bd9Sstevel@tonic-gate 		 * Find ops for the specified output type
120*7c478bd9Sstevel@tonic-gate 		 */
121*7c478bd9Sstevel@tonic-gate 		for (ops = ops_table; ops->type != NULL; ops++) {
122*7c478bd9Sstevel@tonic-gate 			if (strcmp(ops->type, output_type) == 0)
123*7c478bd9Sstevel@tonic-gate 				break;
124*7c478bd9Sstevel@tonic-gate 		}
125*7c478bd9Sstevel@tonic-gate 		if (ops->type == NULL)
126*7c478bd9Sstevel@tonic-gate 			error = B_TRUE;
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	if (!error) {
130*7c478bd9Sstevel@tonic-gate 		/*
131*7c478bd9Sstevel@tonic-gate 		 * Find model characteristics
132*7c478bd9Sstevel@tonic-gate 		 */
133*7c478bd9Sstevel@tonic-gate 		for (model = models; model->name != NULL; model++) {
134*7c478bd9Sstevel@tonic-gate 			if (strcmp(model->name, model_name) == 0)
135*7c478bd9Sstevel@tonic-gate 				break;
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 		if (model->name == NULL)
138*7c478bd9Sstevel@tonic-gate 			error = B_TRUE;
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/* skip over previously processed arguments */
142*7c478bd9Sstevel@tonic-gate 	argc -= optind;
143*7c478bd9Sstevel@tonic-gate 	argv += optind;
144*7c478bd9Sstevel@tonic-gate 	if (argc < 1)
145*7c478bd9Sstevel@tonic-gate 		error = B_TRUE;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	if (error) {
148*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Usage: %s [-d] {-m datamodel} "
149*7c478bd9Sstevel@tonic-gate 		    "{-t output_type} files\n", program);
150*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tSupported data models:\n");
151*7c478bd9Sstevel@tonic-gate 		for (model = models; model->name != NULL; model++)
152*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "\t\t%s\n", model->name);
153*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tSupported output types:\n");
154*7c478bd9Sstevel@tonic-gate 		for (ops = ops_table; ops->type != NULL; ops++)
155*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "\t\t%s\n", ops->type);
156*7c478bd9Sstevel@tonic-gate 		return (1);
157*7c478bd9Sstevel@tonic-gate 	}
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	parse_input();
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	get_dbgs(argc, argv);
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	return (error ? 1 : 0);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * This routine will read the .dbg files and build a list of the structures
168*7c478bd9Sstevel@tonic-gate  * and fields that user is interested in. Any struct specified will get all
169*7c478bd9Sstevel@tonic-gate  * its fields included. If nested struct needs to be printed - then the
170*7c478bd9Sstevel@tonic-gate  * field name and name of struct type needs to be included in the next line.
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate static void
173*7c478bd9Sstevel@tonic-gate get_dbgs(int argc, char **argv)
174*7c478bd9Sstevel@tonic-gate {
175*7c478bd9Sstevel@tonic-gate 	FILE *fp;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	for (; argc != 0; argc--, argv++) {
178*7c478bd9Sstevel@tonic-gate 		if ((fp = fopen(*argv, "r")) == NULL) {
179*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Cannot open %s\n", *argv);
180*7c478bd9Sstevel@tonic-gate 			error = B_TRUE;
181*7c478bd9Sstevel@tonic-gate 			return;
182*7c478bd9Sstevel@tonic-gate 		}
183*7c478bd9Sstevel@tonic-gate 		/* add all types in this file to our table */
184*7c478bd9Sstevel@tonic-gate 		parse_dbg(fp);
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate static char *
189*7c478bd9Sstevel@tonic-gate namex(char *cp, char **w)
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	char *new, *orig, c;
192*7c478bd9Sstevel@tonic-gate 	int len;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	if (*cp == '\0') {
195*7c478bd9Sstevel@tonic-gate 		*w = NULL;
196*7c478bd9Sstevel@tonic-gate 		return (cp);
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	for (c = *cp++; isspace(c); c = *cp++)
200*7c478bd9Sstevel@tonic-gate 		;
201*7c478bd9Sstevel@tonic-gate 	orig = --cp;
202*7c478bd9Sstevel@tonic-gate 	c = *cp++;
203*7c478bd9Sstevel@tonic-gate 	if (isalpha(c) || ispunct(c)) {
204*7c478bd9Sstevel@tonic-gate 		for (c = *cp++; isalnum(c) || ispunct(c); c = *cp++)
205*7c478bd9Sstevel@tonic-gate 			;
206*7c478bd9Sstevel@tonic-gate 		len = cp - orig;
207*7c478bd9Sstevel@tonic-gate 		new = (char *)malloc(len);
208*7c478bd9Sstevel@tonic-gate 		while (orig < cp - 1)
209*7c478bd9Sstevel@tonic-gate 			*new++ = *orig++;
210*7c478bd9Sstevel@tonic-gate 		*new = '\0';
211*7c478bd9Sstevel@tonic-gate 		*w = new - (len - 1);
212*7c478bd9Sstevel@tonic-gate 	} else if (c != '\0') {
213*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "line %d has bad character %c\n", line, c);
214*7c478bd9Sstevel@tonic-gate 		error = B_TRUE;
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	return (cp);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate /*
221*7c478bd9Sstevel@tonic-gate  * checks to see if this field in the struct was requested for by user
222*7c478bd9Sstevel@tonic-gate  * in the .dbg file.
223*7c478bd9Sstevel@tonic-gate  */
224*7c478bd9Sstevel@tonic-gate struct child *
225*7c478bd9Sstevel@tonic-gate find_child(struct node *np, char *w)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	struct child *chp;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	for (chp = np->child; chp != NULL; chp = chp->next) {
230*7c478bd9Sstevel@tonic-gate 		if (strcmp(chp->name, w) == 0)
231*7c478bd9Sstevel@tonic-gate 			return (chp);
232*7c478bd9Sstevel@tonic-gate 	}
233*7c478bd9Sstevel@tonic-gate 	return (NULL);
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate static struct tdesc *
237*7c478bd9Sstevel@tonic-gate find_member(struct tdesc *tdp, char *name)
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate 	struct mlist *mlp;
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	while (tdp->type == TYPEOF)
242*7c478bd9Sstevel@tonic-gate 		tdp = tdp->data.tdesc;
243*7c478bd9Sstevel@tonic-gate 	if (tdp->type != STRUCT && tdp->type != UNION)
244*7c478bd9Sstevel@tonic-gate 		return (NULL);
245*7c478bd9Sstevel@tonic-gate 	for (mlp = tdp->data.members.forw; mlp != NULL; mlp = mlp->next)
246*7c478bd9Sstevel@tonic-gate 		if (strcmp(mlp->name, name) == 0)
247*7c478bd9Sstevel@tonic-gate 			return (mlp->fdesc);
248*7c478bd9Sstevel@tonic-gate 	return (NULL);
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate /*
252*7c478bd9Sstevel@tonic-gate  * add this field to our table of structs/fields that the user has
253*7c478bd9Sstevel@tonic-gate  * requested in the .dbg files
254*7c478bd9Sstevel@tonic-gate  */
255*7c478bd9Sstevel@tonic-gate static void
256*7c478bd9Sstevel@tonic-gate addchild(char *cp, struct node *np)
257*7c478bd9Sstevel@tonic-gate {
258*7c478bd9Sstevel@tonic-gate 	struct child *chp;
259*7c478bd9Sstevel@tonic-gate 	char *w;
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	chp = malloc(sizeof (*chp));
262*7c478bd9Sstevel@tonic-gate 	cp = namex(cp, &w);
263*7c478bd9Sstevel@tonic-gate 	chp->name = w;
264*7c478bd9Sstevel@tonic-gate 	cp = namex(cp, &w);
265*7c478bd9Sstevel@tonic-gate 	if (w == NULL) {
266*7c478bd9Sstevel@tonic-gate 		if (chp->name == NULL) {
267*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "NULL child name\n");
268*7c478bd9Sstevel@tonic-gate 			exit(1);
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 		/* XXX - always convert to upper-case? */
271*7c478bd9Sstevel@tonic-gate 		chp->format = uc(chp->name);
272*7c478bd9Sstevel@tonic-gate 	} else {
273*7c478bd9Sstevel@tonic-gate 		chp->format = w;
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 	chp->next = np->child;
276*7c478bd9Sstevel@tonic-gate 	np->child = chp;
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate /*
280*7c478bd9Sstevel@tonic-gate  * add this struct to our table of structs/fields that the user has
281*7c478bd9Sstevel@tonic-gate  * requested in the .dbg files
282*7c478bd9Sstevel@tonic-gate  */
283*7c478bd9Sstevel@tonic-gate static struct node *
284*7c478bd9Sstevel@tonic-gate getnode(char *cp)
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	char *w;
287*7c478bd9Sstevel@tonic-gate 	struct node *np;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	cp = namex(cp, &w);
290*7c478bd9Sstevel@tonic-gate 	np = malloc(sizeof (*np));
291*7c478bd9Sstevel@tonic-gate 	np->name = w;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	/*
294*7c478bd9Sstevel@tonic-gate 	 * XXX - These positional parameters are a hack
295*7c478bd9Sstevel@tonic-gate 	 * We have two right now for genassym.  The back-ends
296*7c478bd9Sstevel@tonic-gate 	 * can use format and format2 any way they'd like.
297*7c478bd9Sstevel@tonic-gate 	 */
298*7c478bd9Sstevel@tonic-gate 	cp = namex(cp, &w);
299*7c478bd9Sstevel@tonic-gate 	np->format = w;
300*7c478bd9Sstevel@tonic-gate 	if (w != NULL) {
301*7c478bd9Sstevel@tonic-gate 		w = NULL;
302*7c478bd9Sstevel@tonic-gate 		cp = namex(cp, &w);
303*7c478bd9Sstevel@tonic-gate 		np->format2 = w;
304*7c478bd9Sstevel@tonic-gate 	} else {
305*7c478bd9Sstevel@tonic-gate 		np->format2 = NULL;
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 	np->child = NULL;
308*7c478bd9Sstevel@tonic-gate 	return (np);
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate /*
312*7c478bd9Sstevel@tonic-gate  * Format for .dbg files should be
313*7c478bd9Sstevel@tonic-gate  * Ex:
314*7c478bd9Sstevel@tonic-gate  * seg
315*7c478bd9Sstevel@tonic-gate  *	as		s_as
316*7c478bd9Sstevel@tonic-gate  * if you wanted the contents of "s_as" (a pointer) to be printed in
317*7c478bd9Sstevel@tonic-gate  * the format of a "as"
318*7c478bd9Sstevel@tonic-gate  */
319*7c478bd9Sstevel@tonic-gate static void
320*7c478bd9Sstevel@tonic-gate parse_dbg(FILE *sp)
321*7c478bd9Sstevel@tonic-gate {
322*7c478bd9Sstevel@tonic-gate 	char *cp;
323*7c478bd9Sstevel@tonic-gate 	struct node *np;
324*7c478bd9Sstevel@tonic-gate 	static char linebuf[MAXLINE];
325*7c478bd9Sstevel@tonic-gate 	int copy_flag = 0;
326*7c478bd9Sstevel@tonic-gate 	int ignore_flag = 0;
327*7c478bd9Sstevel@tonic-gate 	size_t c;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	/* grab each line and add them to our table */
330*7c478bd9Sstevel@tonic-gate 	for (line = 1; (cp = fgets(linebuf, MAXLINE, sp)) != NULL; line++) {
331*7c478bd9Sstevel@tonic-gate 		if (*cp == '\n') {
332*7c478bd9Sstevel@tonic-gate 			if (copy_flag)
333*7c478bd9Sstevel@tonic-gate 				printf("\n");
334*7c478bd9Sstevel@tonic-gate 			continue;
335*7c478bd9Sstevel@tonic-gate 		}
336*7c478bd9Sstevel@tonic-gate 		if (*cp == '\\') {
337*7c478bd9Sstevel@tonic-gate 			if (cp[1] == '#')
338*7c478bd9Sstevel@tonic-gate 				printf("%s", (cp + 1));
339*7c478bd9Sstevel@tonic-gate 			continue;
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 		if (strcmp(cp, "model_end\n") == 0) {
342*7c478bd9Sstevel@tonic-gate 			if (ignore_flag)
343*7c478bd9Sstevel@tonic-gate 				ignore_flag = 0;
344*7c478bd9Sstevel@tonic-gate 			continue;
345*7c478bd9Sstevel@tonic-gate 		}
346*7c478bd9Sstevel@tonic-gate 		if (ignore_flag)
347*7c478bd9Sstevel@tonic-gate 			continue;
348*7c478bd9Sstevel@tonic-gate 		c = strlen("model_start ");
349*7c478bd9Sstevel@tonic-gate 		if (strncmp(cp, "model_start ", c) == 0) {
350*7c478bd9Sstevel@tonic-gate 			if (strncmp(cp + c, model->name, strlen(model->name))
351*7c478bd9Sstevel@tonic-gate 			    == 0 && *(cp + c + strlen(model->name)) == '\n')
352*7c478bd9Sstevel@tonic-gate 				/* model matches */;
353*7c478bd9Sstevel@tonic-gate 			else
354*7c478bd9Sstevel@tonic-gate 				ignore_flag = 1;
355*7c478bd9Sstevel@tonic-gate 			continue;
356*7c478bd9Sstevel@tonic-gate 		}
357*7c478bd9Sstevel@tonic-gate 		if ((strcmp(cp, "verbatim_begin\n") == 0) ||
358*7c478bd9Sstevel@tonic-gate 		    (strcmp(cp, "forth_start\n") == 0)) {
359*7c478bd9Sstevel@tonic-gate 			copy_flag = 1;
360*7c478bd9Sstevel@tonic-gate 			continue;
361*7c478bd9Sstevel@tonic-gate 		}
362*7c478bd9Sstevel@tonic-gate 		if ((strcmp(cp, "verbatim_end\n") == 0) ||
363*7c478bd9Sstevel@tonic-gate 		    (strcmp(cp, "forth_end\n") == 0)) {
364*7c478bd9Sstevel@tonic-gate 			copy_flag = 0;
365*7c478bd9Sstevel@tonic-gate 			continue;
366*7c478bd9Sstevel@tonic-gate 		}
367*7c478bd9Sstevel@tonic-gate 		if (copy_flag) {
368*7c478bd9Sstevel@tonic-gate 			printf("%s", cp);
369*7c478bd9Sstevel@tonic-gate 			continue;
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 		np = getnode(cp);
372*7c478bd9Sstevel@tonic-gate 		for (line++;
373*7c478bd9Sstevel@tonic-gate 		    ((cp = fgets(linebuf, MAXLINE, sp)) != NULL) &&
374*7c478bd9Sstevel@tonic-gate 			 *cp != '\n'; line++) {
375*7c478bd9Sstevel@tonic-gate 			/* members of struct, union or enum */
376*7c478bd9Sstevel@tonic-gate 			addchild(cp, np);
377*7c478bd9Sstevel@tonic-gate 		}
378*7c478bd9Sstevel@tonic-gate 		printnode(np);
379*7c478bd9Sstevel@tonic-gate 	}
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate static void
383*7c478bd9Sstevel@tonic-gate printnode(struct node *np)
384*7c478bd9Sstevel@tonic-gate {
385*7c478bd9Sstevel@tonic-gate 	struct tdesc *tdp;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	tdp = lookupname(np->name);
388*7c478bd9Sstevel@tonic-gate 	if (tdp == NULL) {
389*7c478bd9Sstevel@tonic-gate 		char *member;
390*7c478bd9Sstevel@tonic-gate 		struct tdesc *ptdp;
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 		if ((member = strchr(np->name, '.')) != NULL) {
393*7c478bd9Sstevel@tonic-gate 			*member = '\0';
394*7c478bd9Sstevel@tonic-gate 			ptdp = lookupname(np->name);
395*7c478bd9Sstevel@tonic-gate 			if (ptdp != NULL)
396*7c478bd9Sstevel@tonic-gate 				tdp = find_member(ptdp, member + 1);
397*7c478bd9Sstevel@tonic-gate 			*member = '.';
398*7c478bd9Sstevel@tonic-gate 		}
399*7c478bd9Sstevel@tonic-gate 		if (tdp == NULL) {
400*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Can't find %s\n", np->name);
401*7c478bd9Sstevel@tonic-gate 			error = B_TRUE;
402*7c478bd9Sstevel@tonic-gate 			return;
403*7c478bd9Sstevel@tonic-gate 		}
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate again:
406*7c478bd9Sstevel@tonic-gate 	switch (tdp->type) {
407*7c478bd9Sstevel@tonic-gate 	case STRUCT:
408*7c478bd9Sstevel@tonic-gate 	case UNION:
409*7c478bd9Sstevel@tonic-gate 		ops->do_sou(tdp, np);
410*7c478bd9Sstevel@tonic-gate 		break;
411*7c478bd9Sstevel@tonic-gate 	case ENUM:
412*7c478bd9Sstevel@tonic-gate 		ops->do_enum(tdp, np);
413*7c478bd9Sstevel@tonic-gate 		break;
414*7c478bd9Sstevel@tonic-gate 	case TYPEOF:
415*7c478bd9Sstevel@tonic-gate 		tdp = tdp->data.tdesc;
416*7c478bd9Sstevel@tonic-gate 		goto again;
417*7c478bd9Sstevel@tonic-gate 	case INTRINSIC:
418*7c478bd9Sstevel@tonic-gate 		ops->do_intrinsic(tdp, np);
419*7c478bd9Sstevel@tonic-gate 		break;
420*7c478bd9Sstevel@tonic-gate 	default:
421*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s isn't aggregate\n", np->name);
422*7c478bd9Sstevel@tonic-gate 		error = B_TRUE;
423*7c478bd9Sstevel@tonic-gate 		break;
424*7c478bd9Sstevel@tonic-gate 	}
425*7c478bd9Sstevel@tonic-gate }
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate char *
429*7c478bd9Sstevel@tonic-gate convert_format(char *format, char *dfault)
430*7c478bd9Sstevel@tonic-gate {
431*7c478bd9Sstevel@tonic-gate 	static char dot[3] = ".";
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	if (format == NULL)
434*7c478bd9Sstevel@tonic-gate 		return (dfault);
435*7c478bd9Sstevel@tonic-gate 	else if (strlen(format) == 1) {
436*7c478bd9Sstevel@tonic-gate 		dot[1] = *format;
437*7c478bd9Sstevel@tonic-gate 		return (dot);
438*7c478bd9Sstevel@tonic-gate 	} else
439*7c478bd9Sstevel@tonic-gate 		return (format);
440*7c478bd9Sstevel@tonic-gate }
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate char *
443*7c478bd9Sstevel@tonic-gate uc(const char *s)
444*7c478bd9Sstevel@tonic-gate {
445*7c478bd9Sstevel@tonic-gate 	char *buf;
446*7c478bd9Sstevel@tonic-gate 	int i;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	buf = strdup(s);
449*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < strlen(buf); i++)
450*7c478bd9Sstevel@tonic-gate 		buf[i] = toupper(buf[i]);
451*7c478bd9Sstevel@tonic-gate 	buf[i] = '\0';
452*7c478bd9Sstevel@tonic-gate 	return (buf);
453*7c478bd9Sstevel@tonic-gate }
454