07d51d0d49c4c9f7c8a3933ec92b4f6af03d994b braney Tue May 11 15:29:20 2021 -0700 first cut at cart re-write library diff --git src/hg/testRewrite/testRewrite.c src/hg/testRewrite/testRewrite.c new file mode 100644 index 0000000..1467751 --- /dev/null +++ src/hg/testRewrite/testRewrite.c @@ -0,0 +1,224 @@ +/* testRewrite - Test harness for cart rewrite tool. */ +#include "common.h" +#include "linefile.h" +#include "hash.h" +#include "options.h" +#include <regex.h> + +void usage() +/* Explain usage and exit. */ +{ +errAbort( + "testRewrite - Test harness for cart rewrite tool\n" + "usage:\n" + " testRewrite script input output\n" + "options:\n" + " -xxx=XXX\n" + ); +} + +/* Command line validation table. */ +static struct optionSpec options[] = { + {NULL, 0}, +}; + +struct snippet +{ +struct snippet *next; +int num; +char *precursor; +int precursorLen; +}; + +struct edit +{ +struct edit *next; +regex_t *compiledExp; +struct snippet *snippets; +}; + +struct snippet *parseSnippets(char *input) +{ +char *in = input; +struct snippet *out = NULL; + +char *prev = input; +for(;;) + { + if ((*in == 0) || ((*in == '\\') && isdigit(in[1]))) + { + struct snippet *snippet; + AllocVar(snippet); + + int size = in - prev; + if (size) + { + char buffer[size + 1]; + strncpy(buffer, prev, size); + buffer[size] = 0; + snippet->precursor = cloneString(buffer); + snippet->precursorLen = size; + prev = in; + } + + if (*in) + { + in++; + snippet->num = atoi(in); + while (isdigit(*in)) + in++; + } + + slAddHead(&out, snippet); + if (*in == 0) + break; + } + else + in++; + } + +slReverse(&out); + +return out; +} + +struct edit *parseEdit(char *line, char *file, int lineNum) +{ +char *strings[3]; + +int count = chopString(line, "\t", strings, 3); + +if (count != 2) + errAbort("Line %d of %s doesn't have exactly two tab separated fields.\n", lineNum, file); + +regex_t *compiledExp = NULL; +int errNum = 0; +int compileFlags = 0; + +AllocVar(compiledExp); +errNum = regcomp(compiledExp, strings[0], compileFlags); + +if (errNum != 0) + { + char errBuf[4096]; + regerror(errNum, compiledExp, errBuf, sizeof(errBuf)); + errAbort("got regular expression compilation error %d: %s on line %d of %s", errNum, errBuf, lineNum, file); + } + +struct edit *edit; +AllocVar(edit); +edit->compiledExp = compiledExp; +edit->snippets = parseSnippets(strings[1]); + +return edit; +} + +char *doSubEdits(struct snippet *snippets, regmatch_t *matches, char *source, int *plength) +{ +char output[40 * 1024], *out = output; +*out = 0; +//for(; matches->rm_so != -1;matches++, snippets = snippets->next) +for(; snippets ; matches++, snippets = snippets->next) + { + // copy the part before the match + strncpy(out, snippets->precursor, snippets->precursorLen); + out += snippets->precursorLen; + *plength += snippets->precursorLen; + + if (matches->rm_so == -1) + break; + + // copy in the part that matches the regular expression + int size = matches->rm_eo - matches->rm_so; + strncpy(out, &source[matches->rm_so], size); + *plength += size; + out += size; + } +*out = 0; +return cloneString(output); +} + +char *doOneEdit(struct edit *edit, char *inputString) +{ +char buffer[40 * 1024]; +char *source = inputString; +regmatch_t matches[1024]; +int lastSrc = 0; +int offset = 0; +int inputLen = strlen(inputString); + +for(;;) + { + if (regexec(edit->compiledExp, source, ArraySize(matches), matches, 0)) + break; + + int size = matches->rm_so; + strncpy(&buffer[lastSrc], source, size); + lastSrc += size; + + int subSize = 0; + char *subEdit = doSubEdits(edit->snippets, matches+1, source, &subSize); + strncpy(&buffer[lastSrc], subEdit, subSize); + + lastSrc += subSize; + offset += matches->rm_eo; + if (offset >= inputLen) + printf("foo"); + source = &inputString[offset]; + } + +strcpy(&buffer[lastSrc], source); + +return cloneString(buffer); +} + +void doEdits(struct edit *edits, char *input, char *outputFile) +{ +FILE *f = mustOpen(outputFile, "w"); + +char *outString = input; + +for(; edits; edits = edits->next) + outString = doOneEdit(edits, outString); +fputs(outString, f); +fclose(f); +} + +void testRewrite(char *script, char *inputFile, char *outputFile) +/* testRewrite - Test harness for cart rewrite tool. */ +{ +struct lineFile *lf = lineFileOpen(script, TRUE); +char *start; +int size; +struct edit *edits = NULL; + +while (lineFileNext(lf, &start, &size)) + { + slAddHead(&edits, parseEdit(start, script, lf->lineIx)); + } + +slReverse(&edits); + +lineFileClose(&lf); + +int count = 0; +lf = lineFileOpen(inputFile, TRUE); +while (lineFileNext(lf, &start, &size)) + { + if (count) + errAbort("input should have only one line with name=value pairs separated by ampersands."); + + doEdits(edits, start, outputFile); + count++; + } +} + +int main(int argc, char *argv[]) +/* Process command line. */ +{ +optionInit(&argc, argv, options); +if (argc != 4) + usage(); +testRewrite(argv[1], argv[2], argv[3]); +return 0; +}