aboutsummaryrefslogtreecommitdiff
path: root/tt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tt.c')
-rw-r--r--tt.c464
1 files changed, 218 insertions, 246 deletions
diff --git a/tt.c b/tt.c
index 973a6ad..66acdb2 100644
--- a/tt.c
+++ b/tt.c
@@ -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;
+}