aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2020-10-23 02:08:00 +0200
committerJohn Ankarström <john@ankarstrom.se>2020-10-23 02:08:00 +0200
commit73bcdd66f3b4ce183bf8b9b0b5784830189c37f5 (patch)
treeefa2430e10347638a21a01598c42c4280690fc26
downloadtt-73bcdd66f3b4ce183bf8b9b0b5784830189c37f5.tar.gz
release 1.0
-rw-r--r--.gitignore1
-rw-r--r--test/no-final-newline/EXP=test.txt5
-rw-r--r--test/no-final-newline/OUT=test.txt5
-rw-r--r--test/no-final-newline/build.bat4
-rw-r--r--test/no-final-newline/in.txt7
-rw-r--r--test/no-final-newline/test.txt5
-rw-r--r--test/self/EXP=test.txt96
-rw-r--r--test/self/OUT=test.txt96
-rw-r--r--test/self/build.bat4
-rw-r--r--test/self/test.txt96
-rw-r--r--test/test.bat18
-rw-r--r--test/vimrc/EXP=vimrc.txt6
-rw-r--r--test/vimrc/OUT=vimrc.txt6
-rw-r--r--test/vimrc/build.bat4
-rw-r--r--test/vimrc/nerdtree.txt3
-rw-r--r--test/vimrc/vimrc.txt3
-rw-r--r--test/vimrc/vimtex.txt3
-rw-r--r--tt.c290
-rw-r--r--tt.exebin0 -> 60928 bytes
19 files changed, 652 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..281748d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.obj \ No newline at end of file
diff --git a/test/no-final-newline/EXP=test.txt b/test/no-final-newline/EXP=test.txt
new file mode 100644
index 0000000..82a2490
--- /dev/null
+++ b/test/no-final-newline/EXP=test.txt
@@ -0,0 +1,5 @@
+at top
+
+---
+
+at bottom
diff --git a/test/no-final-newline/OUT=test.txt b/test/no-final-newline/OUT=test.txt
new file mode 100644
index 0000000..82a2490
--- /dev/null
+++ b/test/no-final-newline/OUT=test.txt
@@ -0,0 +1,5 @@
+at top
+
+---
+
+at bottom
diff --git a/test/no-final-newline/build.bat b/test/no-final-newline/build.bat
new file mode 100644
index 0000000..2253752
--- /dev/null
+++ b/test/no-final-newline/build.bat
@@ -0,0 +1,4 @@
+@echo off
+setlocal
+cd /d %~dp0
+..\..\tt -oOUT= test.txt < in.txt \ No newline at end of file
diff --git a/test/no-final-newline/in.txt b/test/no-final-newline/in.txt
new file mode 100644
index 0000000..9fe42fa
--- /dev/null
+++ b/test/no-final-newline/in.txt
@@ -0,0 +1,7 @@
+-> top
+
+ at top
+
+-> bottom
+
+ at bottom \ No newline at end of file
diff --git a/test/no-final-newline/test.txt b/test/no-final-newline/test.txt
new file mode 100644
index 0000000..3152f74
--- /dev/null
+++ b/test/no-final-newline/test.txt
@@ -0,0 +1,5 @@
+<<top>>
+
+---
+
+<<bottom>> \ No newline at end of file
diff --git a/test/self/EXP=test.txt b/test/self/EXP=test.txt
new file mode 100644
index 0000000..edef5c2
--- /dev/null
+++ b/test/self/EXP=test.txt
@@ -0,0 +1,96 @@
+test
+
+;; -> init
+
+ShellApp := ComObjCreate("Shell.Application")
+GroupAdd, Explorer, ahk_class CabinetWClass
+GroupAdd, Explorer, ahk_class ExploreWClass
+
+;; -> library
+
+Explorer(hwnd := "")
+{
+ global ShellApp
+ if (hwnd = "")
+ WinGet, hwnd, id, A
+ for window in ShellApp.Windows
+ if (window.hwnd = hwnd)
+ return window
+ return -1
+}
+
+;; -> body
+
+#IfWinActive ahk_group Explorer
+
+^n::Run, % "explorer /n,""" Explorer().Document.Folder.Self.path """"
+^p::Run, % "cmd /k cd /d """ Explorer().Document.Folder.Self.path """"
+
++^p::
+path := Explorer().Document.Folder.Self.path
+Run, % "C:\Documents and Settings\All Users\Start Menu\Programs\Microsoft Visual Studio 2010 Express\Visual Studio Command Prompt (2010).lnk"
+WinWait, ahk_class ConsoleWindowClass
+SendInput, % "cd " path "{Return}"
+return
+
+LAlt & Up::
+RAlt & Up::
+e := Explorer()
+path := e.Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+slash := InStr(path, "\", 0, 0)
+if (slash = StrLen(path))
+ slash := InStr(path, "\", 0, 0, 2)
+if (slash = 0)
+ parent = ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} ; My Computer
+else
+ parent := SubStr(path, 1, slash)
+e.Navigate(parent)
+return
+
+LAlt & Down::
+RAlt & Down::
+path := Explorer().Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+Explorer().Navigate(path) ; go to real path of folder
+return
+
+^+n::
+FileCreateDir, % Explorer().Document.Folder.Self.path "\New Folder"
+SendInput, {F5}New Folder{F2}
+return
+
+^!n::
+FileAppend,, % Explorer().Document.Folder.Self.path "\New Text Document.txt"
+SendInput, {F5}New Text Document.txt{F2}
+return
+
+^h::
+SSF_SHOWALLOBJECTS := 0x0001
+VarSetCapacity(SHELLSTATE, 32, 0)
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", false)
+NumPut(NumGet(SHELLSTATE) ^ (1 << 0), SHELLSTATE,, "Int")
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", true)
+WinGet, win, List, ahk_group Explorer
+Loop, % win
+ PostMessage, 0x111, 41504,,, % "ahk_id " win%A_Index% ; refresh
+return
+
+^q::PostMessage, 0x111, 30210, 0,, A ; sort by name
+^w::PostMessage, 0x111, 30213, 0,, A ; sort by modified
+^e::PostMessage, 0x111, 30212, 0,, A ; sort by type
+^t::PostMessage, 0x111, 30214, 0,, A ; sort by created
+^g::PostMessage, 0x111, 30209, 0,, A ; show in groups
+^s::PostMessage, 0x111, 28717, 0,, A ; thumbnails
+^d::PostMessage, 0x111, 28713, 0,, A ; icons
+^i::PostMessage, 0x111, 28718, 0,, A ; tiles
+^l::PostMessage, 0x111, 28715, 0,, A ; list
+^f::PostMessage, 0x111, 28716, 0,, A ; details
+
+#IfWinActive
+
+;; -> .copy
+
+test
diff --git a/test/self/OUT=test.txt b/test/self/OUT=test.txt
new file mode 100644
index 0000000..edef5c2
--- /dev/null
+++ b/test/self/OUT=test.txt
@@ -0,0 +1,96 @@
+test
+
+;; -> init
+
+ShellApp := ComObjCreate("Shell.Application")
+GroupAdd, Explorer, ahk_class CabinetWClass
+GroupAdd, Explorer, ahk_class ExploreWClass
+
+;; -> library
+
+Explorer(hwnd := "")
+{
+ global ShellApp
+ if (hwnd = "")
+ WinGet, hwnd, id, A
+ for window in ShellApp.Windows
+ if (window.hwnd = hwnd)
+ return window
+ return -1
+}
+
+;; -> body
+
+#IfWinActive ahk_group Explorer
+
+^n::Run, % "explorer /n,""" Explorer().Document.Folder.Self.path """"
+^p::Run, % "cmd /k cd /d """ Explorer().Document.Folder.Self.path """"
+
++^p::
+path := Explorer().Document.Folder.Self.path
+Run, % "C:\Documents and Settings\All Users\Start Menu\Programs\Microsoft Visual Studio 2010 Express\Visual Studio Command Prompt (2010).lnk"
+WinWait, ahk_class ConsoleWindowClass
+SendInput, % "cd " path "{Return}"
+return
+
+LAlt & Up::
+RAlt & Up::
+e := Explorer()
+path := e.Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+slash := InStr(path, "\", 0, 0)
+if (slash = StrLen(path))
+ slash := InStr(path, "\", 0, 0, 2)
+if (slash = 0)
+ parent = ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} ; My Computer
+else
+ parent := SubStr(path, 1, slash)
+e.Navigate(parent)
+return
+
+LAlt & Down::
+RAlt & Down::
+path := Explorer().Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+Explorer().Navigate(path) ; go to real path of folder
+return
+
+^+n::
+FileCreateDir, % Explorer().Document.Folder.Self.path "\New Folder"
+SendInput, {F5}New Folder{F2}
+return
+
+^!n::
+FileAppend,, % Explorer().Document.Folder.Self.path "\New Text Document.txt"
+SendInput, {F5}New Text Document.txt{F2}
+return
+
+^h::
+SSF_SHOWALLOBJECTS := 0x0001
+VarSetCapacity(SHELLSTATE, 32, 0)
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", false)
+NumPut(NumGet(SHELLSTATE) ^ (1 << 0), SHELLSTATE,, "Int")
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", true)
+WinGet, win, List, ahk_group Explorer
+Loop, % win
+ PostMessage, 0x111, 41504,,, % "ahk_id " win%A_Index% ; refresh
+return
+
+^q::PostMessage, 0x111, 30210, 0,, A ; sort by name
+^w::PostMessage, 0x111, 30213, 0,, A ; sort by modified
+^e::PostMessage, 0x111, 30212, 0,, A ; sort by type
+^t::PostMessage, 0x111, 30214, 0,, A ; sort by created
+^g::PostMessage, 0x111, 30209, 0,, A ; show in groups
+^s::PostMessage, 0x111, 28717, 0,, A ; thumbnails
+^d::PostMessage, 0x111, 28713, 0,, A ; icons
+^i::PostMessage, 0x111, 28718, 0,, A ; tiles
+^l::PostMessage, 0x111, 28715, 0,, A ; list
+^f::PostMessage, 0x111, 28716, 0,, A ; details
+
+#IfWinActive
+
+;; -> .copy
+
+test
diff --git a/test/self/build.bat b/test/self/build.bat
new file mode 100644
index 0000000..2b48a07
--- /dev/null
+++ b/test/self/build.bat
@@ -0,0 +1,4 @@
+@echo off
+setlocal
+cd /d %~dp0
+..\..\tt -c"" -d";;" -oOUT= test.txt < test.txt \ No newline at end of file
diff --git a/test/self/test.txt b/test/self/test.txt
new file mode 100644
index 0000000..776629c
--- /dev/null
+++ b/test/self/test.txt
@@ -0,0 +1,96 @@
+<<.copy>>
+
+;; -> init
+
+ShellApp := ComObjCreate("Shell.Application")
+GroupAdd, Explorer, ahk_class CabinetWClass
+GroupAdd, Explorer, ahk_class ExploreWClass
+
+;; -> library
+
+Explorer(hwnd := "")
+{
+ global ShellApp
+ if (hwnd = "")
+ WinGet, hwnd, id, A
+ for window in ShellApp.Windows
+ if (window.hwnd = hwnd)
+ return window
+ return -1
+}
+
+;; -> body
+
+#IfWinActive ahk_group Explorer
+
+^n::Run, % "explorer /n,""" Explorer().Document.Folder.Self.path """"
+^p::Run, % "cmd /k cd /d """ Explorer().Document.Folder.Self.path """"
+
++^p::
+path := Explorer().Document.Folder.Self.path
+Run, % "C:\Documents and Settings\All Users\Start Menu\Programs\Microsoft Visual Studio 2010 Express\Visual Studio Command Prompt (2010).lnk"
+WinWait, ahk_class ConsoleWindowClass
+SendInput, % "cd " path "{Return}"
+return
+
+LAlt & Up::
+RAlt & Up::
+e := Explorer()
+path := e.Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+slash := InStr(path, "\", 0, 0)
+if (slash = StrLen(path))
+ slash := InStr(path, "\", 0, 0, 2)
+if (slash = 0)
+ parent = ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} ; My Computer
+else
+ parent := SubStr(path, 1, slash)
+e.Navigate(parent)
+return
+
+LAlt & Down::
+RAlt & Down::
+path := Explorer().Document.Folder.Self.path
+if (InStr(path, "::{") = 1)
+ return
+Explorer().Navigate(path) ; go to real path of folder
+return
+
+^+n::
+FileCreateDir, % Explorer().Document.Folder.Self.path "\New Folder"
+SendInput, {F5}New Folder{F2}
+return
+
+^!n::
+FileAppend,, % Explorer().Document.Folder.Self.path "\New Text Document.txt"
+SendInput, {F5}New Text Document.txt{F2}
+return
+
+^h::
+SSF_SHOWALLOBJECTS := 0x0001
+VarSetCapacity(SHELLSTATE, 32, 0)
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", false)
+NumPut(NumGet(SHELLSTATE) ^ (1 << 0), SHELLSTATE,, "Int")
+DllCall("Shell32\SHGetSetSettings", "Ptr", &SHELLSTATE, "UInt", SSF_SHOWALLOBJECTS, "Int", true)
+WinGet, win, List, ahk_group Explorer
+Loop, % win
+ PostMessage, 0x111, 41504,,, % "ahk_id " win%A_Index% ; refresh
+return
+
+^q::PostMessage, 0x111, 30210, 0,, A ; sort by name
+^w::PostMessage, 0x111, 30213, 0,, A ; sort by modified
+^e::PostMessage, 0x111, 30212, 0,, A ; sort by type
+^t::PostMessage, 0x111, 30214, 0,, A ; sort by created
+^g::PostMessage, 0x111, 30209, 0,, A ; show in groups
+^s::PostMessage, 0x111, 28717, 0,, A ; thumbnails
+^d::PostMessage, 0x111, 28713, 0,, A ; icons
+^i::PostMessage, 0x111, 28718, 0,, A ; tiles
+^l::PostMessage, 0x111, 28715, 0,, A ; list
+^f::PostMessage, 0x111, 28716, 0,, A ; details
+
+#IfWinActive
+
+;; -> .copy
+
+test
diff --git a/test/test.bat b/test/test.bat
new file mode 100644
index 0000000..29d853f
--- /dev/null
+++ b/test/test.bat
@@ -0,0 +1,18 @@
+@echo off
+setlocal
+cd /d %~dp0
+set err=0
+for /f "tokens=*" %%d in ('dir /b/a:d') do (
+ call %%d\build.bat
+ fc %%d\EXP=* %%d\OUT=*
+ if errorlevel 1 (
+ set err=1
+ color 47
+ pause
+ color
+ )
+)
+if %err% == 1 color 0C
+if %err% == 0 color 0A
+pause
+color \ No newline at end of file
diff --git a/test/vimrc/EXP=vimrc.txt b/test/vimrc/EXP=vimrc.txt
new file mode 100644
index 0000000..84465e5
--- /dev/null
+++ b/test/vimrc/EXP=vimrc.txt
@@ -0,0 +1,6 @@
+call plug#begin('~/.vim/plug')
+Plug 'scrooloose/nerdtree'
+let g:NERDTreeWinSize = 30
+Plug 'lervag/vimtex'
+let g:tex_flavor = 'latex'
+call plug#end()
diff --git a/test/vimrc/OUT=vimrc.txt b/test/vimrc/OUT=vimrc.txt
new file mode 100644
index 0000000..84465e5
--- /dev/null
+++ b/test/vimrc/OUT=vimrc.txt
@@ -0,0 +1,6 @@
+call plug#begin('~/.vim/plug')
+Plug 'scrooloose/nerdtree'
+let g:NERDTreeWinSize = 30
+Plug 'lervag/vimtex'
+let g:tex_flavor = 'latex'
+call plug#end()
diff --git a/test/vimrc/build.bat b/test/vimrc/build.bat
new file mode 100644
index 0000000..2f0cb7e
--- /dev/null
+++ b/test/vimrc/build.bat
@@ -0,0 +1,4 @@
+@echo off
+setlocal
+cd /d %~dp0
+type nerdtree.txt vimtex.txt 2>nul | ..\..\tt -d"""" -c -oOUT= vimrc.txt \ No newline at end of file
diff --git a/test/vimrc/nerdtree.txt b/test/vimrc/nerdtree.txt
new file mode 100644
index 0000000..d581921
--- /dev/null
+++ b/test/vimrc/nerdtree.txt
@@ -0,0 +1,3 @@
+" -> plugins
+Plug 'scrooloose/nerdtree'
+let g:NERDTreeWinSize = 30
diff --git a/test/vimrc/vimrc.txt b/test/vimrc/vimrc.txt
new file mode 100644
index 0000000..22376f1
--- /dev/null
+++ b/test/vimrc/vimrc.txt
@@ -0,0 +1,3 @@
+call plug#begin('~/.vim/plug')
+<<plugins>>
+call plug#end() \ No newline at end of file
diff --git a/test/vimrc/vimtex.txt b/test/vimrc/vimtex.txt
new file mode 100644
index 0000000..19f3bc9
--- /dev/null
+++ b/test/vimrc/vimtex.txt
@@ -0,0 +1,3 @@
+" -> plugins
+Plug 'lervag/vimtex'
+let g:tex_flavor = 'latex'
diff --git a/tt.c b/tt.c
new file mode 100644
index 0000000..9548957
--- /dev/null
+++ b/tt.c
@@ -0,0 +1,290 @@
+/* tt.c -- tangle to, written by John Ankarström */
+
+#include <stdio.h>
+
+#ifdef _WIN32
+#include <shlwapi.h>
+#pragma comment(lib, "Shlwapi.lib")
+#else
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#endif
+
+#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;
+
+ 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;
+ tmp = realloc(ins, refs_s * sizeof(char *));
+ if (tmp == NULL) err(1, "malloc");
+ ins = tmp;
+ 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 *in, *_in; /* current insertion */
+ int i, j;
+
+ 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 + (strlen(line) + 1) * sizeof(char));
+ j = 0;
+ } else {
+ j = strlen(ins[i]);
+ _in = realloc(ins[i],
+ 1 + j * sizeof(char) + (strlen(line) + 1) * sizeof(char));
+ if (_in == NULL) err(1, "malloc");
+ ins[i] = _in;
+ }
+
+ strncpy(ins[i] + j, line + strlen(code_prefix),
+ strlen(line) - strlen(code_prefix));
+ ins[i][j + strlen(line) - strlen(code_prefix)] = '\n';
+ ins[i][j + strlen(line) - strlen(code_prefix) + 1] = 0;
+
+ return true;
+}
+
+int main(int argc, char *argv[]) {
+ bool finish, found, iscode, wascode;
+ char **a, b, c, *line, *out_prefix, *tangledfile, *tmp;
+ FILE *f, *fo;
+ int i, j, k;
+ int 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");
+
+ 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) {
+ 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 */
+
+ if (strncmp(line, "<<", 2) != 0
+ || strncmp(line + strlen(line) - 2, ">>", 2) != 0) {
+ fprintf(f, "%s\n", line);
+ continue;
+ }
+
+ line += 2;
+ line[strlen(line) - 2] = '\0';
+
+ for (i = 0; i < strlen(line); i++)
+ if (isspace(line[i])) {
+ fprintf(f, "%s\n", line);
+ continue;
+ }
+
+ if (strlen(line) > REFMAX)
+ fprintf(stderr,
+ "Warning: Truncating identifier exceeding %d characters\n", REFMAX);
+
+ ref = line;
+
+ found = false;
+ for (i = 0; i < refs_c; i++)
+ if (strcmp(refs[i], ref) == 0) { found = true; break; }
+ if (!found) {
+ fprintf(stderr, "Unreferenced destination: %s\n", ref);
+ continue;
+ }
+ if (ins[i] == NULL) {
+ fprintf(stderr, "Warning: Insertion for %s is empty\n", ref);
+ continue;
+ }
+ if (strncmp(ins[i] + strlen(ins[i]) - 2, "\n\n", 2) == 0)
+ ins[i][strlen(ins[i]) - 1] = '\0'; /* remove extra newline */
+ fprintf(f, "%s", ins[i]);
+ }
+ if (c != '\n' && !finish) { finish = true; goto finish2; }
+
+ fclose(f);
+ fclose(fo);
+ }
+
+ return 0;
+}
diff --git a/tt.exe b/tt.exe
new file mode 100644
index 0000000..2ccfebc
--- /dev/null
+++ b/tt.exe
Binary files differ