/* Simplified tokenizer: comments and preproc directives removed, identifiers are a token, others are single char tokens. */ static struct token *tokenize(const void *ctx, const char *code) { unsigned int i, len, tok_start = -1; bool start_of_line = true; struct token *toks = tal_arr(ctx, struct token, 0); for (i = 0; code[i]; i += len) { if (code[i] == '#' && start_of_line) { /* Preprocessor line. */ len = strcspn(code+i, "\n"); } else if (code[i] == '/' && code[i+1] == '/') { /* One line comment. */ len = strcspn(code+i, "\n"); if (tok_start != -1U) { add_token(&toks, code+tok_start, i - tok_start); tok_start = -1U; } } else if (code[i] == '/' && code[i+1] == '*') { /* Multi-line comment. */ const char *end = strstr(code+i+2, "*/"); len = (end + 2) - (code + i); if (!end) len = strlen(code + i); if (tok_start != -1U) { add_token(&toks, code+tok_start, i - tok_start); tok_start = -1U; } } else if (cisalnum(code[i]) || code[i] == '_') { /* Identifier or part thereof */ if (tok_start == -1U) tok_start = i; len = 1; } else if (!cisspace(code[i])) { /* Punctuation: treat as single char token. */ if (tok_start != -1U) { add_token(&toks, code+tok_start, i - tok_start); tok_start = -1U; } add_token(&toks, code+i, 1); len = 1; } else { /* Whitespace. */ if (tok_start != -1U) { add_token(&toks, code+tok_start, i - tok_start); tok_start = -1U; } len = 1; } if (code[i] == '\n') start_of_line = true; else if (!cisspace(code[i])) start_of_line = false; } /* Add terminating NULL. */ tal_resizez(&toks, tal_count(toks) + 1); return toks; }
static bool looks_internal(char **lines, char **why) { unsigned int i; bool last_ended = true; /* Did last line finish a statement? */ for (i = 0; lines[i]; i++) { /* Skip leading whitespace. */ const char *line = lines[i] + strspn(lines[i], " \t"); unsigned len = strspn(line, IDENT_CHARS); if (!line[0] || cisspace(line[0]) || strstarts(line, "//") || strstarts(line, "#line")) continue; assert(line[strlen(line)-1] != '\n'); /* The winners. */ if (strstarts(line, "if") && len == 2) { *why = cast_const(char *, "starts with if"); return true; } if (strstarts(line, "for") && len == 3) { *why = cast_const(char *, "starts with for"); return true; }
void trig_parse_ci(const char *file, trig_parse_cicb *interest, trig_parse_cicb *activate, void *user) { FILE *f; char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol; int l; f = fopen(file, "r"); if (!f) { if (errno == ENOENT) return; /* No file is just like an empty one. */ ohshite(_("unable to open triggers ci file `%.250s'"), file); } push_cleanup(cu_closestream, ~0, NULL, 0, 1, f); while ((l = fgets_checked(linebuf, sizeof(linebuf), f, file)) >= 0) { for (cmd = linebuf; cisspace(*cmd); cmd++); if (*cmd == '#') continue; for (eol = linebuf + l; eol > cmd && cisspace(eol[-1]); eol--); if (eol == cmd) continue; *eol = '\0'; for (spc = cmd; *spc && !cisspace(*spc); spc++); if (!*spc) ohshit(_("triggers ci file contains unknown directive syntax")); *spc++ = '\0'; while (cisspace(*spc)) spc++; if (!strcmp(cmd, "interest")) { parse_ci_call(file, cmd, interest, spc, user, trig_await); } else if (!strcmp(cmd, "interest-noawait")) { parse_ci_call(file, cmd, interest, spc, user, trig_noawait); } else if (!strcmp(cmd, "activate")) { parse_ci_call(file, cmd, activate, spc, user, trig_await); } else if (!strcmp(cmd, "activate-noawait")) { parse_ci_call(file, cmd, activate, spc, user, trig_noawait); } else { ohshit(_("triggers ci file contains unknown directive `%.250s'"), cmd); } } pop_cleanup(ehflag_normaltidy); /* fclose() */ }
/* We only handle simple function definitions here. */ static char *add_func(char *others, const char *line) { const char *p, *end = strchr(line, '(') - 1; while (cisspace(*end)) { end--; if (end == line) return others; } for (p = end; cisalnum(*p) || *p == '_'; p--) { if (p == line) return others; } return talloc_asprintf_append(others, "printf(\"%%p\", %.*s);\n", (unsigned)(end - p), p+1); }
/* We only handle simple function definitions here. */ static char *add_func(const tal_t *ctx, char *others, const char *line) { const char *p, *end = strchr(line, '(') - 1; char *use; while (cisspace(*end)) { end--; if (end == line) return others; } for (p = end; cisalnum(*p) || *p == '_'; p--) { if (p == line) return others; } use = tal_fmt(ctx, "printf(\"%%p\", %.*s);\n", (unsigned)(end - p), p+1); if (others) use = tal_strcat(ctx, take(others), take(use)); return use; }
static bool spacestart(const struct pattern *p, size_t off) { return cisspace(p->text[p->part[off].off]); }
/* We want "finished in100 seconds to match "finished in 5 seconds". */ struct pattern *get_pattern(const char *line, struct values **vals) { enum pattern_type state = LITERAL; size_t len, i, max_parts = 3; struct pattern_part part; struct pattern *p; *vals = malloc(valsize(max_parts)); p = malloc(partsize(max_parts)); p->text = line; p->num_parts = 0; for (i = len = 0; state != TERM; i++, len++) { enum pattern_type old_state = state; bool starts_num; union val v; starts_num = (line[i] == '-' && cisdigit(line[i+1])) || cisdigit(line[i]); switch (state) { case LITERAL: if (starts_num) { state = INTEGER; break; } else if (cisspace(line[i])) { state = PRESPACES; break; } break; case PRESPACES: if (starts_num) { state = INTEGER; break; } else if (!cisspace(line[i])) { state = LITERAL; } break; case INTEGER: if (line[i] == '.') { if (cisdigit(line[i+1])) { /* Was float all along... */ state = old_state = FLOAT; } else state = LITERAL; break; } /* fall thru */ case FLOAT: if (cisspace(line[i])) { state = PRESPACES; break; } else if (!cisdigit(line[i])) { state = LITERAL; break; } break; case TERM: abort(); } if (!line[i]) state = TERM; if (state == old_state) continue; part.type = old_state; part.len = len; part.off = i - len; /* Make sure identical values memcmp in find_literal_numbers */ memset(&v, 0, sizeof(v)); if (old_state == FLOAT) { char *end; v.dval = strtod(line + part.off, &end); if (end != line + i) { warnx("Could not parse float '%.*s'", (int)len, line + i - len); } else { add_part(&p, vals, &part, &v, &max_parts); } len = 0; } else if (old_state == INTEGER) { char *end; v.ival = strtoll(line + part.off, &end, 10); if (end != line + i) { warnx("Could not parse integer '%.*s'", (int)len, line + i - len); } else { add_part(&p, vals, &part, &v, &max_parts); } len = 0; } else if (old_state == LITERAL && len > 0) { /* Since we can go to PRESPACES and back, we can * have successive literals. Collapse them. */ if (p->num_parts > 0 && p->part[p->num_parts-1].type == LITERAL) { p->part[p->num_parts-1].len += len; len = 0; continue; } add_part(&p, vals, &part, &v, &max_parts); len = 0; } } return p; }