From 3f374d8d8b60de9749f472b7cc60901258ecfbc4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 4 May 2016 16:03:04 +0930 Subject: [PATCH] check-bolt: handle references to early-drafts too. Particularly for the onchain.md draft. Signed-off-by: Rusty Russell --- Makefile | 2 +- check-bolt.c | 209 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index e8d531bf4..1bcf91dfc 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ PROTOCC:=protoc-c CCANDIR := ccan # Where we keep the BOLT RFCs -BOLTDIR := ../lightning-rfc/bolts/ +BOLTDIR := ../lightning-rfc/ # Bitcoin uses DER for signatures (Add BIP68 & HAS_CSV if it's supported) BITCOIN_FEATURES := \ diff --git a/check-bolt.c b/check-bolt.c index 684cc4256..1d11d3ef5 100644 --- a/check-bolt.c +++ b/check-bolt.c @@ -12,6 +12,11 @@ static bool verbose = false; +struct bolt_file { + const char *prefix; + const char *contents; +}; + /* Turn any whitespace into a single space. */ static char *canonicalize(char *str) { @@ -36,71 +41,91 @@ static char *canonicalize(char *str) return str; } -static char **get_bolt_files(const char *dir) +static void get_files(const char *dir, const char *subdir, + struct bolt_file **files) { + char *path = path_join(NULL, dir, subdir); + DIR *d = opendir(path); + size_t n = tal_count(*files); struct dirent *e; - char **bolts = tal_arr(NULL, char *, 0); - DIR *d = opendir(dir); + if (!d) - err(1, "Opening BOLT dir %s", dir); + err(1, "Opening BOLT dir %s", path); while ((e = readdir(d)) != NULL) { - char *endp; - unsigned long l; - - /* Must start with the bold number. */ - l = strtoul(e->d_name, &endp, 10); - if (endp == e->d_name) - continue; + int preflen; /* Must end in .md */ if (!strends(e->d_name, ".md")) continue; - if (l >= tal_count(bolts)) - tal_resizez(&bolts, l+1); + /* Prefix is anything up to - */ + preflen = strspn(e->d_name, + "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (!preflen) + continue; + if (preflen + strlen(".md") != strlen(e->d_name) + && e->d_name[preflen] != '-') + continue; if (verbose) - printf("Found bolt %s: #%lu\n", e->d_name, l); + printf("Found bolt %.*s\n", preflen, e->d_name); - bolts[l] = canonicalize(grab_file(NULL, - path_join(NULL, dir, - e->d_name))); + tal_resize(files, n+1); + (*files)[n].prefix = tal_strndup(*files, + e->d_name, preflen); + (*files)[n].contents + = canonicalize(grab_file(*files, + path_join(path, path, + e->d_name))); + n++; } +} + +static struct bolt_file *get_bolt_files(const char *dir) +{ + struct bolt_file *bolts = tal_arr(NULL, struct bolt_file, 0); + + get_files(dir, "bolts", &bolts); + get_files(dir, "early-drafts", &bolts); return bolts; } -static char *find_bolt_ref(char *p, size_t *len, size_t *bolt) +static char *find_bolt_ref(char **p, size_t *len) { for (;;) { - char *end; + char *bolt, *end; + size_t preflen; /* BOLT #X: */ - p = strstr(p, "BOLT"); - if (!p) + *p = strstr(*p, "BOLT"); + if (!*p) return NULL; - p += 4; - while (cisspace(*p)) - p++; - if (*p != '#') - continue; - p++; - *bolt = strtoul(p, &end, 10); - if (!*bolt || p == end) + *p += 4; + while (cisspace(**p)) + (*p)++; + if (**p != '#') continue; - p = end; - while (cisspace(*p)) - p++; - if (*p != ':') + (*p)++; + + preflen = strcspn(*p, " :"); + bolt = tal_strndup(NULL, *p, preflen); + + (*p) += preflen; + while (cisspace(**p)) + (*p)++; + if (**p != ':') continue; - p++; + (*p)++; - end = strstr(p, "*/"); + end = strstr(*p, "*/"); if (!end) - *len = strlen(p); + *len = strlen(*p); else - *len = end - p; - return p; + *len = end - *p; + return bolt; } } @@ -108,7 +133,7 @@ static char *code_to_regex(const char *code, size_t len, bool escape) { char *pattern = tal_arr(NULL, char, len*2 + 1), *p; size_t i; - bool after_nl = false; + bool after_nl = true; /* We swallow '*' if first in line: block comments */ p = pattern; @@ -153,46 +178,81 @@ static char *code_to_regex(const char *code, size_t len, bool escape) return canonicalize(pattern); } -static void fail(const char *filename, const char *raw, const char *pos, - size_t len, const char *bolt) +/* Moves *pos to start of line. */ +static unsigned linenum(const char *raw, const char **pos) { unsigned line = 0; /* Out-by-one below */ - const char *l = raw; + const char *l = raw, *point = *pos; - while (l < pos) { + while (l < point) { + *pos = l; l = strchr(l, '\n'); line++; if (!l) - l = pos + strlen(pos); - else - l++; + break; + l++; } + return line; +} - if (bolt) { - char *try; - - fprintf(stderr, "%s:%u:%.*s\n", filename, line, - (int)(l - pos), pos); - /* Try to find longest match, as a hint. */ - try = code_to_regex(pos, len, false); - while (strlen(try)) { - const char *p = strstr(bolt, try); - if (p) { - fprintf(stderr, "Closest match: %s...[%.20s]\n", - try, p + strlen(try)); - break; - } - try[strlen(try)-1] = '\0'; +static void fail_mismatch(const char *filename, + const char *raw, const char *pos, + size_t len, struct bolt_file *bolt) +{ + unsigned line = linenum(raw, &pos); + char *try; + + fprintf(stderr, "%s:%u:mismatch:%.*s\n", + filename, line, (int)strcspn(pos, "\n"), pos); + /* Try to find longest match, as a hint. */ + try = code_to_regex(pos + strcspn(pos, "\n"), len, false); + while (strlen(try)) { + const char *p = strstr(bolt->contents, try); + if (p) { + fprintf(stderr, "Closest match: %s...[%.20s]\n", + try, p + strlen(try)); + break; } - } else { - fprintf(stderr, "%s:%u:Unknown bolt\n", filename, line); - } + try[strlen(try)-1] = '\0'; + } + exit(1); +} + +static void fail_nobolt(const char *filename, + const char *raw, const char *pos, + const char *bolt_prefix) +{ + unsigned line = linenum(raw, &pos); + + fprintf(stderr, "%s:%u:unknown bolt %s\n", + filename, line, bolt_prefix); exit(1); } +static struct bolt_file *find_bolt(const char *bolt_prefix, + struct bolt_file *bolts) +{ + size_t i, n = tal_count(bolts); + size_t boltnum; + + for (i = 0; i < n; i++) + if (streq(bolts[i].prefix, bolt_prefix)) + return bolts+i; + + /* Now search for numerical match. */ + boltnum = atoi(bolt_prefix); + if (boltnum) { + for (i = 0; i < n; i++) + if (atoi(bolts[i].prefix) == boltnum) + return bolts+i; + } + + return NULL; +} + int main(int argc, char *argv[]) { - char **bolts; + struct bolt_file *bolts; int i; err_set_progname(argv[0]); @@ -211,8 +271,8 @@ int main(int argc, char *argv[]) bolts = get_bolt_files(argv[1]); for (i = 2; i < argc; i++) { - char *f = grab_file(NULL, argv[i]), *p; - size_t len, bolt; + char *f = grab_file(NULL, argv[i]), *p, *bolt; + size_t len; if (!f) err(1, "Loading %s", argv[i]); @@ -220,16 +280,17 @@ int main(int argc, char *argv[]) printf("Checking %s...\n", argv[i]); p = f; - while ((p = find_bolt_ref(p, &len, &bolt)) != NULL) { + while ((bolt = find_bolt_ref(&p, &len)) != NULL) { char *pattern = code_to_regex(p, len, true); - if (bolt >= tal_count(bolts) || !bolts[bolt]) - fail(argv[i], f, p, len, NULL); - if (!tal_strreg(f, bolts[bolt], pattern, NULL)) - fail(argv[i], f, p, len, bolts[bolt]); + struct bolt_file *b = find_bolt(bolt, bolts); + if (!b) + fail_nobolt(argv[i], f, p, bolt); + if (!tal_strreg(f, b->contents, pattern, NULL)) + fail_mismatch(argv[i], f, p, len, b); if (verbose) - printf(" Found %.10s... in %zu\n", - p, bolt); + printf(" Found %.10s... in %s\n", + p, b->prefix); p += len; } tal_free(f);