aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/mi5.awk137
1 files changed, 102 insertions, 35 deletions
diff --git a/bin/mi5.awk b/bin/mi5.awk
index 6e3a7ead..14f2ff2b 100644
--- a/bin/mi5.awk
+++ b/bin/mi5.awk
@@ -1,69 +1,136 @@
# Crude m4 preprocessor
BEGIN {
- mac = 0
+ self = "mi5"
+
+ # You can change any of these, but while changing these is still relatively
+ # sane...
if (!length(open))
open = "<%"
if (!length(shut))
shut = "%>"
+
+ # ... changing these probably isn't, and should compel you to rethink your
+ # code, or quite possibly your entire life thus far.
+ if (!length(quote))
+ quote = "`"
+ if (!length(unquote))
+ unquote = "'"
+ if (!length(dnl))
+ dnl = "dnl"
+}
+
+# Fatal error function
+function fatal(str) {
+ printf "%s: %s\n", self, str | "cat >&2"
+ exit(1)
}
# Print an m4 opener as the first byte
-NR == 1 { printf "`" }
+NR == 1 { printf "%s", quote }
# Blocks
-NF == 1 && $1 == open && !mac++ {
- printf "'"
+NF == 1 && $1 == open && !bmac++ {
+ printf "%s", unquote
next
}
-NF == 1 && $1 == shut && mac-- {
- printf "`"
+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
-mac && NF {
- sub(/^ */, "")
- sub(/ *$/, "")
+bmac && NF {
+ gsub(/(^ +| +$)/, "")
print $0 "dnl"
}
# If not in a block, look for inlines to process
-!mac {
+!bmac {
- # We'll empty one variable into another
+ # We'll parse one variable into another...
src = $0
dst = ""
- # As long as there's a pair of opening and closing tags
- while ((ind = index(src, open)) && index(src, shut) > ind) {
+ # Crude and slow, clansman. Your parser was no better than that of a clumsy
+ # child.
+ for (i = 1; i <= length(src); ) {
- # Read up to opening tag into seg, shift from src
- seg = substr(src, 1, ind - 1)
- src = substr(src, ind)
+ # Inline macro expansion: commented
+ if (iquo) {
- # Escape quote closer and add to dst
- gsub(/'/, "''`", seg)
- dst = dst seg
+ # Look for end of comment and tip flag accordingly
+ if (substr(src, i, length(unquote)) == unquote)
+ iquo = 0
+ }
- # Read up to closing tag into seg, shift from src
- ind = index(src, shut)
- seg = substr(src, length(open) + 1, ind - length(shut) - 1)
- src = substr(src, ind + length(shut))
+ # Inline macro expansion
+ else if (imac) {
- # Translate tags to quote open and close and add to dst
- sub(/^ */, "'", seg)
- sub(/ *$/, "`", seg)
- dst = dst seg
- }
+ # 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
+ i += length(shut)
+ imac = 0
+ continue
+ }
+
+ # Look for start of comment and tip flag accordingly
+ if (substr(src, i, length(quote)) == quote)
+ iquo = 1
+ }
+
+ # Plain text mode
+ else {
- # Escape quote closers in whatever's left
- gsub(/'/, "''`", src)
+ # 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
+ }
- # Tack that onto the end, and print it
- dst = dst src
- print dst
+ # 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)
+ 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
-END { print "'dnl" }
+# 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
+}