diff options
author | John Ankarström <john@ankarstrom.se> | 2020-10-23 02:11:59 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2020-10-23 02:11:59 +0200 |
commit | c3143fbdb7ea46539023e11cb30a7b14434030f3 (patch) | |
tree | e2a4394e0b3d8c6a882c82637a08823e6e5b5043 /tt.c | |
parent | 24da48a86bb542be247127258db5fcafab4ba011 (diff) | |
download | tt-c3143fbdb7ea46539023e11cb30a7b14434030f3.tar.gz |
release 1.2
Diffstat (limited to 'tt.c')
-rw-r--r-- | tt.c | 464 |
1 files changed, 218 insertions, 246 deletions
@@ -1,4 +1,4 @@ -/* tt.c -- tangle to, written by John Ankarström */ +// tt.c -- tangle to, written by John Ankarström -> tt.c #include <stdio.h> @@ -14,224 +14,88 @@ #include <sys/stat.h> #endif +#define REFMAX 80 +#define USAGE "usage: %s [-cCODE_PREFIX] [-dDOC_PREFIX] [-oOUTPREFIX] destination ...\n", argv[0] + #define err(code, string) do { fprintf(stderr, "%s: %s: %s\n", string, strerror(errno)); exit(code); } while (0) #define die(...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0) #define true 1 #define false 0 #define bool int -#define REFMAX 80 - -char *code_prefix; -char *doc_prefix; - -char *ref; /* current reference */ - -char ***ins; /* insertions */ char **refs; /* references */ int refs_c; /* count */ -int refs_s; /* size */ - -void reference(char *line) { - int i, j; - char *ln, **tmp, ***tmp2; - - ln = line; - - /* parse: -> identifier_without_whitespace */ - -start: - if (*ln == '\0') return; - else if (*ln == '-') { ln++; goto arrow; } - else { ln++; goto start; } -arrow: - if (*ln != '>') goto start; - else ln++; -space: - if (*ln == ' ') { ln++; goto space; } - - for (i = 0; i < strlen(ln); i++) - if (isspace(ln[i])) { - for (j = i; j < strlen(ln); j++) - if (!isspace(ln[j])) return; - break; - } - - ln[i] = '\0'; - - if (strlen(ln) > REFMAX) { - fprintf(stderr, "Warning: Truncating identifier exceeding %d characters\n", - REFMAX); - ln[REFMAX] = '\0'; - } - - ref = malloc(1 * strlen(ln) * sizeof(ln)); - sprintf(ref, "%s", ln); /* set current reference */ - ref[strlen(ln)] = 0; - - for (i = 0; i < refs_c; i++) - if (strcmp(refs[i], ref) == 0) return; - - fprintf(stderr, "New reference: %s\n", ref); - - if (++refs_c > refs_s) { - refs_s += 10; - tmp = realloc(refs, refs_s * sizeof(char *)); - if (tmp == NULL) err(1, "malloc"); - refs = tmp; - tmp2 = realloc(ins, refs_s * sizeof(char *)); - if (tmp2 == NULL) err(1, "malloc"); - ins = tmp2; - for (i = refs_s - 10; i < refs_s; i++) /* TODO: is this right? */ - ins[i] = NULL; - } - - refs[refs_c-1] = malloc(1 + REFMAX * sizeof(char)); - sprintf(refs[refs_c-1], "%s", ref); -} - -bool code(char *line) { - char **tmp; - int i, j, len; - - if (ref[0] == '\0') return false; - if (strlen(code_prefix) > 0) - if (strncmp(line, code_prefix, strlen(code_prefix)) != 0) return false; - if (strlen(doc_prefix) > 0) - if (strncmp(line, doc_prefix, strlen(doc_prefix)) == 0) return false; - - for (i = 0; i < refs_c; i++) - if (strcmp(refs[i], ref) == 0) break; - - if (ins[i] == NULL) { - ins[i] = malloc(1 + 1 * sizeof(char *)); - if (ins[i] == NULL) err(1, "malloc"); - len = 0; - } else { - for (len = 0; ins[i][len] != NULL; len++) ; - tmp = realloc(ins[i], 1 + (len + 1) * sizeof(char *)); - if (tmp == NULL) err(1, "malloc"); - ins[i] = tmp; - } - - ins[i][len+1] = NULL; - - ins[i][len] = malloc(1 + strlen(line) * sizeof(char)); - if (ins[i][len] == NULL) err(1, "malloc"); - - strncpy(ins[i][len], line + strlen(code_prefix), - strlen(line) - strlen(code_prefix)); - ins[i][len][strlen(line) - strlen(code_prefix)] = 0; - - return true; -} +int refs_s; /* size (number of elements allocated for) */ +char ***ins; /* insertions */ +void reference(char *line); +char *ref; +bool insertion(char *line); +char *code_prefix; /* string with which code lines should start */ +char *doc_prefix; /* string with which documentation lines should start */ +char *out_prefix; /* string to which the output file name should be appended */ int main(int argc, char *argv[]) { - bool finish, iscode, wascode; - char **a, b, c, *line, *out_prefix, *tangledfile, *tmp; - FILE *f, *fo; - int i, j, k, m; - int indent, line_l, line_s, offset; - - ref = malloc(1 + (REFMAX + 4) * sizeof(char)); /* incl. << and >> */ - if (ref == NULL) err(1, "malloc"); - - refs_c = 0; - refs_s = 10; - refs = malloc(refs_s * sizeof(char *)); - ins = malloc(refs_s * sizeof(char **)); - if (refs == NULL || ins == NULL) err(1, "malloc"); - for (i = 0; i < refs_s; i++) - ins[i] = NULL; - - code_prefix = " "; - doc_prefix = ""; - out_prefix = "out/"; - - for (i = 1; i < argc; i++) - if (argv[i][0] == '-') { - switch(argv[i][1]) { - case 'c': - code_prefix = argv[i] + 2; - break; - case 'd': - doc_prefix = argv[i] + 2; - break; - case 'o': - out_prefix = argv[i] + 2; - break; - } - } else - break; - - if (strcmp(code_prefix, doc_prefix) == 0) - die("code_prefix and doc_prefix cannot be identical\n"); - if (strlen(out_prefix) == 0) - die("out_prefix cannot be empty\n"); - + int i; + char *line; + int line_l; /* length */ + int line_s; /* size (number of characters allocated for) */ + int b; + int c; + char *tmp; + bool wascode = false; + int offset; + int k; + char *tangledfilename; + FILE *f; + FILE *fo; + int indent; + int j; + int m; + refs_c = 0; + refs_s = 10; + refs = malloc(refs_s * sizeof(char *)); + if (refs == NULL) err(1, "malloc"); + ins = malloc(refs_s * sizeof(char **)); + if (ins == NULL) err(1, "malloc"); + for (i = 0; i < refs_s; i++) + ins[i] = NULL; + ref = malloc(1 + REFMAX * sizeof(char)); + if (ref == NULL) err(1, "malloc"); + code_prefix = " "; /* code lines should begin with four spaces */ + doc_prefix = ""; /* other lines are documentation lines */ + out_prefix = "out/"; /* all output files go in the out/ directory */ + for (i = 1; i < argc; i++) + if (argv[i][0] == '-') { + switch(argv[i][1]) { + case 'c': + code_prefix = argv[i] + 2; + break; + case 'd': + doc_prefix = argv[i] + 2; + break; + case 'o': + out_prefix = argv[i] + 2; + break; + case '-': + i++; + goto end; + default: + die(USAGE); + } + } else + break; + end: + if (strcmp(code_prefix, doc_prefix) == 0) + die("code_prefix and doc_prefix cannot be identical\n"); + if (strlen(out_prefix) == 0) + die("out_prefix cannot be empty\n"); + if (i == argc) die(USAGE); offset = i; - if (offset == argc) die("usage: %s destination ...\n", argv[0]); - - line_l = 0; - line_s = 100; - line = malloc(1 + line_s * sizeof(char)); - if (line == NULL) err(1, "malloc"); - - finish = false; - iscode = false; - wascode = false; - while ((b = getchar()) != EOF) { - c = b; - if (c != '\n') { - if (line_l + 1 > line_s) { - line_s += 20; - tmp = realloc(line, 1 + line_s * sizeof(char)); - if (tmp == NULL) err(1, "malloc"); - line = tmp; - } - line[line_l++] = c; - continue; - } - -finish: - line[line_l] = '\0'; line_l = 0; - - if (strlen(code_prefix) == 0 && !wascode && strcmp(line, "") == 0) { - continue; /* ignore empty lines after doc text */ - } - - iscode = code(line); - if (!iscode) reference(line); - - if (strlen(code_prefix) > 0 && wascode && !iscode) { - code(code_prefix); /* add extra empty line after code block */ - } - wascode = iscode; - } - if (c != '\n' && !finish) { finish = true; goto finish; } - - free(ref); - - for (k = offset; k < argc; k++) { - tangledfile = malloc( - 1 + (strlen(out_prefix) + 50 + sizeof(argv[k])) * sizeof(char) /* ??? */ - ); - if (tangledfile == NULL) err(1, "malloc"); - - if (sprintf(tangledfile, "%s%s", out_prefix, argv[k]) == -1) - err(1, "sprintf"); - - f = fopen(tangledfile, "w"); - if (f == NULL) err(1, "fopen"); - fo = fopen(argv[k], "r"); - if (fo == NULL) err(1, "fopen"); - - free(tangledfile); - - line_l = 0; - finish = false; - while ((b = fgetc(fo)) != EOF) { + line_s = 100; + line = malloc(1 + line_s * sizeof(char)); + if (line == NULL) err(1, "malloc"); + while ((b = getchar()) != EOF) { c = b; if (c != '\n') { if (line_l + 1 > line_s) { @@ -243,56 +107,164 @@ finish: line[line_l++] = c; continue; } - -finish2: + finish: line[line_l] = '\0'; - line_l = 0; /* reset line length count */ - - ref = line; - for (indent = 0; *ref == ' '; ref++) indent++; - - if (strncmp(ref, "<<", 2) != 0 - || strncmp(ref + strlen(ref) - 2, ">>", 2) != 0) { - fprintf(f, "%s\n", line); + line_l = 0; + if (strlen(code_prefix) == 0 && !wascode && strcmp(line, "") == 0) { continue; } - ref += 2; - ref[strlen(ref) - 2] = '\0'; + if (!insertion(line)) reference(line); + } + if (c != '\n') { c = '\n'; goto finish; } + free(ref); + for (k = offset; k < argc; k++) { + tangledfilename = malloc(1 + (strlen(out_prefix) + strlen(argv[k]) + 50) * sizeof(char)); + if (tangledfilename == NULL) err(1, "malloc"); + if (sprintf(tangledfilename, "%s%s", out_prefix, argv[k]) == -1) + err(1, "sprintf"); + f = fopen(tangledfilename, "w"); + if (f == NULL) err(1, "fopen"); + fo = fopen(argv[k], "r"); + if (fo == NULL) err(1, "fopen"); + free(tangledfilename); + line_l = 0; + /* line_s is remembered */ - for (i = 0; i < strlen(ref); i++) - if (isspace(ref[i])) { + while ((b = fgetc(fo)) != EOF) { + c = b; + if (c != '\n') { + if (line_l + 1 > line_s) { + line_s += 20; + tmp = realloc(line, 1 + line_s * sizeof(char)); + if (tmp == NULL) err(1, "malloc"); + line = tmp; + } + line[line_l++] = c; + continue; + } + finish2: + line[line_l] = '\0'; + line_l = 0; /* reset line length count */ + ref = line; + for (indent = 0; *ref == ' '; ref++) indent++; + if (strncmp(ref, "<<", 2) != 0 + || strncmp(ref + strlen(ref) - 2, ">>", 2) != 0) { fprintf(f, "%s\n", line); continue; } - - if (strlen(ref) > REFMAX) - fprintf(stderr, - "Warning: Truncating identifier exceeding %d characters\n", REFMAX); - - for (i = 0; i < refs_c; i++) - if (strncmp(refs[i], ref, REFMAX) == 0) goto found; - fprintf(stderr, "Unreferenced destination: %s\n", ref); - continue; -found: - if (ins[i] == NULL) { - fprintf(stderr, "Warning: Insertion for %s is empty\n", ref); + ref += 2; + ref[strlen(ref) - 2] = '\0'; + for (i = 0; i < strlen(ref); i++) + if (isspace(ref[i])) { + fprintf(f, "%s\n", line); + continue; + } + if (strlen(ref) > REFMAX) + fprintf(stderr, + "Warning: Truncating identifier exceeding %d characters\n", REFMAX); + for (i = 0; i < refs_c; i++) + if (strncmp(refs[i], ref, REFMAX) == 0) goto found; + fprintf(stderr, "Unreferenced destination: %s\n", ref); continue; - } - for (j = 0; ins[i][j] != NULL; j++) { - if (ins[i][j + 1] == NULL) { - if (strlen(ins[i][j]) == 0) - break; /* remove extra newline */ + found: + if (ins[i] == NULL) { + fprintf(stderr, "Warning: Insertion for %s is empty\n", ref); + continue; + } + for (j = 0; ins[i][j] != NULL; j++) { + if (ins[i][j + 1] == NULL) { + if (strlen(ins[i][j]) == 0) + break; /* remove extra newline */ + } + for (m = indent; m > 0; m--) putc(' ', f); + fprintf(f, "%s\n", ins[i][j]); } - for (m = indent; m > 0; m--) putc(' ', f); - fprintf(f, "%s\n", ins[i][j]); } + if (c != '\n') { c = '\n'; goto finish2; } + fclose(f); + fclose(fo); } - if (c != '\n' && !finish) { finish = true; goto finish2; } - - fclose(f); - fclose(fo); - } - return 0; } + +void reference(char *line) { + char *ln = line; + int i; + int j; + char **tmp; + char ***tmp2; + if (strncmp(ln, doc_prefix, strlen(doc_prefix)) != 0) return; + hyphen: + if (*ln == '\0') return; + else if (*ln == '-') { ln++; goto lessthan; } + else { ln++; goto hyphen; } + lessthan: + if (*ln != '>') goto hyphen; + else ln++; + space: + if (isspace(*ln)) { ln++; goto space; } + if (*ln == '\0') { ref = ""; return; } + for (i = 0; i < strlen(ln); i++) + if (isspace(ln[i])) { + for (j = i; j < strlen(ln); j++) + if (!isspace(ln[j])) return; + break; + } + ln[i] = '\0'; + + if (strlen(ln) > REFMAX) { + fprintf(stderr, "Warning: Truncating identifier exceeding %d characters\n", + REFMAX); + ln[REFMAX] = '\0'; + } + sprintf(ref, "%s", ln); /* set current reference */ + ref[strlen(ln)] = '\0'; + for (i = 0; i < refs_c; i++) + if (strcmp(refs[i], ref) == 0) return; + fprintf(stderr, "New reference: %s\n", ref); + if (++refs_c > refs_s) { + refs_s += 10; + tmp = realloc(refs, refs_s * sizeof(char *)); + if (tmp == NULL) err(1, "malloc"); + refs = tmp; + tmp2 = realloc(ins, refs_s * sizeof(char *)); + if (tmp2 == NULL) err(1, "malloc"); + ins = tmp2; + for (i = refs_s - 10; i < refs_s; i++) /* TODO: is this right? */ + ins[i] = NULL; + } + refs[refs_c-1] = malloc(1 + REFMAX * sizeof(char)); + sprintf(refs[refs_c-1], "%s", ref); +} + +bool insertion(char *line) { + int i; + char **tmp; + int len; + if (ref[0] == '\0') return false; + if (strlen(code_prefix) > 0) + if (strncmp(line, code_prefix, strlen(code_prefix)) != 0) return false; + if (strlen(doc_prefix) > 0) + if (strncmp(line, doc_prefix, strlen(doc_prefix)) == 0) return false; + for (i = 0; i < refs_c; i++) + if (strcmp(refs[i], ref) == 0) break; + if (ins[i] == NULL) { + ins[i] = malloc(1 + 1 * sizeof(char *)); + if (ins[i] == NULL) err(1, "malloc"); + len = 0; + } + else { + for (len = 0; ins[i][len] != NULL; len++) ; + tmp = realloc(ins[i], 1 + (len + 1) * sizeof(char *)); + if (tmp == NULL) err(1, "malloc"); + ins[i] = tmp; + } + ins[i][len + 1] = NULL; + ins[i][len] = malloc(1 + strlen(line) * sizeof(char)); + if (ins[i][len] == NULL) err(1, "malloc"); + strncpy(ins[i][len], line + strlen(code_prefix), + strlen(line) - strlen(code_prefix)); + ins[i][len][strlen(line) - strlen(code_prefix)] = '\0'; + return true; +} |