home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / AWF.ZIP / PASS1 < prev    next >
Text File  |  1990-12-12  |  5KB  |  213 lines

  1. # first pass:  macro expansion and .if
  2. # We support macros, conditionals (of three quite limited forms), and macro
  3. # argument substitution.
  4. BEGIN {
  5.     curmacro = ""
  6.     macros[""] = 0        # just to make it an array
  7.     macrolen[""] = 0    # just to make it an array
  8.     macrotext[0] = ""    # just to make it an array
  9.     args[""] = ""        # just to make it an array
  10.     ntext = 1        # first slot in macrotext; cannot be 0
  11.     nroffset = 0        # offset between NR and "real" line numbers
  12.     inname = "?"        # input filename
  13.     sp = 0            # stack "pointer" (number of stacked macros)
  14.     maxsp = 25        # limit on nesting depth
  15.     macrostack[sp] = ""    # to make it an array
  16.     nleftstack[sp] = ""    # to make it an array
  17.     ptrstack[sp] = ""    # to make it an array
  18.     nargstack[sp] = ""    # to make it an array
  19.     argstack[sp] = ""    # to make it an array
  20.     condstack[sp] = ""    # to make it an array
  21. }
  22. /^\.\^#/ {            # filename and line no of next line: .^# no fn
  23.     nroffset = (NR+1) - $2
  24.     inname = $3
  25.     print
  26.     next
  27. }
  28. /^\.de/ {            # macro start
  29.     curmacro = "." $2
  30.     macros[curmacro] = ntext
  31.     macrostart = ntext
  32.     next
  33. }
  34. curmacro != "" && $0 !~ /^\.\.$/ {    # macro text - \\ becomes \
  35.     if ($0 !~ /\\/)        # quick case, no backslashes
  36.         line = $0
  37.     else {
  38.         line = ""
  39.         for (n = 1; n <= length; n++) {
  40.             if (substr($0, n, 2) == "\\\\")
  41.                 n++
  42.             line = line substr($0, n, 1)
  43.         }
  44.     }
  45.     macrotext[ntext++] = line
  46.     next
  47. }
  48. curmacro != "" && $0 ~ /^\.\.$/ {    # macro end
  49.     macrolen[curmacro] = ntext - macrostart
  50.     curmacro = ""
  51.     print ".^#", NR - nroffset + 1, inname
  52.     next
  53. }
  54. $0 ~ /^\./ && ( macros[$1] != 0 || $0 ~ /^\.(i[ef]|el)/ ) {
  55.     # something that needs attention
  56.     print ".^=", NR - nroffset, inname
  57.     line = $0
  58.     nleft = 0
  59.     macro = "<none>"
  60.     nargs = 0
  61.  
  62.     while (line != "") {
  63.         # conditionals; note that 1-n is !n (awk doesn't have !)
  64.         invert = 0
  65.         if (line ~ /^\.i[ef] !/)
  66.             invert = 1
  67.         prevcond = cond
  68.         cond = 0
  69.         if (line !~ /^\.(i[ef]|el)/) {        # not conditional
  70.             cond = 1
  71.             iflen = 0
  72.         } else if (line ~ /^\.i[ef] !?\\n\(\.\$[<=>][0-9] /) {
  73.             # arithmetic comparison on arg count
  74.             iflen = length(".if .n(.$=x ") + invert
  75.             n = substr(line, iflen-1, 1) + 0
  76.             op = substr(line, iflen-2, 1)
  77.             if (op == "=" && nargs == n)
  78.                 cond = 1
  79.             else if (op == "<" && nargs < n)
  80.                 cond = 1
  81.             else if (op == ">" && nargs > n)
  82.                 cond = 1
  83.         } else if (line ~ /^\.i[ef] !?'\\\$[0-9]'[^']*' /) {
  84.             # string equality on argument
  85.             iflen = length(".if '.$n'") + invert
  86.             n = substr(line, iflen-1, 1)+0
  87.             if (n <= nargs)
  88.                 s1 = args[n]
  89.             else
  90.                 s1 = ""
  91.             i = index(substr(line, iflen+1), "'")
  92.             s2 = substr(line, iflen+1, i-1)
  93.             iflen += i+1
  94.             if (s1 == s2)
  95.                 cond = 1
  96.         } else if (line ~ /^\.i[ef] !?[nt] /) {
  97.             # nroff vs troff
  98.             iflen = length(".if n ") + invert
  99.             if (substr(line, iflen-1, 1) == "n")
  100.                 cond = 1
  101.         } else if (line ~ /^\.el /) {
  102.             cond = 1 - prevcond
  103.             iflen = length(".el ")
  104.         } else {
  105.             line = ".tm unknown .if/.ie form: " line
  106.             cond = 1
  107.             iflen = 0
  108.         }
  109.         if (invert)
  110.             cond = 1 - cond
  111.         if (cond && iflen > 0)        # trim true conditional off
  112.             line = substr(line, iflen+1)
  113.  
  114.         # do argument substitution, if necessary
  115.         if (cond && line ~ /\\\$/) {
  116.             orig = line
  117.             line = ""
  118.             for (pos = index(orig, "\\$"); pos > 0; \
  119.                         pos = index(orig, "\\$")) {
  120.                 if (pos > 1)
  121.                     line = line substr(orig, 1, pos-1)
  122.                 c = substr(orig, pos+2, 1)
  123.                 if (c ~ /[0-9]/ && c+0 <= nargs)
  124.                     line = line args[c+0]
  125.                 orig = substr(orig, pos+3)
  126.             }
  127.             line = line orig    # the remnant
  128.         }
  129.  
  130.         # is it an nroff command?
  131.         if (cond && line ~ /^\./) {
  132.             cmd = substr(line, 1, 3)
  133.             while (cmd ~ / $/)
  134.                 cmd = substr(cmd, 1, length(cmd)-1)
  135.         } else
  136.             cmd = ""
  137.  
  138.         # deal with it
  139.         if (!cond)
  140.             nop = 0        # nothing
  141.         else if (cmd == "" || macros[cmd] == 0)
  142.             print line    # not a nested macro
  143.         else if (sp >= maxsp)
  144.             print ".tm macros nested too deeply (" sp " levels)"
  145.         else {            # nesting
  146.             # stack old one
  147.             sp++
  148.             nleftstack[sp] = nleft
  149.             ptrstack[sp] = ptr
  150.             macrostack[sp] = macro
  151.             nargstack[sp] = nargs
  152.             condstack[sp] = cond
  153.             for (i = 1; i <= nargs; i++)
  154.                 argstack[sp ":" i] = args[i]
  155.  
  156.             # start new one, mostly pulling arguments apart
  157.             macro = cmd
  158.             nleft = macrolen[macro]
  159.             ptr = macros[macro]
  160.             cond = 0
  161.             argno = 1
  162.             pos = length(macro) + 1
  163.             for (;;) {
  164.                 while (substr(line, pos, 1) ~ /[ \t]/)
  165.                     pos++
  166.                 if (pos > length(line))
  167.                     break        # NOTE BREAK OUT
  168.                 arg = ""
  169.                 if (substr(line, pos, 1) == "\"") {
  170.                     pos++
  171.                     while (substr(line, pos, 1) ~ /[^"]/) {
  172.                         arg = arg substr(line, pos, 1)
  173.                         pos++
  174.                     }
  175.                     pos++
  176.                 } else
  177.                     while (substr(line, pos, 1) ~ /[^ \t]/) {
  178.                         arg = arg substr(line, pos, 1)
  179.                         pos++
  180.                     }
  181.                 args[argno++] = arg
  182.             }
  183.             nargs = argno - 1
  184.         }
  185.  
  186.         # clean up any completed macros
  187.         while (nleft <= 0 && sp > 0) {
  188.             nleft = nleftstack[sp]
  189.             ptr = ptrstack[sp]
  190.             macro = macrostack[sp]
  191.             nargs = nargstack[sp]
  192.             cond = condstack[sp]
  193.             for (i = 1; i <= nargs; i++)
  194.                 args[i] = argstack[sp ":" i]
  195.             sp--
  196.         }
  197.  
  198.         # finally, get next line
  199.         if (nleft > 0) {
  200.             line = macrotext[ptr++]
  201.             nleft--
  202.         } else
  203.             line = ""    # signal loop to terminate
  204.     }
  205.  
  206.     print ".^#", NR - nroffset + 1, inname
  207.     next
  208. }
  209. {
  210.     # it's ordinary
  211.     print
  212. }
  213.