diff options
Diffstat (limited to 'preproc.awk')
| -rw-r--r-- | preproc.awk | 180 |
1 files changed, 111 insertions, 69 deletions
diff --git a/preproc.awk b/preproc.awk index 4eb1718..abc44d4 100644 --- a/preproc.awk +++ b/preproc.awk @@ -1,38 +1,39 @@ BEGIN { stage1 = 1 depth = 0 - nql = 0 -} + __nvlen = 0 -function nameQueuePush(name) { - prename = "" - if (nql > 0) { - name = nameQueue[nql-1] "/" name - } - nameQueue[nql++] = name - nameClose[name] = depth + fileCount = 0 + # Last stylesheet is also used for replacement + ARGV[ARGC] = ARGV[ARGC - 1] + ARGC++ } -function nameQueueTop() { - return "<" nameQueue[nql - 1] ">" +FNR == 1 { + fileCount++ } -function nameQueueGet(ind) { - return "<" nameQueue[ind] ">" -} +# Do substitution on last file +stage1 && fileCount == ARGC - 1 { + stage1 = 0 + stage2 = 1 -function nameCloseTop() { - return nameClose[nameQueue[nql - 1]] -} + depth = 0 + macroNameOnly = 0 + + # Do substitutions inside definitions + for (name in macros) { + for (subname in macros) { + gsub(subname, macros[subname], macros[name]) + } + } -function nameQueuePop() { - delete nameClose[nameQueue[nql - 1]] - delete nameQueue[--nql] + fileCount = 0 } -# Comments -/^\/\/.*$/ { - next +# Comments (experimental) +{ + sub(/[[:blank:]]*\/\/.*$/, "") } # @@ -54,107 +55,107 @@ function nameQueuePop() { # printNQ() # } -stage1 && gotNameOnly { +stage1 && macroNameOnly { + # Skip blank lines if ($0 ~ /^[[:blank:]]*$/) { next } - gotNameOnly = 0 - if ($0 ~ /^[[:blank:]]*\{/) { + macroNameOnly = 0 + # We had a name, blank lines, and now the beginning of line has "{" + # There is a definition + if (sub(/^[[:blank:]]*\{/, "") > 0) { depth++ - next } + # The name was not starting a definition else { - nameQueuePop() - for (ind in nameQueue) { - macros[nameQueueGet(ind)] = macros[nameQueueGet(ind)] ORS nameOnly + namevec_Pop() + # Since the line didn't start a new definition, we need to add it + # "back" verbatim to the current definition(s) + for (ind in __nvnames) { + macros[namevec_At(ind)] = macros[namevec_At(ind)] ORS macroNameLine } } } stage1 && /<[^>]*>[[:blank:]]*\{/ { - match($0, /<[^>]*>/) - nameQueuePush(substr($0, RSTART + 1, RLENGTH - 2)) - sub(/^[^{]*{[[:blank:]]*/, "") + # There is a definition + namevec_Push() depth++ - if ($0 == "") next + # Remove definition start + sub(/^[^{]*{[[:blank:]]*/, "") } -# Macro placement stage1 && /<[^>]*>/ { - for (i = 0; i < nql; i++) { - sub(/^ /, "") - } - nameOnly = $0 - match($0, /<[^>]*>/); - nameQueuePush(substr($0, RSTART + 1, RLENGTH - 2)) - gotNameOnly = 1 + removeLeadingTabulation() + + # Start searching for a potential opening brace + macroNameOnly = 1 + macroNameLine = $0 + namevec_Push() next } stage1 && depth >= 1 { depth += gsub("{", "{") - gsub("}", "}") - for (i = 0; i < nql; i++) { - sub(/^ /, "") - } + removeLeadingTabulation() skipORS = 0 - if (depth <= nameCloseTop()) { - sub(/[[:blank:]]*}[[:blank:]]*$/, "") + if (depth <= namevec_TopDepth()) { + # Remove macro closing braces + for (i = namevec_TopDepth() - depth; i >= 0; i--) { + sub(/}/, "") + } skipORS = 1 } - for (ind in nameQueue) { - if (length(macros[nameQueueGet(ind)]) != 0 && !skipORS) { - macros[nameQueueGet(ind)] = macros[nameQueueGet(ind)] ORS + # Add line to definition and parent definitions + for (ind in __nvnames) { + if (length(macros[namevec_At(ind)]) != 0 && !skipORS) { + macros[namevec_At(ind)] = macros[namevec_At(ind)] ORS } - macros[nameQueueGet(ind)] = macros[nameQueueGet(ind)] $0 + macros[namevec_At(ind)] = macros[namevec_At(ind)] $0 } - if (depth <= nameCloseTop()) { - nameQueuePop() + if (depth <= namevec_TopDepth()) { + namevec_Pop() } next } -ENDFILE { - if (stage1) { - stage1 = 0 - stage2 = 1 - depth = 0 - gotNameOnly = 0 - - for (name in macros) { - for (subname in macros) { - gsub(subname, macros[subname], macros[name]) - } - } +function removeLeadingTabulation() { + # Remove leading tabulation when inside macro definition + for (i = namevec_Length(); i > 0; i--) { + sub(/^ /, "") } } # # Stage 2 -# Do placements +# Do substitution # +# Skip over definitions stage2 && depth >= 1 { depth += gsub("{", "{") - gsub("}", "}") next } -stage2 && gotNameOnly { +stage2 && macroNameOnly { + # Skip over blank lines if ($0 ~ /^[[:blank:]]*$/) { next } - gotNameOnly = 0 + macroNameOnly = 0 # If is definition if ($0 ~ /^[[:blank:]]*\{/) { depth = 1 macroName = "" next } + # Do substitution else { print macros[macroName] macroName = "" @@ -163,18 +164,22 @@ stage2 && gotNameOnly { stage2 && /^[[:blank:]]*<[^>]*>/ { match($0, /<[^>]*>/) + # If we found a definition if ($0 ~ "{") { macroName = "" depth = gsub("{", "{") - gsub("}", "}") } + # Macro name could begin a potential definition, with a "{" on a new line else { macroName = substr($0, RSTART, RLENGTH) - gotNameOnly = 1 + macroNameOnly = 1 } next } +# Outside definition stage2 && depth == 0 { + # Do macro substitutions on line while(match($0, /<[^>]*>/)) { macroName = substr($0, RSTART, RLENGTH) sub(macroName, macros[macroName]) @@ -183,6 +188,7 @@ stage2 && depth == 0 { } END { + # Substitution for macro name at end of file if (macroName != "") print macros[macroName] @@ -191,3 +197,39 @@ END { # print macroName ORS macros[macroName] # } } + +# +# namevec "structure" +# + +function namevec_Top() { + return namevec_At(__nvlen - 1) +} + +function namevec_TopDepth() { + return __nvdepth[__nvlen - 1] +} + +function namevec_At(_ind) { + return "<" __nvnames[_ind] ">" +} + +function namevec_Length() { + return __nvlen +} + +function namevec_Push() { + match($0, /<[^>]*>/) + name = substr($0, RSTART + 1, RLENGTH - 2) + if (__nvlen > 0) { + name = __nvnames[__nvlen-1] "/" name + } + + __nvnames[__nvlen] = name + __nvdepth[__nvlen++] = depth +} + +function namevec_Pop() { + delete __nvnames[--__nvlen] + delete __nvdepth[__nvlen] +} |
