Commit ab4a6fd9 authored by Rusty Russell's avatar Rusty Russell

ccanlint: yet more modifications to example extraction and compile.

Now (with fixes) every ccanlint example compiles!
parent 0f66da71
...@@ -37,6 +37,10 @@ static char *add_dep(const struct manifest *m, char *list, const char *mod) ...@@ -37,6 +37,10 @@ static char *add_dep(const struct manifest *m, char *list, const char *mod)
char **deps, *obj; char **deps, *obj;
unsigned int i; unsigned int i;
/* Not ourselves. */
if (streq(m->basename, mod))
return list;
/* Not if there's no object file for that module */ /* Not if there's no object file for that module */
if (!expect_obj_file(talloc_asprintf(list, "%s/ccan/%s", ccan_dir,mod))) if (!expect_obj_file(talloc_asprintf(list, "%s/ccan/%s", ccan_dir,mod)))
return list; return list;
...@@ -87,9 +91,6 @@ static char *obj_list(const struct manifest *m, struct ccan_file *f) ...@@ -87,9 +91,6 @@ static char *obj_list(const struct manifest *m, struct ccan_file *f)
mod = *lines + preflen + strlen("#include <ccan/"); mod = *lines + preflen + strlen("#include <ccan/");
modlen = strcspn(mod, "/"); modlen = strcspn(mod, "/");
mod = talloc_strndup(f, mod, modlen); mod = talloc_strndup(f, mod, modlen);
/* Not ourselves. */
if (streq(m->basename, mod))
continue;
list = add_dep(m, list, mod); list = add_dep(m, list, mod);
} }
} }
...@@ -179,35 +180,53 @@ static void strip_leading_whitespace(char **lines) ...@@ -179,35 +180,53 @@ static void strip_leading_whitespace(char **lines)
static bool looks_internal(char **lines) static bool looks_internal(char **lines)
{ {
unsigned int i; unsigned int i;
bool last_ended = true; /* Did last line finish a statement? */
for (i = 0; lines[i]; i++) { for (i = 0; lines[i]; i++) {
unsigned len = strspn(lines[i], IDENT_CHARS); /* Skip leading whitespace. */
const char *line = lines[i] + strspn(lines[i], " \t");
unsigned len = strspn(line, IDENT_CHARS);
if (!line[0] || isblank(line[0]) || strstarts(line, "//"))
continue;
/* The winners. */ /* The winners. */
if (strstarts(lines[i], "if") && len == 2) if (strstarts(line, "if") && len == 2)
return true; return true;
if (strstarts(lines[i], "for") && len == 3) if (strstarts(line, "for") && len == 3)
return true; return true;
if (strstarts(lines[i], "while") && len == 5) if (strstarts(line, "while") && len == 5)
return true; return true;
if (strstarts(lines[i], "do") && len == 2) if (strstarts(line, "do") && len == 2)
return true; return true;
/* The losers. */ /* The losers. */
if (strchr(lines[i], '(')) { if (strstarts(line, "#include"))
if (strstarts(lines[i], "static")) return false;
if (last_ended && strchr(line, '(')) {
if (strstarts(line, "static"))
return false; return false;
if (strends(lines[i], ")")) if (strends(line, ")"))
return false; return false;
} }
/* Single identifier then operator == inside function. */
if (last_ended && len
&& ispunct(line[len+strspn(line+len, " ")]))
return true;
last_ended = (strends(line, "}")
|| strends(line, ";")
|| streq(line, "..."));
} }
/* No idea... Say no? */ /* No idea... Say yes? */
return false; return true;
} }
/* Examples will often build on prior ones. Try combining them. */ /* Examples will often build on prior ones. Try combining them. */
static char **combine(char **lines, char **prev) static char **combine(const void *ctx, char **lines, char **prev)
{ {
unsigned int i, lines_total, prev_total, count; unsigned int i, lines_total, prev_total, count;
char **ret; char **ret;
...@@ -215,8 +234,6 @@ static char **combine(char **lines, char **prev) ...@@ -215,8 +234,6 @@ static char **combine(char **lines, char **prev)
if (!prev) if (!prev)
return NULL; return NULL;
strip_leading_whitespace(lines);
/* If it looks internal, put prev at start. */ /* If it looks internal, put prev at start. */
if (looks_internal(lines)) { if (looks_internal(lines)) {
count = 0; count = 0;
...@@ -239,7 +256,7 @@ static char **combine(char **lines, char **prev) ...@@ -239,7 +256,7 @@ static char **combine(char **lines, char **prev)
for (i = 0; prev[i]; i++); for (i = 0; prev[i]; i++);
prev_total = i; prev_total = i;
ret = talloc_array(lines, char *, lines_total + prev_total + 1); ret = talloc_array(ctx, char *, lines_total + prev_total + 1);
memcpy(ret, lines, count * sizeof(ret[0])); memcpy(ret, lines, count * sizeof(ret[0]));
memcpy(ret + count, prev, prev_total * sizeof(ret[0])); memcpy(ret + count, prev, prev_total * sizeof(ret[0]));
memcpy(ret + count + prev_total, lines + count, memcpy(ret + count + prev_total, lines + count,
...@@ -272,10 +289,11 @@ static char *mangle(struct manifest *m, char **lines) ...@@ -272,10 +289,11 @@ static char *mangle(struct manifest *m, char **lines)
m->basename, m->basename); m->basename, m->basename);
ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\n" ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\n"
"int somefunc(void);\n" "extern int somefunc(void);\n"
"int somefunc(void) { return 0; }\n"); "int somefunc(void) { return 0; }\n"
"extern char somestring[];\n"
"char somestring[] = \"hello world\";\n");
strip_leading_whitespace(lines);
if (looks_internal(lines)) { if (looks_internal(lines)) {
/* Wrap it all in main(). */ /* Wrap it all in main(). */
ret = start_main(ret); ret = start_main(ret);
...@@ -306,12 +324,10 @@ static char *mangle(struct manifest *m, char **lines) ...@@ -306,12 +324,10 @@ static char *mangle(struct manifest *m, char **lines)
} }
} }
} }
/* ... means elided code. If followed by spaced line, means /* ... means elided code. */
* next part is supposed to be inside a function. */
if (strcmp(lines[i], "...") == 0) { if (strcmp(lines[i], "...") == 0) {
if (!in_function if (!in_function && !has_main
&& lines[i+1] && looks_internal(lines + i + 1)) {
&& isblank(lines[i+1][0])) {
/* This implies we start a function here. */ /* This implies we start a function here. */
ret = start_main(ret); ret = start_main(ret);
has_main = true; has_main = true;
...@@ -394,6 +410,8 @@ static void *build_examples(struct manifest *m, bool keep, ...@@ -394,6 +410,8 @@ static void *build_examples(struct manifest *m, bool keep,
char *ret; char *ret;
examples_compile.total_score++; examples_compile.total_score++;
/* Simplify our dumb parsing. */
strip_leading_whitespace(get_ccan_file_lines(i));
ret = compile(score, m, i, keep); ret = compile(score, m, i, keep);
if (!ret) { if (!ret) {
prev = get_ccan_file_lines(i); prev = get_ccan_file_lines(i);
...@@ -401,33 +419,30 @@ static void *build_examples(struct manifest *m, bool keep, ...@@ -401,33 +419,30 @@ static void *build_examples(struct manifest *m, bool keep,
continue; continue;
} }
talloc_free(ret);
mangle = mangle_example(m, i, get_ccan_file_lines(i), keep);
ret = compile(score, m, mangle, keep);
if (!ret) {
prev = get_ccan_file_lines(i);
score->score++;
continue;
}
/* Try combining with previous (successful) example... */ /* Try combining with previous (successful) example... */
if (prev) { if (prev) {
prev = combine(get_ccan_file_lines(i), prev); char **new = combine(i, get_ccan_file_lines(i), prev);
talloc_free(ret); talloc_free(ret);
/* We're going to replace this failure. */ mangle = mangle_example(m, i, new, keep);
if (keep)
unlink(mangle->fullname);
talloc_free(mangle);
mangle = mangle_example(m, i, prev, keep);
ret = compile(score, m, mangle, keep); ret = compile(score, m, mangle, keep);
if (!ret) { if (!ret) {
prev = new;
score->score++; score->score++;
continue; continue;
} }
} }
/* Try standalone. */
talloc_free(ret);
mangle = mangle_example(m, i, get_ccan_file_lines(i), keep);
ret = compile(score, m, mangle, keep);
if (!ret) {
prev = get_ccan_file_lines(i);
score->score++;
continue;
}
if (!score->errors) if (!score->errors)
score->errors = ret; score->errors = ret;
else { else {
...@@ -436,7 +451,6 @@ static void *build_examples(struct manifest *m, bool keep, ...@@ -436,7 +451,6 @@ static void *build_examples(struct manifest *m, bool keep,
talloc_free(ret); talloc_free(ret);
} }
/* This didn't work, so not a candidate for combining. */ /* This didn't work, so not a candidate for combining. */
talloc_free(prev);
prev = NULL; prev = NULL;
} }
return score; return score;
......
...@@ -24,12 +24,16 @@ static char *add_example(struct manifest *m, struct ccan_file *source, ...@@ -24,12 +24,16 @@ static char *add_example(struct manifest *m, struct ccan_file *source,
int fd; int fd;
struct ccan_file *f; struct ccan_file *f;
name = maybe_temp_file(m, ".c", keep, name = talloc_asprintf(m, "%s/example-%s-%s.c",
talloc_asprintf(m, "%s/example-%s-%s.c", talloc_dirname(m,
talloc_dirname(m, source->fullname),
source->fullname), source->name,
source->name, example->function);
example->function)); /* example->function == 'struct foo' */
while (strchr(name, ' '))
*strchr(name, ' ') = '_';
name = maybe_temp_file(m, ".c", keep, name);
f = new_ccan_file(m, talloc_dirname(m, name), talloc_basename(m, name)); f = new_ccan_file(m, talloc_dirname(m, name), talloc_basename(m, name));
talloc_steal(f, name); talloc_steal(f, name);
list_add_tail(&m->examples, &f->list); list_add_tail(&m->examples, &f->list);
......
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