char * VAV_BackSlashDecode(const char *s, const char *e) { const char *q; char *p, *r; int i; if (e == NULL) e = strchr(s, '\0'); assert(e != NULL); p = calloc((e - s) + 1, 1); if (p == NULL) return (p); for (r = p, q = s; q < e; ) { if (*q != '\\') { *r++ = *q++; continue; } i = VAV_BackSlash(q, r); q += i; r++; } *r = '\0'; return (p); }
void parse_string(const char *spec, const struct cmds *cmd, void *priv, struct vtclog *vl) { char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS]; struct vsb *token_exp[MAX_TOKENS]; char *p, *q, *f, *buf; int nest_brace; int tn; const struct cmds *cp; AN(spec); buf = strdup(spec); AN(buf); for (p = buf; *p != '\0'; p++) { if (vtc_error || vtc_stop) break; /* Start of line */ if (isspace(*p)) continue; if (*p == '\n') continue; if (*p == '#') { for (; *p != '\0' && *p != '\n'; p++) ; if (*p == '\0') break; continue; } q = strchr(p, '\n'); if (q == NULL) q = strchr(p, '\0'); if (q - p > 60) vtc_log(vl, 2, "=== %.60s...", p); else vtc_log(vl, 2, "=== %.*s", (int)(q - p), p); /* First content on line, collect tokens */ tn = 0; f = p; while (*p != '\0') { assert(tn < MAX_TOKENS); if (*p == '\n') { /* End on NL */ break; } if (isspace(*p)) { /* Inter-token whitespace */ p++; continue; } if (*p == '\\' && p[1] == '\n') { /* line-cont */ p += 2; continue; } if (*p == '"') { /* quotes */ token_s[tn] = ++p; q = p; for (; *p != '\0'; p++) { if (*p == '"') break; if (*p == '\\') { p += VAV_BackSlash(p, q) - 1; q++; } else { if (*p == '\n') vtc_log(vl, 0, "Unterminated quoted string in line: %*.*s", (int)(p - f), (int)(p - f), f); assert(*p != '\n'); *q++ = *p; } } token_e[tn++] = q; p++; } else if (*p == '{') { /* Braces */ nest_brace = 0; token_s[tn] = p + 1; for (; *p != '\0'; p++) { if (*p == '{') nest_brace++; else if (*p == '}') { if (--nest_brace == 0) break; } } assert(*p == '}'); token_e[tn++] = p++; } else { /* other tokens */ token_s[tn] = p; for (; *p != '\0' && !isspace(*p); p++) ; token_e[tn++] = p; } } assert(tn < MAX_TOKENS); token_s[tn] = NULL; for (tn = 0; token_s[tn] != NULL; tn++) { token_exp[tn] = NULL; AN(token_e[tn]); /*lint !e771 */ *token_e[tn] = '\0'; /*lint !e771 */ if (NULL == strstr(token_s[tn], "${")) continue; token_exp[tn] = macro_expand(vl, token_s[tn]); if (vtc_error) { return; } token_s[tn] = VSB_data(token_exp[tn]); token_e[tn] = strchr(token_s[tn], '\0'); } for (cp = cmd; cp->name != NULL; cp++) if (!strcmp(token_s[0], cp->name)) break; if (cp->name == NULL) { vtc_log(vl, 0, "Unknown command: \"%s\"", token_s[0]); return; } assert(cp->cmd != NULL); cp->cmd(token_s, priv, cmd, vl); } }