/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Read in "high-level" adb script and emit C program.
* The input may have specifications within {} which
* we analyze and then emit C code to generate the
* ultimate adb acript.
* We are just a filter; no arguments are accepted.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Format specifier strings
* which are recognized by adbgen when surrounded by {}
*/
/*
* Types of specifications in {}.
*/
/*
* Special return code from nextchar.
*/
typedef struct adbgen_fmt {
char *f_str;
char f_char;
} adbgen_fmt_t;
/* This is a kludge so we emit pending */
/* printf's when we see a CPP line */
{FSTR_PTR},
};
void emit_end(void);
void emit_expr(void);
void emit_indirect(void);
void emit_offset(void);
void emit_offsetok(void);
void emit_print(void);
void emit_printf(char *cp);
void emit_sizeof(void);
void generate(void);
int get_type(void);
void read_spec(void);
char *start_printf(void);
int
{
char *cp;
int c;
int warn_flag = 0;
int is_lp64 = 0;
switch (c) {
case 'm':
is_lp64 = 0;
is_lp64 = 1;
else
break;
case 'w':
warn_flag++;
break;
case '?':
break;
}
}
if (is_lp64) {
} else {
}
/*
* Get structure name.
*/
cp = struct_name;
if (c == EOF) {
exit(1);
}
if (c == CPP)
continue;
*cp++ = (char)c;
}
*cp = '\0';
/*
* Basically, the generated program is just an ongoing printf
* with breaks for {} format specifications.
*/
printf("\n");
printf("#include <sys/inttypes.h>\n");
printf("\n\n");
printf("int do_fmt(char *acp);\n");
printf("void format(char *name, size_t size, char *fmt);\n");
printf("void indirect(off_t offset, size_t size, "
"char *base, char *member);\n");
printf("void offset(off_t off);\n");
printf("void offsetok(void);\n");
printf("\n\n");
printf("main(int argc, char *argv[])\n");
printf("{\n");
if (warn_flag) {
printf("\textern int warnings;\n\n\twarnings = 0;\n");
}
cp = start_printf();
switch (c) {
case '"':
*cp++ = '"';
break;
case '\n':
*cp++ = 'n';
break;
case '{':
read_spec();
generate();
cp = start_printf();
break;
case CPP:
/*
* Restart printf after cpp line.
*/
cp = start_printf();
break;
default:
*cp++ = c;
break;
}
cp = start_printf();
}
}
/* terminate program, checking for "error" mode */
printf("\n\tif (argc > 1 && strcmp(argv[1], \"-e\") == 0) {\n");
printf("\t\textern int warns;\n\n");
printf("\t\tif (warns)\n");
printf("\t\t\treturn (1);\n");
printf("\t}\n");
printf("\treturn (0);\n");
printf("}\n");
return (0);
}
int
{
int c;
c = getchar();
/*
* Lines beginning with '#' and blank lines are passed right through.
*/
while (newline) {
switch (c) {
case '#':
if (state)
do {
putchar(c);
c = getchar();
if (c == EOF)
return (c);
} while (c != '\n');
putchar(c);
line_no++;
return (CPP);
case '\n':
if (state)
putchar(c);
c = getchar();
line_no++;
break;
default:
newline = 0;
break;
}
}
if (c == '\n') {
newline++;
line_no++;
}
return (c);
}
/*
* Get started on printf of ongoing adb script.
*/
char *
start_printf(void)
{
char *cp;
*cp++ = '"';
return (cp);
}
/*
* Emit call to printf to print part of ongoing adb script.
*/
void
char *cp;
{
*cp++ = '"';
*cp = '\0';
state = 0; /* XXX */
}
/*
* Read {} specification.
* The first part (up to a comma) is put into "member".
* The second part, if present, is put into "format".
*/
void
read_spec(void)
{
char *cp;
int c;
int nesting;
specsize = 1;
nesting = 0;
switch (c) {
case EOF:
exit(1);
case '\n':
line_no);
exit(1);
case '#':
line_no);
exit(1);
case ',':
if (specsize == 2) {
exit(1);
}
specsize = 2;
*cp = '\0';
break;
case '{':
/*
* Allow up to one set of nested {}'s for adbgen
* requests of the form {member, {format string}}
*/
if (!nesting) {
nesting = 1;
*cp++ = c;
} else {
line_no);
exit(1);
}
break;
case '}':
*cp++ = c;
nesting = 0;
break;
default:
*cp++ = c;
break;
}
}
*cp = '\0';
specsize = 0;
}
}
/*
* Decide what type of input specification we have.
*/
int
get_type(void)
{
int i;
if (specsize == 1) {
return (SIZEOF);
}
return (OFFSETOK);
}
return (END);
}
for (i = 0; i < FMT_ENTRIES; i++)
return (i);
return (OFFSET);
}
if (specsize == 2) {
if (member[0] == '*') {
return (INDIRECT);
}
return (EXPR);
}
return (PRINT);
}
exit(1);
}
/*
* Generate the appropriate output for an input specification.
*/
void
generate(void)
{
char *cp;
int type;
switch (type) {
case PTR_HEX:
case LONG_DEC:
case LONG_OCT:
case ULONG_DEC:
case ULONG_HEX:
case ULONG_OCT:
cp = start_printf();
break;
case PRINT:
emit_print();
break;
case OFFSET:
emit_offset();
break;
case INDIRECT:
break;
case OFFSETOK:
break;
case SIZEOF:
emit_sizeof();
break;
case EXPR:
emit_expr();
break;
case END:
emit_end();
break;
default:
exit(1);
}
}
/*
* Emit calls to set the offset and print a member.
*/
void
emit_print(void)
{
char *cp;
int i;
emit_offset();
/*
* Emit call to "format" subroutine
*/
/*
* Split the format string into <number><format character string>
* This is for format strings that contain format specifier requests
* like {POINTER_HEX}, {LONG_DEC}, etc. which need to be substituted
* with a format character instead.
*/
cp++, i++)
number[i] = '\0';
for (i = 0; i < FMT_ENTRIES; i++) {
break;
}
}
if (i == FMT_ENTRIES)
}
/*
* Emit calls to set the offset and print a member.
*/
void
emit_offset(void)
{
/*
* Emit call to "offset" subroutine
*/
}
/*
* Emit call to indirect routine.
*/
void
emit_indirect(void)
{
}
/*
* Emit call to "offsetok" routine.
*/
void
emit_offsetok(void)
{
emit_call("offsetok", 0);
}
/*
* Emit call to printf the sizeof the structure.
*/
void
emit_sizeof(void)
{
}
/*
* Emit call to printf an arbitrary C expression.
*/
void
emit_expr(void)
{
}
/*
* Emit call to set offset to end of struct.
*/
void
emit_end(void)
{
}
/*
* Emit call to subroutine name with nargs arguments from arg array.
*/
void
{
int i;
for (i = 0; i < nargs; i++) {
if (i > 0) {
}
}
}