]> git.plutz.net Git - shellwiki/blob - macros.awk
Merge commit '6bc502434737d7f08379e79b94fc6fda424ef779'
[shellwiki] / macros.awk
1 #!/bin/awk -f
2 #!/opt/busybox/awk -f
3
4 # Copyright 2022 - 2023 Paul Hänsch
5
6 # Permission to use, copy, modify, and/or distribute this software for any
7 # purpose with or without fee is hereby granted, provided that the above
8 # copyright notice and this permission notice appear in all copies.
9
10 # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 function sh_escape(arg){
19   return "'" gensub(/'/, "'\"'\"'", "g", arg) "'";
20 }
21
22 function argsplit(line, args, LOCAL, c, n, ctx) {
23   ctx="space"; n=0;
24
25   while ( length(line) > 0 ) {
26     c = substr(line, 1, 1);
27     line = substr(line, 2);
28     if (ctx == "space" )
29            if (c ~ /[ \t]/) ctx = "space";
30       else if (c ~ /\\/) { n++; ctx = "escbare"; }
31       else if (c ~ /"/)  { n++; ctx = "dquot"; }
32       else if (c ~ /'/)  { n++; ctx = "squot"; }
33       else   { n++; args[n] = c; ctx = "bare"; }
34     else if (ctx == "bare")
35            if (c ~ /[ \t]/) ctx = "space";
36       else if (c ~ /\\/)  ctx = "escbare";
37       else if (c ~ /"/)   ctx = "dquot";
38       else if (c ~ /'/)   ctx = "squot";
39       else args[n] = args[n] c;
40     else if (ctx == "dquot")
41            if (c ~ /"/)  ctx = "bare";
42       else if (c ~ /\\/) ctx = "escdquot";
43       else args[n] = args[n] c;
44     else if (ctx == "squot")
45       if (c ~ /'/)  ctx = "bare";
46       else args[n] = args[n] c;
47     else if (ctx == "escbare") {
48       args[n] = args[n] c;
49       ctx = "bare";
50     }
51     else if (ctx == "escdquot") {
52       args[n] = args[n] c;
53       ctx = "dquot";
54     }
55   }
56
57
58 function HTML ( text ) {
59   gsub( /&/,  "\\&",  text );
60   gsub( /</,  "\\&lt;",   text );
61   gsub( />/,  "\\&gt;",   text );
62   gsub( /"/,  "\\&quot;", text );
63   gsub( /'/,  "\\&#x27;", text );
64   gsub( /\\/, "\\&#x5C;", text );
65   return text;
66 }
67
68 function macro(call, LOCAL, line, args) {
69   argsplit(call, args);
70   call="";
71
72   for (n = 1; n in args; n++) call = call sh_escape(args[n]) " ";
73
74   if (args[1] in MACROS) {
75     printf "%s", file | sh_escape(ENVIRON["MD_MACROS"]) "/" call;
76     close(sh_escape(ENVIRON["MD_MACROS"]) "/" call);
77   } else {
78     printf "%s", HTML("<<" call ">>");
79   }
80 }
81
82 function unhtml ( text ) {
83   gsub( /&lt;/, "<", text);
84   gsub( /&gt;/, ">", text);
85   gsub( /&quot;/, "\"", text);
86   gsub( /&#x27;/, "'", text);
87   gsub( /&#x5c;/, "\\", text);
88   gsub( /&amp;/, "\\&", text);
89   return text;
90 }
91
92 function findmacro(line, LOCAL, st, len, pre, post) {
93   if ( match(line, /<code class="macro">[^\n]*<\/code>/) ) {
94     match(line, /<code class="macro">/); pre = substr( line, 1, RSTART - 1 );
95     line = substr( line, RSTART + RLENGTH);
96     match( line, /<\/code>/); post = substr(line, RSTART + RLENGTH);
97     line = substr(line, 1, RSTART - 1);
98
99     printf "%s", pre; macro( unhtml(line) ); findmacro( post );
100   } else {
101     printf "%s", line;
102   }
103 }
104
105 BEGIN {
106   if (ENVIRON["MD_MACROS"]) {
107     AllowMacros = "true";
108     "cd " sh_escape(ENVIRON["MD_MACROS"]) "; printf '%s/' *" |getline macro_list;
109     split(macro_list, MACROS, "/");
110     for (n in MACROS) { MACROS[MACROS[n]] = ""; delete MACROS[n]; }
111     delete MACROS[""];
112
113     file = ""; while ( getline ) { file = file $0 "\n"; }
114     findmacro( file );
115   }
116 }