diff options
Diffstat (limited to 'bin/mi5.awk')
-rw-r--r-- | bin/mi5.awk | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/bin/mi5.awk b/bin/mi5.awk new file mode 100644 index 00000000..7acb6f3b --- /dev/null +++ b/bin/mi5.awk @@ -0,0 +1,133 @@ +# Crude m4 preprocessor +BEGIN { + self = "mi5" + + # You can change any of these, but while changing these is still relatively + # sane... + open = "<%" + shut = "%>" + + # ... changing these probably isn't, and should compel you to rethink your + # code, or quite possibly your entire life thus far. + quote = "`" + unquote = "'" + dnl = "dnl" + + # We do not start in a block + bmac = 0 +} + +# Fatal error function +function fatal(str) { + stderr = "cat >&2" + printf "%s: %s\n", self, str | stderr + close(stderr) + exit(1) +} + +# Print an m4 opener as the first byte +NR == 1 { printf "%s", quote } + +# Blocks +NF == 1 && $1 == open && !bmac++ { + printf "%s", unquote + next +} +NF == 1 && $1 == shut && bmac-- { + printf "%s", quote + next +} + +# If in a block, print each line with any content on it after stripping leading +# and trailing whitespace +bmac && NF { + gsub(/(^ +| +$)/, "") + print $0 dnl +} + +# If not in a block, look for inlines to process +!bmac { + + # We'll parse one variable into another. + src = $0 + dst = "" + + # Start off neither quoting nor macroing. + iquo = imac = 0 + + # Crude and slow, clansman. Your parser was no better than that of a clumsy + # child. + for (i = 1; i <= length(src); ) { + + # Inline macro expansion: commented + # Look for end of comment and tip flag accordingly + if (iquo) + iquo = (substr(src, i, length(unquote)) != unquote) + + # Inline macro expansion + else if (imac) { + + # Close the current inline macro expansion if a close tag is found + # (in m4 terms: open a new quote), looking ahead past any spaces + # from this point first + for (j = i; substr(src, j, 1) ~ /[ \t]/; j++) + continue + if (substr(src, j, length(shut)) == shut) { + dst = dst quote + i = j + length(shut) + imac = 0 + continue + } + + # Look for start of comment and tip flag accordingly + iquo = (substr(src, i, length(quote)) == quote) + } + + # Plain text mode + else { + + # Open a new inline macro expansion if an open tag is found (in m4 + # terms: close the quote), and then look ahead past any spaces from + # that point afterward + if (substr(src, i, length(open)) == open) { + dst = dst unquote + imac = 1 + for (i += length(open); substr(src, i, 1) ~ /[ \t]/; i++) + continue + continue + } + + # Escape quote terminators + if (substr(src, i, length(unquote)) == unquote) { + + # Dear Mr. President. There are too many variables nowadays. + # Please eliminate three. I am NOT a crackpot. + dst = dst unquote unquote quote + + i += length(unquote) + continue + } + } + + # If we got down here, we can just add the next character and move on + dst = dst substr(src, i++, 1) + } + + # If we're still in a macro expansion or quote by this point, something's + # wrong; say so and stop, rather than print anything silly. + if (iquo) + fatal("Unterminated inline quote") + else if (imac) + fatal("Unterminated inline macro") + else + print dst +} + +# Print an m4 closer and newline deleter as the last bytes if we've correctly +# stopped all our blocks +END { + if (bmac) + fatal("Unterminated block macro") + else + print unquote dnl +} |