xref: /onnv-gate/usr/src/cmd/adbgen/common/adbgen1.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * Read in "high-level" adb script and emit C program.
31*0Sstevel@tonic-gate  * The input may have specifications within {} which
32*0Sstevel@tonic-gate  * we analyze and then emit C code to generate the
33*0Sstevel@tonic-gate  * ultimate adb acript.
34*0Sstevel@tonic-gate  * We are just a filter; no arguments are accepted.
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <stdio.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include <string.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #define	streq(s1, s2)	(strcmp(s1, s2) == 0)
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate #define	LINELEN  	1024	/* max line length expected in input */
44*0Sstevel@tonic-gate #define	STRLEN		128	/* for shorter strings */
45*0Sstevel@tonic-gate #define	NARGS		5	/* number of emitted subroutine arguments */
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate /*
48*0Sstevel@tonic-gate  * Format specifier strings
49*0Sstevel@tonic-gate  * which are recognized by adbgen when surrounded by {}
50*0Sstevel@tonic-gate  */
51*0Sstevel@tonic-gate #define	FSTR_PTR	"POINTER"
52*0Sstevel@tonic-gate #define	FSTR_LONG_DEC	"LONGDEC"
53*0Sstevel@tonic-gate #define	FSTR_LONG_OCT	"LONGOCT"
54*0Sstevel@tonic-gate #define	FSTR_ULONG_DEC	"ULONGDEC"
55*0Sstevel@tonic-gate #define	FSTR_ULONG_HEX	"ULONGHEX"
56*0Sstevel@tonic-gate #define	FSTR_ULONG_OCT	"ULONGOCT"
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate /*
59*0Sstevel@tonic-gate  * Types of specifications in {}.
60*0Sstevel@tonic-gate  */
61*0Sstevel@tonic-gate #define	PTR_HEX		0	/* emit hex pointer format char */
62*0Sstevel@tonic-gate #define	LONG_DEC	1	/* emit decimal long format char */
63*0Sstevel@tonic-gate #define	LONG_OCT	2	/* emit octal unsigned long format char */
64*0Sstevel@tonic-gate #define	ULONG_DEC	3	/* emit decimal unsigned long format char */
65*0Sstevel@tonic-gate #define	ULONG_HEX	4	/* emit hexadecimal long format char */
66*0Sstevel@tonic-gate #define	ULONG_OCT	5	/* emit octal unsigned long format char */
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #define	FMT_ENTRIES	6	/* number of adbgen format specifier strings */
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate #define	PRINT   	6	/* print member name with format */
71*0Sstevel@tonic-gate #define	INDIRECT	7	/* fetch member value */
72*0Sstevel@tonic-gate #define	OFFSETOK	8	/* insist that the offset is ok */
73*0Sstevel@tonic-gate #define	SIZEOF		9	/* print sizeof struct */
74*0Sstevel@tonic-gate #define	END		10	/* get offset to end of struct */
75*0Sstevel@tonic-gate #define	OFFSET		11	/* just emit offset */
76*0Sstevel@tonic-gate #define	EXPR		12	/* arbitrary C expression */
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate /*
79*0Sstevel@tonic-gate  * Special return code from nextchar.
80*0Sstevel@tonic-gate  */
81*0Sstevel@tonic-gate #define	CPP		-2	/* cpp line, restart parsing */
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate typedef struct adbgen_fmt {
84*0Sstevel@tonic-gate 	char *f_str;
85*0Sstevel@tonic-gate 	char f_char;
86*0Sstevel@tonic-gate } adbgen_fmt_t;
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate char struct_name[STRLEN];	/* struct name */
89*0Sstevel@tonic-gate char member[STRLEN];		/* member name */
90*0Sstevel@tonic-gate char format[STRLEN];		/* adb format spec */
91*0Sstevel@tonic-gate char arg[NARGS][STRLEN];	/* arg list for called subroutine */
92*0Sstevel@tonic-gate char *ptr_hex_fmt;		/* adb format character for pointer in hex */
93*0Sstevel@tonic-gate char *long_dec_fmt;		/* adb format character for long in decimal */
94*0Sstevel@tonic-gate char *ulong_dec_fmt;		/* adb format character for ulong in decimal */
95*0Sstevel@tonic-gate char *ulong_hex_fmt;		/* adb format character for ulong in hex */
96*0Sstevel@tonic-gate char *long_oct_fmt;		/* adb format character for long in octal */
97*0Sstevel@tonic-gate char *ulong_oct_fmt;		/* adb format character for ulong in octal */
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate int line_no = 1;		/* input line number - for error messages */
100*0Sstevel@tonic-gate int specsize;			/* size of {} specification - 1 or 2 parts */
101*0Sstevel@tonic-gate int state;			/* XXX 1 = gathering a printf */
102*0Sstevel@tonic-gate 				/* This is a kludge so we emit pending */
103*0Sstevel@tonic-gate 				/* printf's when we see a CPP line */
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate adbgen_fmt_t adbgen_fmt_tbl [FMT_ENTRIES] = {
106*0Sstevel@tonic-gate 	{FSTR_PTR},
107*0Sstevel@tonic-gate 	{FSTR_LONG_DEC},
108*0Sstevel@tonic-gate 	{FSTR_LONG_OCT},
109*0Sstevel@tonic-gate 	{FSTR_ULONG_DEC},
110*0Sstevel@tonic-gate 	{FSTR_ULONG_HEX},
111*0Sstevel@tonic-gate 	{FSTR_ULONG_OCT}
112*0Sstevel@tonic-gate };
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate void emit_call(char *name, int nargs);
115*0Sstevel@tonic-gate void emit_end(void);
116*0Sstevel@tonic-gate void emit_expr(void);
117*0Sstevel@tonic-gate void emit_indirect(void);
118*0Sstevel@tonic-gate void emit_offset(void);
119*0Sstevel@tonic-gate void emit_offsetok(void);
120*0Sstevel@tonic-gate void emit_print(void);
121*0Sstevel@tonic-gate void emit_printf(char *cp);
122*0Sstevel@tonic-gate void emit_sizeof(void);
123*0Sstevel@tonic-gate void generate(void);
124*0Sstevel@tonic-gate int get_type(void);
125*0Sstevel@tonic-gate int nextchar(char *cp);
126*0Sstevel@tonic-gate void read_spec(void);
127*0Sstevel@tonic-gate char *start_printf(void);
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate int
main(int argc,char ** argv)130*0Sstevel@tonic-gate main(int argc, char **argv)
131*0Sstevel@tonic-gate {
132*0Sstevel@tonic-gate 	char *cp;
133*0Sstevel@tonic-gate 	int c;
134*0Sstevel@tonic-gate 	int warn_flag = 0;
135*0Sstevel@tonic-gate 	int is_lp64 = 0;
136*0Sstevel@tonic-gate 	char *usage = "adbgen1 [-w] [-m ilp32|lp64] < <macro file>\n";
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "m:w")) != EOF) {
139*0Sstevel@tonic-gate 		switch (c) {
140*0Sstevel@tonic-gate 		case 'm':
141*0Sstevel@tonic-gate 			if (streq(optarg, "ilp32"))
142*0Sstevel@tonic-gate 				is_lp64 = 0;
143*0Sstevel@tonic-gate 			else if (streq(optarg, "lp64"))
144*0Sstevel@tonic-gate 				is_lp64 = 1;
145*0Sstevel@tonic-gate 			else
146*0Sstevel@tonic-gate 				fprintf(stderr, usage);
147*0Sstevel@tonic-gate 			break;
148*0Sstevel@tonic-gate 		case 'w':
149*0Sstevel@tonic-gate 			warn_flag++;
150*0Sstevel@tonic-gate 			break;
151*0Sstevel@tonic-gate 		case '?':
152*0Sstevel@tonic-gate 			fprintf(stderr, usage);
153*0Sstevel@tonic-gate 			break;
154*0Sstevel@tonic-gate 		}
155*0Sstevel@tonic-gate 	}
156*0Sstevel@tonic-gate 	if (is_lp64) {
157*0Sstevel@tonic-gate 		adbgen_fmt_tbl[PTR_HEX].f_char = 'J';
158*0Sstevel@tonic-gate 		adbgen_fmt_tbl[LONG_DEC].f_char = 'e';
159*0Sstevel@tonic-gate 		adbgen_fmt_tbl[LONG_OCT].f_char = 'g';
160*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_DEC].f_char = 'E';
161*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_HEX].f_char = 'J';
162*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_OCT].f_char = 'G';
163*0Sstevel@tonic-gate 	} else {
164*0Sstevel@tonic-gate 		adbgen_fmt_tbl[PTR_HEX].f_char = 'X';
165*0Sstevel@tonic-gate 		adbgen_fmt_tbl[LONG_DEC].f_char = 'D';
166*0Sstevel@tonic-gate 		adbgen_fmt_tbl[LONG_OCT].f_char = 'Q';
167*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_DEC].f_char = 'U';
168*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_HEX].f_char = 'X';
169*0Sstevel@tonic-gate 		adbgen_fmt_tbl[ULONG_OCT].f_char = 'O';
170*0Sstevel@tonic-gate 	}
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	/*
173*0Sstevel@tonic-gate 	 * Get structure name.
174*0Sstevel@tonic-gate 	 */
175*0Sstevel@tonic-gate 	cp = struct_name;
176*0Sstevel@tonic-gate 	while ((c = nextchar(NULL)) != '\n') {
177*0Sstevel@tonic-gate 		if (c == EOF) {
178*0Sstevel@tonic-gate 			fprintf(stderr, "Premature EOF\n");
179*0Sstevel@tonic-gate 			exit(1);
180*0Sstevel@tonic-gate 		}
181*0Sstevel@tonic-gate 		if (c == CPP)
182*0Sstevel@tonic-gate 			continue;
183*0Sstevel@tonic-gate 		*cp++ = (char)c;
184*0Sstevel@tonic-gate 	}
185*0Sstevel@tonic-gate 	*cp = '\0';
186*0Sstevel@tonic-gate 	/*
187*0Sstevel@tonic-gate 	 * Basically, the generated program is just an ongoing printf
188*0Sstevel@tonic-gate 	 * with breaks for {} format specifications.
189*0Sstevel@tonic-gate 	 */
190*0Sstevel@tonic-gate 	printf("\n");
191*0Sstevel@tonic-gate 	printf("#include <sys/types.h>\n");
192*0Sstevel@tonic-gate 	printf("#include <sys/inttypes.h>\n");
193*0Sstevel@tonic-gate 	printf("\n\n");
194*0Sstevel@tonic-gate 	printf("int do_fmt(char *acp);\n");
195*0Sstevel@tonic-gate 	printf("void format(char *name, size_t size, char *fmt);\n");
196*0Sstevel@tonic-gate 	printf("void indirect(off_t offset, size_t size, "
197*0Sstevel@tonic-gate 	    "char *base, char *member);\n");
198*0Sstevel@tonic-gate 	printf("void offset(off_t off);\n");
199*0Sstevel@tonic-gate 	printf("void offsetok(void);\n");
200*0Sstevel@tonic-gate 	printf("\n\n");
201*0Sstevel@tonic-gate 	printf("main(int argc, char *argv[])\n");
202*0Sstevel@tonic-gate 	printf("{\n");
203*0Sstevel@tonic-gate 	if (warn_flag) {
204*0Sstevel@tonic-gate 		printf("\textern int warnings;\n\n\twarnings = 0;\n");
205*0Sstevel@tonic-gate 	}
206*0Sstevel@tonic-gate 	cp = start_printf();
207*0Sstevel@tonic-gate 	while ((c = nextchar(cp)) != EOF) {
208*0Sstevel@tonic-gate 		switch (c) {
209*0Sstevel@tonic-gate 		case '"':
210*0Sstevel@tonic-gate 			*cp++ = '\\';	/* escape ' in string */
211*0Sstevel@tonic-gate 			*cp++ = '"';
212*0Sstevel@tonic-gate 			break;
213*0Sstevel@tonic-gate 		case '\n':
214*0Sstevel@tonic-gate 			*cp++ = '\\';	/* escape newline in string */
215*0Sstevel@tonic-gate 			*cp++ = 'n';
216*0Sstevel@tonic-gate 			break;
217*0Sstevel@tonic-gate 		case '{':
218*0Sstevel@tonic-gate 			emit_printf(cp);
219*0Sstevel@tonic-gate 			read_spec();
220*0Sstevel@tonic-gate 			generate();
221*0Sstevel@tonic-gate 			cp = start_printf();
222*0Sstevel@tonic-gate 			break;
223*0Sstevel@tonic-gate 		case CPP:
224*0Sstevel@tonic-gate 			/*
225*0Sstevel@tonic-gate 			 * Restart printf after cpp line.
226*0Sstevel@tonic-gate 			 */
227*0Sstevel@tonic-gate 			cp = start_printf();
228*0Sstevel@tonic-gate 			break;
229*0Sstevel@tonic-gate 		default:
230*0Sstevel@tonic-gate 			*cp++ = c;
231*0Sstevel@tonic-gate 			break;
232*0Sstevel@tonic-gate 		}
233*0Sstevel@tonic-gate 		if (cp - arg[1] >= STRLEN - 10) {
234*0Sstevel@tonic-gate 			emit_printf(cp);
235*0Sstevel@tonic-gate 			cp = start_printf();
236*0Sstevel@tonic-gate 		}
237*0Sstevel@tonic-gate 	}
238*0Sstevel@tonic-gate 	emit_printf(cp);
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 	/* terminate program, checking for "error" mode */
241*0Sstevel@tonic-gate 	printf("\n\tif (argc > 1 && strcmp(argv[1], \"-e\") == 0) {\n");
242*0Sstevel@tonic-gate 	printf("\t\textern int warns;\n\n");
243*0Sstevel@tonic-gate 	printf("\t\tif (warns)\n");
244*0Sstevel@tonic-gate 	printf("\t\t\treturn (1);\n");
245*0Sstevel@tonic-gate 	printf("\t}\n");
246*0Sstevel@tonic-gate 	printf("\treturn (0);\n");
247*0Sstevel@tonic-gate 	printf("}\n");
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 	return (0);
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate int
nextchar(char * cp)253*0Sstevel@tonic-gate nextchar(char *cp)
254*0Sstevel@tonic-gate {
255*0Sstevel@tonic-gate 	int c;
256*0Sstevel@tonic-gate 	static int newline = 1;
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	c = getchar();
259*0Sstevel@tonic-gate 	/*
260*0Sstevel@tonic-gate 	 * Lines beginning with '#' and blank lines are passed right through.
261*0Sstevel@tonic-gate 	 */
262*0Sstevel@tonic-gate 	while (newline) {
263*0Sstevel@tonic-gate 		switch (c) {
264*0Sstevel@tonic-gate 		case '#':
265*0Sstevel@tonic-gate 			if (state)
266*0Sstevel@tonic-gate 				emit_printf(cp);
267*0Sstevel@tonic-gate 			do {
268*0Sstevel@tonic-gate 				putchar(c);
269*0Sstevel@tonic-gate 				c = getchar();
270*0Sstevel@tonic-gate 				if (c == EOF)
271*0Sstevel@tonic-gate 					return (c);
272*0Sstevel@tonic-gate 			} while (c != '\n');
273*0Sstevel@tonic-gate 			putchar(c);
274*0Sstevel@tonic-gate 			line_no++;
275*0Sstevel@tonic-gate 			return (CPP);
276*0Sstevel@tonic-gate 		case '\n':
277*0Sstevel@tonic-gate 			if (state)
278*0Sstevel@tonic-gate 				emit_printf(cp);
279*0Sstevel@tonic-gate 			putchar(c);
280*0Sstevel@tonic-gate 			c = getchar();
281*0Sstevel@tonic-gate 			line_no++;
282*0Sstevel@tonic-gate 			break;
283*0Sstevel@tonic-gate 		default:
284*0Sstevel@tonic-gate 			newline = 0;
285*0Sstevel@tonic-gate 			break;
286*0Sstevel@tonic-gate 		}
287*0Sstevel@tonic-gate 	}
288*0Sstevel@tonic-gate 	if (c == '\n') {
289*0Sstevel@tonic-gate 		newline++;
290*0Sstevel@tonic-gate 		line_no++;
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 	return (c);
293*0Sstevel@tonic-gate }
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate /*
296*0Sstevel@tonic-gate  * Get started on printf of ongoing adb script.
297*0Sstevel@tonic-gate  */
298*0Sstevel@tonic-gate char *
start_printf(void)299*0Sstevel@tonic-gate start_printf(void)
300*0Sstevel@tonic-gate {
301*0Sstevel@tonic-gate 	char *cp;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	strcpy(arg[0], "\"%s\"");
304*0Sstevel@tonic-gate 	cp = arg[1];
305*0Sstevel@tonic-gate 	*cp++ = '"';
306*0Sstevel@tonic-gate 	state = 1;			/* XXX */
307*0Sstevel@tonic-gate 	return (cp);
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate /*
311*0Sstevel@tonic-gate  * Emit call to printf to print part of ongoing adb script.
312*0Sstevel@tonic-gate  */
313*0Sstevel@tonic-gate void
emit_printf(cp)314*0Sstevel@tonic-gate emit_printf(cp)
315*0Sstevel@tonic-gate 	char *cp;
316*0Sstevel@tonic-gate {
317*0Sstevel@tonic-gate 	*cp++ = '"';
318*0Sstevel@tonic-gate 	*cp = '\0';
319*0Sstevel@tonic-gate 	emit_call("printf", 2);
320*0Sstevel@tonic-gate 	state = 0;			/* XXX */
321*0Sstevel@tonic-gate }
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate /*
324*0Sstevel@tonic-gate  * Read {} specification.
325*0Sstevel@tonic-gate  * The first part (up to a comma) is put into "member".
326*0Sstevel@tonic-gate  * The second part, if present, is put into "format".
327*0Sstevel@tonic-gate  */
328*0Sstevel@tonic-gate void
read_spec(void)329*0Sstevel@tonic-gate read_spec(void)
330*0Sstevel@tonic-gate {
331*0Sstevel@tonic-gate 	char *cp;
332*0Sstevel@tonic-gate 	int c;
333*0Sstevel@tonic-gate 	int nesting;
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	cp = member;
336*0Sstevel@tonic-gate 	specsize = 1;
337*0Sstevel@tonic-gate 	nesting = 0;
338*0Sstevel@tonic-gate 	while ((c = nextchar(NULL)) != '}' || (c == '}' && nesting)) {
339*0Sstevel@tonic-gate 		switch (c) {
340*0Sstevel@tonic-gate 		case EOF:
341*0Sstevel@tonic-gate 			fprintf(stderr, "Unexpected EOF inside {}\n");
342*0Sstevel@tonic-gate 			exit(1);
343*0Sstevel@tonic-gate 		case '\n':
344*0Sstevel@tonic-gate 			fprintf(stderr, "Newline not allowed in {}, line %d\n",
345*0Sstevel@tonic-gate 				line_no);
346*0Sstevel@tonic-gate 			exit(1);
347*0Sstevel@tonic-gate 		case '#':
348*0Sstevel@tonic-gate 			fprintf(stderr, "# not allowed in {}, line %d\n",
349*0Sstevel@tonic-gate 				line_no);
350*0Sstevel@tonic-gate 			exit(1);
351*0Sstevel@tonic-gate 		case ',':
352*0Sstevel@tonic-gate 			if (specsize == 2) {
353*0Sstevel@tonic-gate 				fprintf(stderr, "Excessive commas in {}, ");
354*0Sstevel@tonic-gate 				fprintf(stderr, "line %d\n", line_no);
355*0Sstevel@tonic-gate 				exit(1);
356*0Sstevel@tonic-gate 			}
357*0Sstevel@tonic-gate 			specsize = 2;
358*0Sstevel@tonic-gate 			*cp = '\0';
359*0Sstevel@tonic-gate 			cp = format;
360*0Sstevel@tonic-gate 			break;
361*0Sstevel@tonic-gate 		case '{':
362*0Sstevel@tonic-gate 			/*
363*0Sstevel@tonic-gate 			 * Allow up to one set of nested {}'s for adbgen
364*0Sstevel@tonic-gate 			 * requests of the form {member, {format string}}
365*0Sstevel@tonic-gate 			 */
366*0Sstevel@tonic-gate 			if (!nesting) {
367*0Sstevel@tonic-gate 				nesting = 1;
368*0Sstevel@tonic-gate 				*cp++ = c;
369*0Sstevel@tonic-gate 			} else {
370*0Sstevel@tonic-gate 				fprintf(stderr, "Too many {'s, line %d\n",
371*0Sstevel@tonic-gate 					line_no);
372*0Sstevel@tonic-gate 				exit(1);
373*0Sstevel@tonic-gate 			}
374*0Sstevel@tonic-gate 			break;
375*0Sstevel@tonic-gate 		case '}':
376*0Sstevel@tonic-gate 			*cp++ = c;
377*0Sstevel@tonic-gate 			nesting = 0;
378*0Sstevel@tonic-gate 			break;
379*0Sstevel@tonic-gate 		default:
380*0Sstevel@tonic-gate 			*cp++ = c;
381*0Sstevel@tonic-gate 			break;
382*0Sstevel@tonic-gate 		}
383*0Sstevel@tonic-gate 	}
384*0Sstevel@tonic-gate 	*cp = '\0';
385*0Sstevel@tonic-gate 	if (cp == member) {
386*0Sstevel@tonic-gate 		specsize = 0;
387*0Sstevel@tonic-gate 	}
388*0Sstevel@tonic-gate }
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate /*
391*0Sstevel@tonic-gate  * Decide what type of input specification we have.
392*0Sstevel@tonic-gate  */
393*0Sstevel@tonic-gate int
get_type(void)394*0Sstevel@tonic-gate get_type(void)
395*0Sstevel@tonic-gate {
396*0Sstevel@tonic-gate 	int i;
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 	if (specsize == 1) {
399*0Sstevel@tonic-gate 		if (streq(member, "SIZEOF")) {
400*0Sstevel@tonic-gate 			return (SIZEOF);
401*0Sstevel@tonic-gate 		}
402*0Sstevel@tonic-gate 		if (streq(member, "OFFSETOK")) {
403*0Sstevel@tonic-gate 			return (OFFSETOK);
404*0Sstevel@tonic-gate 		}
405*0Sstevel@tonic-gate 		if (streq(member, "END")) {
406*0Sstevel@tonic-gate 			return (END);
407*0Sstevel@tonic-gate 		}
408*0Sstevel@tonic-gate 		for (i = 0; i < FMT_ENTRIES; i++)
409*0Sstevel@tonic-gate 			if (streq(member, adbgen_fmt_tbl[i].f_str))
410*0Sstevel@tonic-gate 				return (i);
411*0Sstevel@tonic-gate 		return (OFFSET);
412*0Sstevel@tonic-gate 	}
413*0Sstevel@tonic-gate 	if (specsize == 2) {
414*0Sstevel@tonic-gate 		if (member[0] == '*') {
415*0Sstevel@tonic-gate 			return (INDIRECT);
416*0Sstevel@tonic-gate 		}
417*0Sstevel@tonic-gate 		if (streq(member, "EXPR")) {
418*0Sstevel@tonic-gate 			return (EXPR);
419*0Sstevel@tonic-gate 		}
420*0Sstevel@tonic-gate 		return (PRINT);
421*0Sstevel@tonic-gate 	}
422*0Sstevel@tonic-gate 	fprintf(stderr, "Invalid specification, line %d\n", line_no);
423*0Sstevel@tonic-gate 	exit(1);
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate /*
427*0Sstevel@tonic-gate  * Generate the appropriate output for an input specification.
428*0Sstevel@tonic-gate  */
429*0Sstevel@tonic-gate void
generate(void)430*0Sstevel@tonic-gate generate(void)
431*0Sstevel@tonic-gate {
432*0Sstevel@tonic-gate 	char *cp;
433*0Sstevel@tonic-gate 	int type;
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	type = get_type();
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	switch (type) {
438*0Sstevel@tonic-gate 	case PTR_HEX:
439*0Sstevel@tonic-gate 	case LONG_DEC:
440*0Sstevel@tonic-gate 	case LONG_OCT:
441*0Sstevel@tonic-gate 	case ULONG_DEC:
442*0Sstevel@tonic-gate 	case ULONG_HEX:
443*0Sstevel@tonic-gate 	case ULONG_OCT:
444*0Sstevel@tonic-gate 		cp = start_printf();
445*0Sstevel@tonic-gate 		*cp++ = adbgen_fmt_tbl[type].f_char;
446*0Sstevel@tonic-gate 		emit_printf(cp);
447*0Sstevel@tonic-gate 		break;
448*0Sstevel@tonic-gate 	case PRINT:
449*0Sstevel@tonic-gate 		emit_print();
450*0Sstevel@tonic-gate 		break;
451*0Sstevel@tonic-gate 	case OFFSET:
452*0Sstevel@tonic-gate 		emit_offset();
453*0Sstevel@tonic-gate 		break;
454*0Sstevel@tonic-gate 	case INDIRECT:
455*0Sstevel@tonic-gate 		emit_indirect();
456*0Sstevel@tonic-gate 		break;
457*0Sstevel@tonic-gate 	case OFFSETOK:
458*0Sstevel@tonic-gate 		emit_offsetok();
459*0Sstevel@tonic-gate 		break;
460*0Sstevel@tonic-gate 	case SIZEOF:
461*0Sstevel@tonic-gate 		emit_sizeof();
462*0Sstevel@tonic-gate 		break;
463*0Sstevel@tonic-gate 	case EXPR:
464*0Sstevel@tonic-gate 		emit_expr();
465*0Sstevel@tonic-gate 		break;
466*0Sstevel@tonic-gate 	case END:
467*0Sstevel@tonic-gate 		emit_end();
468*0Sstevel@tonic-gate 		break;
469*0Sstevel@tonic-gate 	default:
470*0Sstevel@tonic-gate 		fprintf(stderr, "Internal error in generate\n");
471*0Sstevel@tonic-gate 		exit(1);
472*0Sstevel@tonic-gate 	}
473*0Sstevel@tonic-gate }
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate /*
476*0Sstevel@tonic-gate  * Emit calls to set the offset and print a member.
477*0Sstevel@tonic-gate  */
478*0Sstevel@tonic-gate void
emit_print(void)479*0Sstevel@tonic-gate emit_print(void)
480*0Sstevel@tonic-gate {
481*0Sstevel@tonic-gate 	char *cp;
482*0Sstevel@tonic-gate 	char fmt_request[STRLEN];
483*0Sstevel@tonic-gate 	int i;
484*0Sstevel@tonic-gate 	char number[STRLEN];
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	emit_offset();
487*0Sstevel@tonic-gate 	/*
488*0Sstevel@tonic-gate 	 * Emit call to "format" subroutine
489*0Sstevel@tonic-gate 	 */
490*0Sstevel@tonic-gate 	sprintf(arg[0], "\"%s\"", member);
491*0Sstevel@tonic-gate 	sprintf(arg[1], "sizeof ((struct %s *)0)->%s",
492*0Sstevel@tonic-gate 		struct_name, member);
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 	/*
495*0Sstevel@tonic-gate 	 * Split the format string into <number><format character string>
496*0Sstevel@tonic-gate 	 * This is for format strings that contain format specifier requests
497*0Sstevel@tonic-gate 	 * like {POINTER_HEX}, {LONG_DEC}, etc. which need to be substituted
498*0Sstevel@tonic-gate 	 * with a format character instead.
499*0Sstevel@tonic-gate 	 */
500*0Sstevel@tonic-gate 	for (cp = format, i = 0; *cp >= '0' && *cp <= '9' && *cp != '\0';
501*0Sstevel@tonic-gate 	    cp++, i++)
502*0Sstevel@tonic-gate 		number[i] = *cp;
503*0Sstevel@tonic-gate 	number[i] = '\0';
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 	for (i = 0; i < FMT_ENTRIES; i++) {
506*0Sstevel@tonic-gate 		(void) sprintf(fmt_request, "{%s}", adbgen_fmt_tbl[i].f_str);
507*0Sstevel@tonic-gate 		if (streq(cp, fmt_request)) {
508*0Sstevel@tonic-gate 			sprintf(arg[2], "\"%s%c\"",
509*0Sstevel@tonic-gate 				number, adbgen_fmt_tbl[i].f_char);
510*0Sstevel@tonic-gate 			break;
511*0Sstevel@tonic-gate 		}
512*0Sstevel@tonic-gate 	}
513*0Sstevel@tonic-gate 	if (i == FMT_ENTRIES)
514*0Sstevel@tonic-gate 		sprintf(arg[2], "\"%s\"", format);
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 	emit_call("format", 3);
517*0Sstevel@tonic-gate }
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate /*
520*0Sstevel@tonic-gate  * Emit calls to set the offset and print a member.
521*0Sstevel@tonic-gate  */
522*0Sstevel@tonic-gate void
emit_offset(void)523*0Sstevel@tonic-gate emit_offset(void)
524*0Sstevel@tonic-gate {
525*0Sstevel@tonic-gate 	/*
526*0Sstevel@tonic-gate 	 * Emit call to "offset" subroutine
527*0Sstevel@tonic-gate 	 */
528*0Sstevel@tonic-gate 	sprintf(arg[0], "(off_t) &(((struct %s *)0)->%s)",
529*0Sstevel@tonic-gate 		struct_name, member);
530*0Sstevel@tonic-gate 	emit_call("offset", 1);
531*0Sstevel@tonic-gate }
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate /*
534*0Sstevel@tonic-gate  * Emit call to indirect routine.
535*0Sstevel@tonic-gate  */
536*0Sstevel@tonic-gate void
emit_indirect(void)537*0Sstevel@tonic-gate emit_indirect(void)
538*0Sstevel@tonic-gate {
539*0Sstevel@tonic-gate 	sprintf(arg[0], "(off_t) &(((struct %s *)0)->%s)",
540*0Sstevel@tonic-gate 		struct_name, member+1);
541*0Sstevel@tonic-gate 	sprintf(arg[1], "sizeof ((struct %s *)0)->%s", struct_name, member+1);
542*0Sstevel@tonic-gate 	sprintf(arg[2], "\"%s\"", format);	/* adb register name */
543*0Sstevel@tonic-gate 	sprintf(arg[3], "\"%s\"", member);
544*0Sstevel@tonic-gate 	emit_call("indirect", 4);
545*0Sstevel@tonic-gate }
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate /*
548*0Sstevel@tonic-gate  * Emit call to "offsetok" routine.
549*0Sstevel@tonic-gate  */
550*0Sstevel@tonic-gate void
emit_offsetok(void)551*0Sstevel@tonic-gate emit_offsetok(void)
552*0Sstevel@tonic-gate {
553*0Sstevel@tonic-gate 	emit_call("offsetok", 0);
554*0Sstevel@tonic-gate }
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate /*
557*0Sstevel@tonic-gate  * Emit call to printf the sizeof the structure.
558*0Sstevel@tonic-gate  */
559*0Sstevel@tonic-gate void
emit_sizeof(void)560*0Sstevel@tonic-gate emit_sizeof(void)
561*0Sstevel@tonic-gate {
562*0Sstevel@tonic-gate 	sprintf(arg[0], "\"0t%%d\"");
563*0Sstevel@tonic-gate 	sprintf(arg[1], "sizeof (struct %s)", struct_name);
564*0Sstevel@tonic-gate 	emit_call("printf", 2);
565*0Sstevel@tonic-gate }
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate /*
568*0Sstevel@tonic-gate  * Emit call to printf an arbitrary C expression.
569*0Sstevel@tonic-gate  */
570*0Sstevel@tonic-gate void
emit_expr(void)571*0Sstevel@tonic-gate emit_expr(void)
572*0Sstevel@tonic-gate {
573*0Sstevel@tonic-gate 	sprintf(arg[0], "\"0t%%d\"");
574*0Sstevel@tonic-gate 	sprintf(arg[1], "(%s)", format);
575*0Sstevel@tonic-gate 	emit_call("printf", 2);
576*0Sstevel@tonic-gate }
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate /*
579*0Sstevel@tonic-gate  * Emit call to set offset to end of struct.
580*0Sstevel@tonic-gate  */
581*0Sstevel@tonic-gate void
emit_end(void)582*0Sstevel@tonic-gate emit_end(void)
583*0Sstevel@tonic-gate {
584*0Sstevel@tonic-gate 	sprintf(arg[0], "sizeof (struct %s)", struct_name);
585*0Sstevel@tonic-gate 	emit_call("offset", 1);
586*0Sstevel@tonic-gate }
587*0Sstevel@tonic-gate 
588*0Sstevel@tonic-gate /*
589*0Sstevel@tonic-gate  * Emit call to subroutine name with nargs arguments from arg array.
590*0Sstevel@tonic-gate  */
591*0Sstevel@tonic-gate void
emit_call(char * name,int nargs)592*0Sstevel@tonic-gate emit_call(char *name, int nargs)
593*0Sstevel@tonic-gate {
594*0Sstevel@tonic-gate 	int i;
595*0Sstevel@tonic-gate 
596*0Sstevel@tonic-gate 	printf("\t%s(", name);		/* name of subroutine */
597*0Sstevel@tonic-gate 	for (i = 0; i < nargs; i++) {
598*0Sstevel@tonic-gate 		if (i > 0) {
599*0Sstevel@tonic-gate 			printf(", ");	/* argument separator */
600*0Sstevel@tonic-gate 		}
601*0Sstevel@tonic-gate 		printf("%s", arg[i]);	/* argument */
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 	printf(");\n");			/* end of call */
604*0Sstevel@tonic-gate }
605