|
@@ -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)
|
|
|
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)
|
|
|
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(lines[i], "static"))
|
|
|
|
|
|
|
+ if (strstarts(line, "#include"))
|
|
|
|
|
+ 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? */
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ /* No idea... Say yes? */
|
|
|
|
|
+ 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)
|
|
|
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)
|
|
|
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)
|
|
|
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"
|
|
|
|
|
- "int somefunc(void) { return 0; }\n");
|
|
|
|
|
|
|
+ "extern int somefunc(void);\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)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- /* ... means elided code. If followed by spaced line, means
|
|
|
|
|
- * next part is supposed to be inside a function. */
|
|
|
|
|
|
|
+ /* ... means elided code. */
|
|
|
if (strcmp(lines[i], "...") == 0) {
|
|
if (strcmp(lines[i], "...") == 0) {
|
|
|
- if (!in_function
|
|
|
|
|
- && lines[i+1]
|
|
|
|
|
- && isblank(lines[i+1][0])) {
|
|
|
|
|
|
|
+ if (!in_function && !has_main
|
|
|
|
|
+ && looks_internal(lines + i + 1)) {
|
|
|
/* 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,
|
|
|
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,
|
|
|
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. */
|
|
|
|
|
- if (keep)
|
|
|
|
|
- unlink(mangle->fullname);
|
|
|
|
|
- talloc_free(mangle);
|
|
|
|
|
-
|
|
|
|
|
- mangle = mangle_example(m, i, prev, keep);
|
|
|
|
|
|
|
+ mangle = mangle_example(m, i, new, 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,
|
|
|
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;
|