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

  1. # second pass:  interpretation of directives
  2. # A macro-set-specific portion gets interpolated into this at the "#include"
  3. # line.  As a minimum, it must deal with .^b and .^e and with any input traps.
  4. BEGIN {
  5.     # stuff for output to third pass
  6.     nobreak = -1
  7.     dobreak = -2
  8.     message = -3
  9.     OFS = "\t"
  10.  
  11.     # special-character table; this one character needs to be hardcoded
  12.     chars[" "] = " " ; charwidths[" "] = 1
  13.  
  14.     debug["e"] = 0        # just to make it an array
  15.     strings["a"] = ""    # just to make it an array
  16.     numbers["a"] = 0    # just to make it an array
  17.     hyphens["a"] = ""    # just to make it an array
  18.     hyphenwidths["a"] = ""    # just to make it an array
  19.  
  20.     # stuff for expression decoding
  21.     signfactor["+"] = 1
  22.     signfactor["-"] = -1
  23.     scale["i"] = 240
  24.     scale["c"] = 240*50/127
  25.     scale["P"] = 240/6
  26.     # we get m, n, and v when we see .^r
  27.     scale["p"] = 240/72
  28.     scale["u"] = 1
  29.  
  30.     # stuff for basic parameters that just get passed to third pass
  31.     parms["in"] = 0        # just to make it an array
  32.     prevparms["in"] = 0    # just to make it an array
  33.     setcmd["ll"] = "linelen"
  34.     setcmd["in"] = "indent"
  35.     setcmd["ti"] = "tempindent"
  36.     setcmd["po"] = "pageoffset"
  37.     setcmd["pl"] = "pagelen"
  38.  
  39.     # did last word end with \c ?  (in which case, it's still in "word")
  40.     backc = 0
  41.  
  42.     # stuff for error reporting
  43.     il = 0            # input line number
  44.     lockil = 0        # il is locked, we're inside a macro
  45.     inname = "?"        # input filename
  46.     msg = message "\t"    # later picks up filename etc.
  47.  
  48.     # current input trap
  49.     afternext = ""
  50. }
  51. {
  52.     if (!lockil)
  53.         il++
  54.     msg = message "\t" inname "," il ": "
  55.     # fallthrough
  56. }
  57. /^[ \t]*$/ {            # empty line
  58.     print dobreak, "space"
  59.     next
  60. }
  61. /^[ \t]/ {            # line starting with white space
  62.     print dobreak, "flush"
  63.     print 0, ""        # empty word
  64.     # fallthrough
  65. }
  66. /^[^.]/ {            # text
  67.     # dispose of the easy case
  68.     if (font == "R" && $0 !~ /\\|\t|-|  / && !backc && afternext == "") {
  69.         for (i = 1; i <= NF; i++)
  70.             print length($i), $i
  71.         if ($0 ~ /[.!?:][\])'"*]*$/)
  72.             print nobreak, "gap", 2
  73.         if (centering > 0) {
  74.             print dobreak, "center"
  75.             centering--
  76.         } else if (!fill)
  77.             print dobreak, "flush"
  78.         next
  79.     }
  80.  
  81.     # the hard case, needs a character-by-character scan
  82.     s = $0 " "        # the space flushes the last word
  83.     n = 1            # current position in s
  84.     inword = 0        # have we been processing a word?
  85.     period = ""        # "." if this word ended a sentence
  86.     nsp = 0            # count of spaces seen so far
  87.     tabpos = 0        # which tab position was used last
  88.     while (n <= length(s)) {
  89.         c = substr(s, n, 1)
  90.  
  91.         # handle state transitions
  92.         if (c == " " || c == "\t") {
  93.             if (inword) {        # ends word
  94.                 if (!backc) {
  95.                     print wordlen, word
  96.                     if (usedhyphen)
  97.                         print nobreak, "nohyphen"
  98.                 }
  99.                 inword = 0
  100.                 nsp = 0
  101.             }
  102.         } else {
  103.             if (!inword) {        # begins word
  104.                 if (!backc) {
  105.                     word = ""
  106.                     wordlen = 0
  107.                     usedhyphen = 0
  108.                 }
  109.                 backc = 0
  110.                 inword = 1
  111.                 if (nsp > 1)
  112.                     print nobreak, "gap", nsp
  113.             }
  114.         }
  115.  
  116.         # deal with the character
  117.         if (c == " ") {
  118.             nsp++
  119.             if (n != length(s))    # not the trailing flusher
  120.                 period = ""
  121.         } else if (c == "\t") {
  122.             # not really right, should be based on input position
  123.             # also, one space following tab gets ignored
  124.             tabpos++
  125.             if (tabpos <= ntabs)
  126.                 print nobreak, "tabto", tabs[tabpos]
  127.             nsp = 0
  128.             period = ""
  129.         } else if (c == "-" && wordlen > 0) {
  130.             # hyphen within word
  131.             print wordlen, word, hyphenwidths[font]
  132.             print nobreak, "userhyphen", hyphens[font], hyphenwidths[font]
  133.             word = ""
  134.             wordlen = 0
  135.             period = ""
  136.             usedhyphen = 1
  137.         } else if (c != "\\") {
  138.             # ordinary character
  139.             if (font == "B")
  140.                 word = word c "\b" c "\b" c
  141.             else if (font == "I" && c ~ /[a-zA-Z0-9]/)
  142.                 word = word "_\b" c
  143.             else
  144.                 word = word c
  145.             wordlen++
  146.             if (c ~ /[.!?:]/)
  147.                 period = "."
  148.             else if (c !~ /[\])'"*]/)
  149.                 period = ""
  150.         } else {            # backslash
  151.             n++
  152.             c = substr(s, n, 1)
  153.             if (c == "f") {
  154.                 # font change
  155.                 n++
  156.                 code = substr(s, n, 1)
  157.                 if (code == "(") {
  158.                     n++
  159.                     code = substr(s, n, 2)
  160.                     n++
  161.                 }
  162.                 if (code == "P")
  163.                     font = prevfont
  164.                 else if (fontok[code] == "")
  165.                     print msg "unknown font `" code "'"
  166.                 else {
  167.                     prevfont = font
  168.                     font = code
  169.                 }
  170.             } else if (c == "n") {
  171.                 # number-register value
  172.                 n++
  173.                 code = substr(s, n, 1)
  174.                 if (code == "(") {
  175.                     n++
  176.                     code = substr(s, n, 2)
  177.                     n++
  178.                 }
  179.                 s = substr(s, 1, n) numbers[code] substr(s, n+1)
  180.             } else if (c == "s") {
  181.                 # size change
  182.                 n++
  183.                 if (substr(s, n, 1) ~ /[0-9]/)
  184.                     n++
  185.                 # just ignore it
  186.             } else if (c == "c")
  187.                 # word continuation
  188.                 backc = 1
  189.             else if (c == "*") {
  190.                 # string-variable value
  191.                 n++
  192.                 code = substr(s, n, 1)
  193.                 if (code == "(") {
  194.                     n++
  195.                     code = substr(s, n, 2)
  196.                     n++
  197.                 }
  198.                 s = substr(s, 1, n) strings[code] substr(s, n+1)
  199.             } else if (c == "%") {
  200.                 # discretionary hyphen
  201.                 if (wordlen > 0) {
  202.                     print wordlen, word, hyphenwidths[font]
  203.                     print nobreak, "hyphen", hyphens[font], hyphenwidths[font]
  204.                     word = ""
  205.                     wordlen = 0
  206.                     usedhyphen = 1
  207.                 }
  208.             } else if (c == "(" && substr(s, n+1, 2) == "em" && \
  209.                             chars["em"] != "") {
  210.                 # em-dash, special case due to hyphenation
  211.                 n += 2
  212.                 emw = charwidths["em"]
  213.                 print wordlen, word, emw
  214.                 print nobreak, "userhyphen", chars["em"], emw
  215.                 word = ""
  216.                 wordlen = 0
  217.                 period = ""
  218.                 usedhyphen = 1
  219.             } else {
  220.                 # special-character name
  221.                 code = c
  222.                 if (code == "(") {
  223.                     n++
  224.                     code = substr(s, n, 2)
  225.                     n++
  226.                 }
  227.                 word = word chars[code]
  228.                 wordlen += charwidths[code]
  229.                 period = ""
  230.             }
  231.         }
  232.  
  233.         # on to the next character, at last
  234.         n++
  235.     }
  236.  
  237.     # end-of-line processing
  238.     if (!backc) {
  239.         if (period == ".")
  240.             print nobreak, "gap", 2
  241.         if (centering > 0) {
  242.             print dobreak, "center"
  243.             centering--
  244.         } else if (!fill)
  245.             print dobreak, "flush"
  246.     }
  247.  
  248.     # if no input trap, we're done
  249.     if (afternext == "")
  250.         next
  251.  
  252.     # if there is an input trap, fall into the macro-dependent section
  253. }
  254. #
  255. #
  256. #
  257. # at this point we plug in the macro-specific stuff, keyed on the next line
  258. #include            note that this is an awk comment
  259. #
  260. #
  261. #
  262. /^\.it/ {            # plant an input trap, sort of
  263.     if (NF > 1 && $2 != 1)
  264.         print msg ".it first argument must be 1"
  265.     if (NF > 2)
  266.         afternext = afternext "," $3
  267.     else
  268.         afternext = ""
  269.     next
  270. }
  271. /^\.\^r cpi / {            # set resolutions, in cpi:  .^r cpi hor vert
  272.     scale["m"] = 240/$3
  273.     scale["n"] = 240/$3
  274.     scale["v"] = 240/$4
  275.     next
  276. }
  277. /^\.(ta|ll|in|ti|po|ne|sp|pl|nr)/ {    # expression processing
  278.     # sort out default scale factor
  279.     if ($1 ~ /^\.(ne|sp|pl)/)
  280.         exprscale = "v"
  281.     else if ($1 ~ /^\.(nr)/)
  282.         exprscale = "u"
  283.     else
  284.         exprscale = "n"
  285.  
  286.     # which argument should we start with?
  287.     offset = length($1) + 1
  288.     if ($1 == ".nr")
  289.         offset += length($2) + 1
  290.  
  291.     # beginning of debugging message
  292.     if (debug["e"])
  293.         printf "%s ", msg substr($0, 1, offset)
  294.  
  295.     # do the expressions
  296.     s = substr($0, offset+1)
  297.     n = 1
  298.     while (s != "") {
  299.         while (s ~ /^[ \t]/)
  300.             s = substr(s, 2)
  301.  
  302.         # an initial sign is magic
  303.         ssign = ""
  304.         if (s ~ /^[+-]/) {
  305.             ssign = substr(s, 1, 1)
  306.             s = substr(s, 2)
  307.         }
  308.         s = "+" s    # this is an un-magic addition operator
  309.  
  310.         # process terms
  311.         sval = 0
  312.         # there is no portable way to put a slash in a regexp
  313.         while (s ~ /^[+*%)-]/ || substr(s, 1, 1) == "/") {
  314.             # figure out what it is and what it contributes
  315.             if (debug["e"] > 1)
  316.                 print "s=`" s "'"
  317.             termop = substr(s, 1, 1)
  318.             s = substr(s, 2)
  319.             termscale = exprscale
  320.             if (termop == ")") {
  321.                 if (debug["e"] > 1)
  322.                     print "pop " valstack[vsp] " " opstack[vsp] " with " sval
  323.                 termval = sval
  324.                 sval = valstack[vsp]
  325.                 termop = opstack[vsp]
  326.                 vsp--
  327.                 termscale = "u"
  328.             } else if (s ~ /^\(/) {
  329.                 if (debug["e"] > 1)
  330.                     print "push " sval " " termop
  331.                 vsp++
  332.                 valstack[vsp] = sval
  333.                 opstack[vsp] = termop
  334.                 sval = 0
  335.                 termop = "+"    # dummy op and value
  336.                 termval = 0
  337.                 s = "+" substr(s, 2)
  338.             } else if (s ~ /^\\w/) {
  339.                 delim = substr(s, 3, 1)
  340.                 s = substr(s, 4)
  341.                 endp = index(s, delim)
  342.                 if (endp == 0)
  343.                     endp = length(s) + 1
  344.                 termval = (endp - 1) * scale["n"]    # crude
  345.                 s = substr(s, endp+1)
  346.             } else if (s ~ /^\\n/) {
  347.                 if (s ~ /^\\n\(/) {
  348.                     code = substr(s, 4, 2)
  349.                     s = substr(s, 6)
  350.                 } else {
  351.                     code = substr(s, 3, 1)
  352.                     s = substr(s, 4)
  353.                 }
  354.                 termval = numbers[code]
  355.             } else if (s ~ /^[0-9.]/) {
  356.                 for (endp = 1; endp <= length(s); endp++)
  357.                     if (substr(s, endp, 1) !~ /[0-9.]/)
  358.                         break
  359.                 termval = substr(s, 1, endp-1) + 0
  360.                 s = substr(s, endp)
  361.             }
  362.  
  363.             # add it in, with scaling factor
  364.             c = substr(s, 1, 1)
  365.             if (scale[c] != "") {
  366.                 termval *= scale[c]
  367.                 s = substr(s, 2)
  368.             } else
  369.                 termval *= scale[termscale]
  370.             if (termop == "+")
  371.                 sval += termval
  372.             else if (termop == "-")
  373.                 sval -= termval
  374.             else if (termop == "*")
  375.                 sval *= termval
  376.             else if (termop == "/")
  377.                 sval = int(sval) / int(termval)
  378.             else if (termop == "%")
  379.                 sval = int(sval) % int(termval)
  380.         }
  381.  
  382.         # remember the value, print if debugging
  383.         expr[n] = sval
  384.         exprsign[n] = ssign
  385.         iexpr[n] = signfactor[ssign] * sval    # convenience
  386.         if (debug["e"])
  387.             printf "%s ", ssign "(" sval ")"
  388.  
  389.         # proceed to next, skipping trash if necessary
  390.         while (s ~ /^[^ \t]/)
  391.             s = substr(s, 2)
  392.         n++
  393.     }
  394.  
  395.     # final cleanup
  396.     nexprs = n - 1
  397.     if (debug["e"])
  398.         printf "\n"
  399.  
  400.     # fallthrough
  401. }
  402. /^\.(ll|in|ti|po|pl)/ {        # common code for set-parameter requests
  403.     # relies on expression processing, including setting of exprscale
  404.     name = substr($1, 2, 2)
  405.     n = parms[name]
  406.     if (nexprs == 0)
  407.         n = prevparms[name]
  408.     else if (exprsign[1] == "" || name == "ti")
  409.         n = expr[1] / scale[exprscale]
  410.     else
  411.         n += iexpr[1] / scale[exprscale]
  412.     prevparms[name] = parms[name]
  413.     parms[name] = int(n)
  414.     print dobreak, setcmd[name], parms[name]
  415.     next
  416. }
  417. /^\.nr/ {
  418.     # relies on expression processing
  419.     n = numbers[$2]
  420.     if (exprsign[1] == "")
  421.         n = expr[1]
  422.     else
  423.         n += iexpr[1]
  424.     numbers[$2] = int(n)
  425.     next
  426. }
  427. /^\.ne/ {
  428.     # relies on expression processing
  429.     print dobreak, "need", int(expr[1]/scale["v"] + 0.99)
  430.     next
  431. }
  432. /^\.sp/ {
  433.     # relies on expression processing
  434.     if (nexprs == 0)
  435.         i = 1
  436.     else
  437.         i = int(expr[1]/scale["v"] + 0.99)
  438.     for (; i > 0; i--)
  439.         print dobreak, "space"
  440.     next
  441. }
  442. /^\.ta/ {
  443.     # relies on expression processing
  444.     tabstop = 0
  445.     for (n = 1; n <= nexprs; n++) {
  446.         if (exprsign[n] == "")
  447.             tabstop = expr[n]
  448.         else
  449.             tabstop += iexpr[n]
  450.         tabs[n] = int(tabstop/scale["n"])
  451.     }
  452.     ntabs = nexprs
  453.     next
  454. }
  455. /^\.ft/ {
  456.     if (NF > 1)
  457.         code = $2
  458.     else
  459.         code = "P"
  460.  
  461.     if (code == "P")
  462.         font = prevfont
  463.     else if (fontok[code] == "")
  464.         print msg "unknown font `" code "'"
  465.     else {
  466.         prevfont = font
  467.         font = code
  468.     }
  469.     next
  470. }
  471. /^\.br/ {
  472.     print dobreak, "flush"
  473.     next
  474. }
  475. /^\.ds/ {
  476.     # note, macro-set-specific code often looks at .ds as well
  477.     if ($3 !~ /^"/)
  478.         strings[$2] = $3
  479.     else
  480.         strings[$2] = substr($0, index($0, "\"")+1)
  481.     next
  482. }
  483. /^\.ns/ {
  484.     print nobreak, "nospace"
  485.     next
  486. }
  487. /^\.rs/ {
  488.     print nobreak, "yesspace"
  489.     next
  490. }
  491. /^\.ad/ {
  492.     print nobreak, "both"
  493.     next
  494. }
  495. /^\.na/ {
  496.     print nobreak, "left"
  497.     next
  498. }
  499. /^\.nf/ {
  500.     fill = 0
  501.     print dobreak, "flush"
  502.     next
  503. }
  504. /^\.fi/ {
  505.     fill = 1
  506.     print dobreak, "flush"
  507.     next
  508. }
  509. /^\.\^x/ {            # direct errors to this file:  .^x filename
  510.     print nobreak, "errsto", $2
  511.     next
  512. }
  513. /^\.\^c/ {            # define character:  .^c name width text
  514.     if ($4 ~ /^"/)
  515.         s = substr($0, index($0, "\"")+1)
  516.     else
  517.         s = $4
  518.     ns = ""
  519.     while ((n = index(s, "\\")) > 0) {
  520.         if (n > 1)
  521.             ns = ns substr(s, 1, n-1)
  522.         n++
  523.         c = substr(s, n, 1)
  524.         if (c == "\\")
  525.             ns = ns "\\"
  526.         else if (c == "b")
  527.             ns = ns "\b"
  528.         s = substr(s, n+1)
  529.     }
  530.     ns = ns s
  531.     if ($2 == "hy") {
  532.         hyphens[font] = ns
  533.         hyphenwidths[font] = $3
  534.     } else {
  535.         chars[$2] = ns
  536.         charwidths[$2] = $3
  537.     }
  538.     next
  539. }
  540. /^\.\^f/ {            # this font is okay:  .^f fontname
  541.     # someday, this might take font-change codes as further arguments
  542.     fontok[$2] = "yes"
  543.     next
  544. }
  545. /^\.tm/ {
  546.     print msg $0
  547.     next
  548. }
  549. /^\.ps/ {
  550.     # ignore
  551.     next
  552. }
  553. /^\.ce/ {
  554.     if (NF > 1)
  555.         centering = $2
  556.     else
  557.         centering = 1
  558.     next
  559. }
  560. /^\.bp/ {
  561.     print dobreak, "need", 999
  562.     next
  563. }
  564. /^\.\^d/ {            # debug control:  .^d debugvar value
  565.     debug[$2] = $3
  566.     next
  567. }
  568. /^\.\^#/ {            # set line number of next line: .^# no file
  569.     il = $2 - 1
  570.     lockil = 0
  571.     inname = $3
  572.     next
  573. }
  574. /^\.\^=/ {            # lock line number to value:  .^= no file
  575.     il = $2
  576.     lockil = 1
  577.     inname = $3
  578.     next
  579. }
  580. /^\.\\"/ {            # comment
  581.     next
  582. }
  583. /^\./ {
  584.     print msg "command `" $1 "' unsupported or unknown"
  585. }
  586. END {
  587.     print dobreak, "need", 999    # flush page
  588. }
  589.