Commit f7315b84 authored by Rusty Russell's avatar Rusty Russell

Avoid hacky recompilation of files to namespacize, use hacky parser

instead!
parent 2040a0c4
...@@ -13,7 +13,10 @@ ...@@ -13,7 +13,10 @@
#include "talloc/talloc.h" #include "talloc/talloc.h"
#define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I. -Iccan_tools/libtap/src/" #define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I. -Iccan_tools/libtap/src/"
#define CFLAGS_HDR "-Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Werror -I."
#define IDENT_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz" \
"01234567889_"
static bool verbose = false; static bool verbose = false;
static int indent = 0; static int indent = 0;
...@@ -166,20 +169,6 @@ lines_from_cmd(const void *ctx, char *format, ...) ...@@ -166,20 +169,6 @@ lines_from_cmd(const void *ctx, char *format, ...)
return split(ctx, buffer, "\n", NULL); return split(ctx, buffer, "\n", NULL);
} }
static char *build_obj(const char *cfile)
{
char *cmd;
char *ofile = talloc_strdup(cfile, cfile);
ofile[strlen(ofile)-1] = 'c';
cmd = talloc_asprintf(ofile, "gcc " CFLAGS " -o %s -c %s",
ofile, cfile);
if (system(cmd) != 0)
errx(1, "Failed to compile %s", cfile);
return ofile;
}
struct replace struct replace
{ {
struct replace *next; struct replace *next;
...@@ -200,11 +189,12 @@ static void __attribute__((noreturn)) usage(void) ...@@ -200,11 +189,12 @@ static void __attribute__((noreturn)) usage(void)
static void add_replace(struct replace **repl, const char *str) static void add_replace(struct replace **repl, const char *str)
{ {
struct replace *new; struct replace *new, *i;
/* Don't replace things already CCAN-ized (eg. idempotent wrappers) */ /* Avoid duplicates. */
if (strstarts(str, "CCAN_") || strstarts(str, "ccan_")) for (i = *repl; i; i = i->next)
return; if (streq(i->string, str))
return;
new = talloc(*repl, struct replace); new = talloc(*repl, struct replace);
new->next = *repl; new->next = *repl;
...@@ -212,6 +202,17 @@ static void add_replace(struct replace **repl, const char *str) ...@@ -212,6 +202,17 @@ static void add_replace(struct replace **repl, const char *str)
*repl = new; *repl = new;
} }
static void add_replace_tok(struct replace **repl, const char *s)
{
struct replace *new;
unsigned int len = strspn(s, IDENT_CHARS);
new = talloc(*repl, struct replace);
new->next = *repl;
new->string = talloc_strndup(new, s, len);
*repl = new;
}
static char *basename(const void *ctx, const char *dir) static char *basename(const void *ctx, const char *dir)
{ {
char *p = strrchr(dir, '/'); char *p = strrchr(dir, '/');
...@@ -221,20 +222,11 @@ static char *basename(const void *ctx, const char *dir) ...@@ -221,20 +222,11 @@ static char *basename(const void *ctx, const char *dir)
return talloc_strdup(ctx, p+1); return talloc_strdup(ctx, p+1);
} }
/* FIXME: Only does main header, should chase local includes. */ static void look_for_macros(char *contents, struct replace **repl)
static void analyze_headers(const char *dir, struct replace **repl)
{ {
char *hdr, *contents, *p; char *p;
enum { LINESTART, HASH, DEFINE, NONE } state = LINESTART; enum { LINESTART, HASH, DEFINE, NONE } state = LINESTART;
/* Get hold of header, assume that's it. */
hdr = talloc_asprintf(dir, "%s/%s.h", dir, basename(dir, dir));
contents = grab_file(dir, hdr);
if (!contents)
err(1, "Reading %s", hdr);
verbose("Looking in %s\n", hdr);
verbose_indent();
/* Look for lines of form #define X */ /* Look for lines of form #define X */
for (p = contents; *p; p++) { for (p = contents; *p; p++) {
if (*p == '\n') if (*p == '\n')
...@@ -248,79 +240,160 @@ static void analyze_headers(const char *dir, struct replace **repl) ...@@ -248,79 +240,160 @@ static void analyze_headers(const char *dir, struct replace **repl)
} else if (state == DEFINE) { } else if (state == DEFINE) {
unsigned int len; unsigned int len;
len = strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" len = strspn(p, IDENT_CHARS);
"abcdefghijklmnopqrstuvwxyz"
"01234567889_");
if (len) { if (len) {
char *s; char *s;
s = talloc_strndup(contents, p, len); s = talloc_strndup(contents, p, len);
verbose("Found %s\n", s); /* Don't wrap idempotent wrappers */
add_replace(repl, s); if (!strstarts(s, "CCAN_")) {
verbose("Found %s\n", s);
add_replace(repl, s);
}
} }
state = NONE; state = NONE;
} else } else
state = NONE; state = NONE;
} }
} }
verbose_unindent();
} }
static void add_extern_symbols(const char *ofile, struct replace **repl) /* Blank out preprocessor lines, and eliminate \ */
static void preprocess(char *p)
{ {
/* Should actually read the elf: this is a hack. */ char *s;
char **line;
line = lines_from_cmd(ofile, "nm --defined-only --extern %s", ofile); /* We assume backslashes are only used for macros. */
while ((s = strstr(p, "\\\n")) != NULL)
s[0] = s[1] = ' ';
/* nm output is of form [hexaddr] [char] [name]\n */ /* Now eliminate # lines. */
for (; *line; line++) { if (p[0] == '#') {
unsigned int cols; unsigned int i;
char **names = split(ofile, *line, " \t", &cols); for (i = 0; p[i] != '\n'; i++)
if (cols != 3) p[i] = ' ';
errx(1, "Unexpected nm line '%s' (%i cols)", *line, cols); }
while ((s = strstr(p, "\n#")) != NULL) {
unsigned int i;
for (i = 1; s[i] != '\n'; i++)
s[i] = ' ';
}
}
verbose("Found %s\n", names[2]); static char *get_statement(const void *ctx, char **p)
add_replace(repl, names[2]); {
unsigned brackets = 0;
bool seen_brackets = false;
char *answer = talloc_strdup(ctx, "");
for (;;) {
if ((*p)[0] == '/' && (*p)[1] == '/')
*p += strcspn(*p, "\n");
else if ((*p)[0] == '/' && (*p)[1] == '*')
*p = strstr(*p, "*/") + 1;
else {
char c = **p;
if (c == ';' && !brackets) {
(*p)++;
return answer;
}
/* Compress whitespace into a single ' ' */
if (isspace(c)) {
c = ' ';
while (isspace((*p)[1]))
(*p)++;
} else if (c == '{' || c == '(' || c == '[') {
if (c == '(')
seen_brackets = true;
brackets++;
} else if (c == '}' || c == ')' || c == ']')
brackets--;
if (answer[0] != '\0' || c != ' ') {
answer = talloc_realloc(NULL, answer, char,
strlen(answer) + 2);
answer[strlen(answer)+1] = '\0';
answer[strlen(answer)] = c;
}
if (c == '}' && seen_brackets && brackets == 0) {
(*p)++;
return answer;
}
}
(*p)++;
if (**p == '\0')
return NULL;
} }
} }
static void get_header_symbols(const char *dir, struct replace **repl) /* This hack should handle well-formatted code. */
static void look_for_definitions(char *contents, struct replace **repl)
{ {
char *cmd; char *stmt, *p = contents;
char *hfile = talloc_asprintf(dir, "%s/%s.h", dir, basename(dir, dir));
char *ofile = talloc_asprintf(dir, "%s.o", hfile);
/* Horrible hack to get static inlines. */ preprocess(contents);
cmd = talloc_asprintf(dir, "gcc " CFLAGS_HDR
" -Dstatic= -include %s -o %s -c -x c /dev/null",
hfile, ofile);
if (system(cmd) != 0)
errx(1, "Failed to compile %s", hfile);
add_extern_symbols(ofile, repl); while ((stmt = get_statement(contents, &p)) != NULL) {
} int i, len;
/* FIXME: Better to analyse headers in more depth, rather than recompile. */ /* Definition of struct/union? */
static void get_exposed_symbols(const char *dir, struct replace **repl) if ((strncmp(stmt, "struct", 5) == 0
{ || strncmp(stmt, "union", 5) == 0)
char **files; && strchr(stmt, '{') && stmt[7] != '{')
unsigned int i; add_replace_tok(repl, stmt+7);
files = get_dir(dir); /* Definition of var or typedef? */
for (i = 0; files[i]; i++) { for (i = strlen(stmt)-1; i >= 0; i--)
char *ofile; if (strspn(stmt+i, IDENT_CHARS) == 0)
if (!strends(files[i], ".c") || strends(files[i], "/_info.c")) break;
if (i != strlen(stmt)-1) {
add_replace_tok(repl, stmt+i+1);
continue; continue;
}
/* This produces file.c -> file.o */ /* function or array declaration? */
ofile = build_obj(files[i]); len = strspn(stmt, IDENT_CHARS "* ");
verbose("Looking in %s\n", ofile); if (len > 0 && (stmt[len] == '(' || stmt[len] == '[')) {
verbose_indent(); if (strspn(stmt + len + 1, IDENT_CHARS) != 0) {
add_extern_symbols(ofile, repl); for (i = len-1; i >= 0; i--)
unlink(ofile); if (strspn(stmt+i, IDENT_CHARS) == 0)
verbose_unindent(); break;
if (i != len-1) {
add_replace_tok(repl, stmt+i+1);
continue;
}
} else {
/* Pointer to function? */
len++;
len += strspn(stmt + len, " *");
i = strspn(stmt + len, IDENT_CHARS);
if (i > 0 && stmt[len + i] == ')')
add_replace_tok(repl, stmt+len);
}
}
} }
get_header_symbols(dir, repl); }
/* FIXME: Only does main header, should chase local includes. */
static void analyze_headers(const char *dir, struct replace **repl)
{
char *hdr, *contents;
/* Get hold of header, assume that's it. */
hdr = talloc_asprintf(dir, "%s/%s.h", dir, basename(dir, dir));
contents = grab_file(dir, hdr);
if (!contents)
err(1, "Reading %s", hdr);
verbose("Looking in %s for macros\n", hdr);
verbose_indent();
look_for_macros(contents, repl);
verbose_unindent();
verbose("Looking in %s for symbols\n", hdr);
verbose_indent();
look_for_definitions(contents, repl);
verbose_unindent();
} }
static void write_replacement_file(const char *dir, struct replace **repl) static void write_replacement_file(const char *dir, struct replace **repl)
...@@ -472,7 +545,6 @@ static void convert_dir(const char *dir) ...@@ -472,7 +545,6 @@ static void convert_dir(const char *dir)
name[strlen(name)-1] = '\0'; name[strlen(name)-1] = '\0';
analyze_headers(name, &replace); analyze_headers(name, &replace);
get_exposed_symbols(name, &replace);
write_replacement_file(name, &replace); write_replacement_file(name, &replace);
setup_adjust_files(name, replace, &adj); setup_adjust_files(name, replace, &adj);
rename_files(adj); rename_files(adj);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment