4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Read in "high-level" adb script and emit C program.
31 * The input may have specifications within {} which
32 * we analyze and then emit C code to generate the
33 * ultimate adb acript.
34 * We are just a filter; no arguments are accepted.
41 #define streq(s1, s2) (strcmp(s1, s2) == 0)
43 #define LINELEN 1024 /* max line length expected in input */
44 #define STRLEN 128 /* for shorter strings */
45 #define NARGS 5 /* number of emitted subroutine arguments */
48 * Format specifier strings
49 * which are recognized by adbgen when surrounded by {}
51 #define FSTR_PTR "POINTER"
52 #define FSTR_LONG_DEC "LONGDEC"
53 #define FSTR_LONG_OCT "LONGOCT"
54 #define FSTR_ULONG_DEC "ULONGDEC"
55 #define FSTR_ULONG_HEX "ULONGHEX"
56 #define FSTR_ULONG_OCT "ULONGOCT"
59 * Types of specifications in {}.
61 #define PTR_HEX 0 /* emit hex pointer format char */
62 #define LONG_DEC 1 /* emit decimal long format char */
63 #define LONG_OCT 2 /* emit octal unsigned long format char */
64 #define ULONG_DEC 3 /* emit decimal unsigned long format char */
65 #define ULONG_HEX 4 /* emit hexadecimal long format char */
66 #define ULONG_OCT 5 /* emit octal unsigned long format char */
68 #define FMT_ENTRIES 6 /* number of adbgen format specifier strings */
70 #define PRINT 6 /* print member name with format */
71 #define INDIRECT 7 /* fetch member value */
72 #define OFFSETOK 8 /* insist that the offset is ok */
73 #define SIZEOF 9 /* print sizeof struct */
74 #define END 10 /* get offset to end of struct */
75 #define OFFSET 11 /* just emit offset */
76 #define EXPR 12 /* arbitrary C expression */
79 * Special return code from nextchar.
81 #define CPP -2 /* cpp line, restart parsing */
83 typedef struct adbgen_fmt
{
88 char struct_name
[STRLEN
]; /* struct name */
89 char member
[STRLEN
]; /* member name */
90 char format
[STRLEN
]; /* adb format spec */
91 char arg
[NARGS
][STRLEN
]; /* arg list for called subroutine */
92 char *ptr_hex_fmt
; /* adb format character for pointer in hex */
93 char *long_dec_fmt
; /* adb format character for long in decimal */
94 char *ulong_dec_fmt
; /* adb format character for ulong in decimal */
95 char *ulong_hex_fmt
; /* adb format character for ulong in hex */
96 char *long_oct_fmt
; /* adb format character for long in octal */
97 char *ulong_oct_fmt
; /* adb format character for ulong in octal */
99 int line_no
= 1; /* input line number - for error messages */
100 int specsize
; /* size of {} specification - 1 or 2 parts */
101 int state
; /* XXX 1 = gathering a printf */
102 /* This is a kludge so we emit pending */
103 /* printf's when we see a CPP line */
105 adbgen_fmt_t adbgen_fmt_tbl
[FMT_ENTRIES
] = {
114 void emit_call(char *name
, int nargs
);
116 void emit_expr(void);
117 void emit_indirect(void);
118 void emit_offset(void);
119 void emit_offsetok(void);
120 void emit_print(void);
121 void emit_printf(char *cp
);
122 void emit_sizeof(void);
125 int nextchar(char *cp
);
126 void read_spec(void);
127 char *start_printf(void);
130 main(int argc
, char **argv
)
136 char *usage
= "adbgen1 [-w] [-m ilp32|lp64] < <macro file>\n";
138 while ((c
= getopt(argc
, argv
, "m:w")) != EOF
) {
141 if (streq(optarg
, "ilp32"))
143 else if (streq(optarg
, "lp64"))
146 fprintf(stderr
, usage
);
152 fprintf(stderr
, usage
);
157 adbgen_fmt_tbl
[PTR_HEX
].f_char
= 'J';
158 adbgen_fmt_tbl
[LONG_DEC
].f_char
= 'e';
159 adbgen_fmt_tbl
[LONG_OCT
].f_char
= 'g';
160 adbgen_fmt_tbl
[ULONG_DEC
].f_char
= 'E';
161 adbgen_fmt_tbl
[ULONG_HEX
].f_char
= 'J';
162 adbgen_fmt_tbl
[ULONG_OCT
].f_char
= 'G';
164 adbgen_fmt_tbl
[PTR_HEX
].f_char
= 'X';
165 adbgen_fmt_tbl
[LONG_DEC
].f_char
= 'D';
166 adbgen_fmt_tbl
[LONG_OCT
].f_char
= 'Q';
167 adbgen_fmt_tbl
[ULONG_DEC
].f_char
= 'U';
168 adbgen_fmt_tbl
[ULONG_HEX
].f_char
= 'X';
169 adbgen_fmt_tbl
[ULONG_OCT
].f_char
= 'O';
173 * Get structure name.
176 while ((c
= nextchar(NULL
)) != '\n') {
178 fprintf(stderr
, "Premature EOF\n");
187 * Basically, the generated program is just an ongoing printf
188 * with breaks for {} format specifications.
191 printf("#include <sys/types.h>\n");
192 printf("#include <sys/inttypes.h>\n");
194 printf("int do_fmt(char *acp);\n");
195 printf("void format(char *name, size_t size, char *fmt);\n");
196 printf("void indirect(off_t offset, size_t size, "
197 "char *base, char *member);\n");
198 printf("void offset(off_t off);\n");
199 printf("void offsetok(void);\n");
201 printf("main(int argc, char *argv[])\n");
204 printf("\textern int warnings;\n\n\twarnings = 0;\n");
207 while ((c
= nextchar(cp
)) != EOF
) {
210 *cp
++ = '\\'; /* escape ' in string */
214 *cp
++ = '\\'; /* escape newline in string */
225 * Restart printf after cpp line.
233 if (cp
- arg
[1] >= STRLEN
- 10) {
240 /* terminate program, checking for "error" mode */
241 printf("\n\tif (argc > 1 && strcmp(argv[1], \"-e\") == 0) {\n");
242 printf("\t\textern int warns;\n\n");
243 printf("\t\tif (warns)\n");
244 printf("\t\t\treturn (1);\n");
246 printf("\treturn (0);\n");
256 static int newline
= 1;
260 * Lines beginning with '#' and blank lines are passed right through.
296 * Get started on printf of ongoing adb script.
303 strcpy(arg
[0], "\"%s\"");
311 * Emit call to printf to print part of ongoing adb script.
319 emit_call("printf", 2);
324 * Read {} specification.
325 * The first part (up to a comma) is put into "member".
326 * The second part, if present, is put into "format".
338 while ((c
= nextchar(NULL
)) != '}' || (c
== '}' && nesting
)) {
341 fprintf(stderr
, "Unexpected EOF inside {}\n");
344 fprintf(stderr
, "Newline not allowed in {}, line %d\n",
348 fprintf(stderr
, "# not allowed in {}, line %d\n",
353 fprintf(stderr
, "Excessive commas in {}, ");
354 fprintf(stderr
, "line %d\n", line_no
);
363 * Allow up to one set of nested {}'s for adbgen
364 * requests of the form {member, {format string}}
370 fprintf(stderr
, "Too many {'s, line %d\n",
391 * Decide what type of input specification we have.
399 if (streq(member
, "SIZEOF")) {
402 if (streq(member
, "OFFSETOK")) {
405 if (streq(member
, "END")) {
408 for (i
= 0; i
< FMT_ENTRIES
; i
++)
409 if (streq(member
, adbgen_fmt_tbl
[i
].f_str
))
414 if (member
[0] == '*') {
417 if (streq(member
, "EXPR")) {
422 fprintf(stderr
, "Invalid specification, line %d\n", line_no
);
427 * Generate the appropriate output for an input specification.
445 *cp
++ = adbgen_fmt_tbl
[type
].f_char
;
470 fprintf(stderr
, "Internal error in generate\n");
476 * Emit calls to set the offset and print a member.
482 char fmt_request
[STRLEN
];
488 * Emit call to "format" subroutine
490 sprintf(arg
[0], "\"%s\"", member
);
491 sprintf(arg
[1], "sizeof ((struct %s *)0)->%s",
492 struct_name
, member
);
495 * Split the format string into <number><format character string>
496 * This is for format strings that contain format specifier requests
497 * like {POINTER_HEX}, {LONG_DEC}, etc. which need to be substituted
498 * with a format character instead.
500 for (cp
= format
, i
= 0; *cp
>= '0' && *cp
<= '9' && *cp
!= '\0';
505 for (i
= 0; i
< FMT_ENTRIES
; i
++) {
506 (void) sprintf(fmt_request
, "{%s}", adbgen_fmt_tbl
[i
].f_str
);
507 if (streq(cp
, fmt_request
)) {
508 sprintf(arg
[2], "\"%s%c\"",
509 number
, adbgen_fmt_tbl
[i
].f_char
);
513 if (i
== FMT_ENTRIES
)
514 sprintf(arg
[2], "\"%s\"", format
);
516 emit_call("format", 3);
520 * Emit calls to set the offset and print a member.
526 * Emit call to "offset" subroutine
528 sprintf(arg
[0], "(off_t) &(((struct %s *)0)->%s)",
529 struct_name
, member
);
530 emit_call("offset", 1);
534 * Emit call to indirect routine.
539 sprintf(arg
[0], "(off_t) &(((struct %s *)0)->%s)",
540 struct_name
, member
+1);
541 sprintf(arg
[1], "sizeof ((struct %s *)0)->%s", struct_name
, member
+1);
542 sprintf(arg
[2], "\"%s\"", format
); /* adb register name */
543 sprintf(arg
[3], "\"%s\"", member
);
544 emit_call("indirect", 4);
548 * Emit call to "offsetok" routine.
553 emit_call("offsetok", 0);
557 * Emit call to printf the sizeof the structure.
562 sprintf(arg
[0], "\"0t%%d\"");
563 sprintf(arg
[1], "sizeof (struct %s)", struct_name
);
564 emit_call("printf", 2);
568 * Emit call to printf an arbitrary C expression.
573 sprintf(arg
[0], "\"0t%%d\"");
574 sprintf(arg
[1], "(%s)", format
);
575 emit_call("printf", 2);
579 * Emit call to set offset to end of struct.
584 sprintf(arg
[0], "sizeof (struct %s)", struct_name
);
585 emit_call("offset", 1);
589 * Emit call to subroutine name with nargs arguments from arg array.
592 emit_call(char *name
, int nargs
)
596 printf("\t%s(", name
); /* name of subroutine */
597 for (i
= 0; i
< nargs
; i
++) {
599 printf(", "); /* argument separator */
601 printf("%s", arg
[i
]); /* argument */
603 printf(");\n"); /* end of call */