From 73bcdd66f3b4ce183bf8b9b0b5784830189c37f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Fri, 23 Oct 2020 02:08:00 +0200 Subject: release 1.0 --- .gitignore | 1 + test/no-final-newline/EXP=test.txt | 5 + test/no-final-newline/OUT=test.txt | 5 + test/no-final-newline/build.bat | 4 + test/no-final-newline/in.txt | 7 + test/no-final-newline/test.txt | 5 + test/self/EXP=test.txt | 96 ++++++++++++ test/self/OUT=test.txt | 96 ++++++++++++ test/self/build.bat | 4 + test/self/test.txt | 96 ++++++++++++ test/test.bat | 18 +++ test/vimrc/EXP=vimrc.txt | 6 + test/vimrc/OUT=vimrc.txt | 6 + test/vimrc/build.bat | 4 + test/vimrc/nerdtree.txt | 3 + test/vimrc/vimrc.txt | 3 + test/vimrc/vimtex.txt | 3 + tt.c | 290 +++++++++++++++++++++++++++++++++++++ tt.exe | Bin 0 -> 60928 bytes 19 files changed, 652 insertions(+) create mode 100644 .gitignore create mode 100644 test/no-final-newline/EXP=test.txt create mode 100644 test/no-final-newline/OUT=test.txt create mode 100644 test/no-final-newline/build.bat create mode 100644 test/no-final-newline/in.txt create mode 100644 test/no-final-newline/test.txt create mode 100644 test/self/EXP=test.txt create mode 100644 test/self/OUT=test.txt create mode 100644 test/self/build.bat create mode 100644 test/self/test.txt create mode 100644 test/test.bat create mode 100644 test/vimrc/EXP=vimrc.txt create mode 100644 test/vimrc/OUT=vimrc.txt create mode 100644 test/vimrc/build.bat create mode 100644 test/vimrc/nerdtree.txt create mode 100644 test/vimrc/vimrc.txt create mode 100644 test/vimrc/vimtex.txt create mode 100644 tt.c create mode 100644 tt.exe 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 @@ +<> + +--- + +<> \ 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') +<> +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 + +#ifdef _WIN32 +#include +#pragma comment(lib, "Shlwapi.lib") +#else +#include +#include +#include +#include +#include +#include +#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 Binary files /dev/null and b/tt.exe differ -- cgit v1.2.3