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