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