Calculation of page width using printer colon file escape sequences

You can use printer colon file escape sequences to calculate page width.

The printer colon file for an ASCII queue on an IBM® 4029 LaserPrinter defines page width, in characters, with the work attribute wW. As formatted by the lsvirprt (see Virtual printer definitions for more information) command, wW is defined as follows:

 
Page Width In Characters, Using Width From Data Base (used in 
pipelines)
wW = %?%Cw%t%f!w%e%I_w%;
 %?            <IF>
     %Cw       PUSH: (1 If -w Flag on Command Line; Otherwise 0)
 %t            <THEN>
     %f!w      For Each Flag x on Command Line: "-xArgument" -> 
OUTPUT
 %e            <ELSE>
     %I_w      INCLUDE: (COLUMNS per page)
 %;            <END>

The %Cw checks to see if the w flag was used on the command line; if it was, then a 1 is pushed onto the stack, else a 0 is pushed onto the stack. In this case, the w flag was not used on the command line so a 0 is pushed onto the stack. The %t checks for a true (non-zero) value on the stack and, not finding one, executes the %e (else) construct %I_w.

The _w attribute is defined as %IwX, shown below as formatted by the lsvirprt command.

 
Default Page Width (characters)
wX = 
%?%G_z%{1}%&%t%GwK%e%GwJ%;%?%G_p%{17}%=%t%{171}%e%G_p%{10}%*%;%*%
?%G_W%t%{6000}%e%{3000}%;%/%d
 %?            <IF>
     %G_z      PUSH: (Page ORIENTATION)
     %{1}      PUSH: (Integer Constant 1)
     %&        PUSH: (pop2 & pop1) -- Bitwise AND
 %t            <THEN>
     %GwK      PUSH: (Primary Page Length (-z 0) or Secondary 
Page Width (-z
               1), in pels)
 %e            <ELSE>
     %GwJ      PUSH: (Primary Page Width (-z 0) or Secondary Page
Length (-z
               1), in pels)
 %;            <END>
 %?            <IF>
     %G_p      PUSH: (PITCH (characters per inch))
     %{17}     PUSH: (Integer Constant 17)
     %=        PUSH: (pop2 = pop1 ?)
 %t            <THEN>
     %{171}    PUSH: (Integer Constant 171)
 %e            <ELSE>
     %G_p      PUSH: (PITCH (characters per inch))
     %{10}     PUSH: (Integer Constant 10)
     %*        PUSH: (pop2 * pop1)
 %;            <END>
 %*            PUSH: (pop2 * pop1)
 %?            <IF>
     %G_W      PUSH: (DOUBLE-WIDE print?)
 %t            <THEN>
     %{6000}   PUSH: (Integer Constant 6000)
 %e            <ELSE>
     %{3000}   PUSH: (Integer Constant 3000)
 %;            <END>
 %/            PUSH: (pop2 / pop1)
 %d            POP -> ASCII String -> OUTPUT

The calculation of _w begins by pushing the value of _z, page orientation, onto the stack. The job submission command being used in this example, qprt -a1 -Pasc -fp -p12 -scourier -C -N3 /etc/motd, specifies a z value of 1, so a 1 is pushed onto the stack. The %{1} pushes another 1 onto the stack, after which the %& pops the top two values (both1s) off the stack and performs a bitwise AND with the two values. The result of the bitwise AND, a 1, is pushed onto the stack.

Note: The test is a bitwise AND instead of a simple test for equality because the legal values for the z flag are 0, 1, 2, and 3, corresponding to the legal number of 90 degree rotations that can be applied to a printed page.

The next %t finds a true (non-zero) value on the stack and so the then clause, %GwK, is resolved before any more work is done resolving _w.

As formatted by lsvirprt, wK is defined as follows:

 
Primary Page Length (-z 0) or Secondary Page Width (-z 1), in pels
wK = 
%G_Q%Pq%?%GWu%{3}%<%t%?%gq%{1}%=%t%{3200}%e%gq%{2}%=%t%{4100}%e%g
q%{3}%=%t%{2935}%e%gq%{4}%=%t%{3407}%e%{3050}%;%e%?%gq%{1}%=%t%{2
150}%e%gq%{2}%=%t%{2562}%e%gq%{3}%=%t%{2750}%e%gq%{4}%=%t%{2498}%
e%gq%{5}%=%t%{2604}%e%{2852}%;%;%d
 %G_Q          PUSH: (PAPER SIZE override for input paper source)
 %Pq           POP -> Internal Variable q
 %?            <IF>
     %GWu      PUSH: (Calculate value for paper source based on 
_O and _u.)
     %{3}      PUSH: (Integer Constant 3)
     %<        PUSH: (pop2 < pop1 ?)
 %t            <THEN>
     %?        <IF>
         %gq   PUSH: (Internal Variable q)
         %{1}  PUSH: (Integer Constant 1)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{3200}  PUSH: (Integer Constant 3200)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{2}  PUSH: (Integer Constant 2)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{4100}  PUSH: (Integer Constant 4100)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{3}  PUSH: (Integer Constant 3)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2935}  PUSH: (Integer Constant 2935)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{4}  PUSH: (Integer Constant 4)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{3407}  PUSH: (Integer Constant 3407)
     %e        <ELSE>
         %{3050}  PUSH: (Integer Constant 3050)
     %;        <END>
 %e            <ELSE>
     %?        <IF>
         %gq   PUSH: (Internal Variable q)
         %{1}  PUSH: (Integer Constant 1)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2150}  PUSH: (Integer Constant 2150)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{2}  PUSH: (Integer Constant 2)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2562}  PUSH: (Integer Constant 2562)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{3}  PUSH: (Integer Constant 3)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2750}  PUSH: (Integer Constant 2750)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{4}  PUSH: (Integer Constant 4)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2498}  PUSH: (Integer Constant 2498)
     %e        <ELSE>
         %gq   PUSH: (Internal Variable q)
         %{5}  PUSH: (Integer Constant 5)
         %=    PUSH: (pop2 = pop1 ?)
     %t        <THEN>
         %{2604}  PUSH: (Integer Constant 2604)
     %e        <ELSE>
         %{2852}  PUSH: (Integer Constant 2852)
     %;        <END>
 %;            <END>
 %d            POP -> ASCII String -> OUTPUT

The calculation of wK begins by pushing the value of _Q, the paper size override for the input paper source, onto the stack. The value of _Q is defined as %IwQ. At this point in the calculation of Wk, we are exactly where we were in the calculation of wJ, that is, trying to determine a value for wQ and Wu. Within the context of a single job submission command, the final values of wQ and Wu are not going to change just because a final value was requested from a different attribute calculation. Thus we'll use the previously calculated values of 1 for wQ and 1 for Wu.

The 1 returned to the in-progress calculation of wK is the value of _Q, and is pushed onto the stack. It is immediately popped back off the stack and stored in the internal variable q. Wu, already determined to be 1, is again pushed onto the stack. %{3} pushes a 3 onto the stack, then the %< pops the top two values (a 3 and a 1) off the stack and checks to see if the second value popped is less than the first value popped. 1 is less than 3 today, so a 1 is pushed onto stack. The %t find the 1 and so enters the if-then-else-then-else-then-else... sequence looking for an integer to pair with the paper size value calculated for _Q.

The %gq fetches the stored value of _Q from the internal variable q, and pushes it onto the stack. The %{1} pushes a 1 onto the stack. The %= pops the top two values (two 1s) off the stack and, checking them for equality, succeeds; a 1 is pushed onto the stack. The %t finds the 1 and so evaluates the %{3200}, which pushes a 3200 onto the stack. The calculation of wK then falls through all but the last line of the remaining printer colon file escape sequences defining wK. The last escape sequence, %d, pops the top value, 3200, off the stack and returns it, in ASCII format, to the in-progress calculation of wX.

The 3200 returned to the in-progress calculation of wX is the value of wK, and is pushed onto the stack. The %GwJ in the else clause is skipped and the %; terminates the if-then-else sequence. At this point in the calculation of wJ, the remainder of the attribute definition dealt with factors that affected page length (in lines), such as vertical line density. In the calculation of page width, however, we will be interested in pitch and in whether or not double-wide printing was selected.

The next escape sequence evaluated is %G_p. This fetches the value of the _p attribute, which defines the pitch in characters per inch for this queue. The default value for this queue is 10 but the command line being used in this example specified a pitch of 12 (-p12), so a 12 is pushed onto the stack. The %{17} pushes a 17 onto the stack. The %= pops the top two values (a 17 and a 12) off the stack and, checking them for equality, fails; a 0 is pushed onto the stack. The %t finds the 0 (a false value) and the following else clause is evalutated. %G_p again pushes a 12 onto the stack. The %{10} pushes a 10 onto the stack. The %* pops the top two values (a 12 and a 10) off the stack and multiplies them together; the resulting 120 is pushed onto the stack. The %; terminates this if-then-else sequence.

The following %* pops the top two values (a 120 and a 3200) off the stack and multiplies them together; the resulting 384000 is pushed onto the stack. The %G_W fetches the value of _W and pushes it onto the stack; _W is a yes (1) or no (0) question concerning whether or not double-wide printing is needed. The default value is 0 and we did not override it on the command line, so a 0 is pushed onto the stack. The %t finds the 0 and so executes the else clause. The %{3000} pushes a 3000 onto the stack. The %; terminates this if-then-else sequence. The following %/ pops the top two values (a 3000 and a 384000) off the stack and divides the second value popped by the first value popped; the resulting 128 is pushed onto the stack. The %d pops the top value, 128, off the stack and returns it, in ASCII format, to the in-progress calculation of wW.

The 128 returned to the in-progress calculation of wW is the value of _w. The value of wW was originally referenced in the determination of the value of the ia attribute, the input datastream pipeline for ASCII jobs. The number 128 replaces the %IwW in that determination, so the value of the -! flag to pioformat becomes /usr/lib/lpd/pio/fmtrs/piof5202 -l48 -w128. The -w128 can be seen in the original diagnostic message from piobe that was the basis of this discussion; it is part of the PIPELINE OF FILTERS section of the mail sent by the qdaemon on behalf of piobe.

The following "Calculation of Page Width" figure depicts the stacks operations (as described above) used to obtain a final numeric value for page width in characters. The following numbered steps correspond to the numbers on the left side of the columns in the figure, and provide a step-by-step description of the evaluation of the printer colon file escape sequences defining page width, in characters, for this particular queue (asc), colon file, and command line.

Figure 1. Calculation of Page Width
Calculation of Page Width
  1. %Cw - Pushes a 0 onto the stack because the w flag was not used on the command line.
  2. %I_w - Calls for the evaluation of _w.
  3. %G_z - Pushes a 1 onto the stack.
  4. %{1} - Pushes a 1 onto the stack.
  5. %& - Pops the top two values (two 1s) off the stack, performs a bitwise AND on the two values, and pushes the resultant 1 onto the stack.
  6. %t - Pops the 1 off the stack and, because it is a TRUE (non-zero) value, calls for the evaluation of %GwK.
  7. %GwK - Calls for the evaluation of wK.
  8. %G_Q - Calls for the evaluation of _Q.
  9. %GwQ - Calls for the evaluation of wQ.
  10. %GWu - Calls for the evaluation of Wu.
  11. %CO - Pushes a 0 onto the stack because the O flag was not used on the command line.
  12. %t - Pops the 0 off the stack and, because it is a FALSE (zero) value, calls for the evaluation of %G_u. The stack labeled Wu is now empty.
  13. %G_u - Pushes a 1 onto the stack.
  14. %d - Pops the 1 off the stack and returns it, in ASCII format, to the in-progress calculation of wQ.
  15. %{0} - Pushes a 0 onto the stack.
  16. %= - Pops the 0 and 1 off the stack, compares them for equality, and pushes the resultant 0 onto the stack.
  17. %t - Pops the 0 off the stack and, because it is a FALSE (zero) value, calls for the evaluation of %GWu.
  18. %GWu - This value is already known, so a 1 is pushed onto the stack.
  19. %{1} - Pushes a 1 onto the stack.
  20. %= - Pops the two 1s off the stack, compares them for equality, and pushes the resultant 1 onto the stack.
  21. %t - Pops the 1 off the stack and, because it is a TRUE (non-zero) values, calls for the evaluation of %Gs1.
  22. %Gs1 - Pushes a 1 onto the stack.
  23. %d - Pops the 1 off the stack and returns it, in ASCII format, to the in-progress calculation of wK.
  24. %Pq - Pops the 1 off the stack and stores it in the internal variable q.
  25. %GWu - This value is already known, so a 1 is pushed onto the stack.
  26. %{3} - Pushes a 3 onto the stack.
  27. %< - Pops the top two values off the stack (a 3 and a 1) and, because 1 is less than 3, pushes a 1 onto the stack.
  28. %t - Pops the 1 off the stack and, because it is a TRUE (non-zero) value, calls for the evaluation of %pq.
  29. %pq - Pushes the value of the internal variable q, a 1, onto the stack.
  30. %{1} - Pushes a 1 onto the stack.
  31. %= - Pops the top two values (two 1s) off the stack, compares them for equality, and pushes the resultant 1 onto the stack.
  32. %t - Pops the 1 off the stack and, because it is a TRUE (non-zero) value, calls for the evaluation of %{3200}.
  33. %{3200} - Pushes a 3200 onto the stack.
  34. %d - Pops the 3200 off the stack and returns it to the in-progress calculation of _w.
  35. %G_p - Pushes a 12 onto the stack.
  36. %{17} - Pushes a 17 onto the stack.
  37. %= - Pops the top two values (a 17 and a 12) off the stack, compares them for equality, and pushes the resultant 0 onto the stack.
  38. %t - Pops the 0 off the stack and, because it is a FALSE (zero) value, calls for the evaluation of %G_p.
  39. %G_p - Pushes a 12 onto the stack.
  40. %{10} - Pushes a 10 onto the stack.
  41. %* - Pops the top two values (a10 and a 12) off the stack, multiplies them together, and pushes the resultant 120 onto the stack.
  42. %* - Pops the top two values (a 120 and a 3200) off the stack, multiplies them together, and pushes the resultant 384000 onto the stack.
  43. %G_w - Pushes a 0 onto the stack.
  44. %t - Pops the 0 off the stack and, because it is a FALSE (zero) value, calls for the evaluation of %{3000}.
  45. %{3000} - Pushes a 3000 onto the stack.
  46. %/ - Pops the top two values (a 3000 and a 384000) off the stack, divides the second value popped by the first value popped, and pushes the resultant 128 onto the stack.
  47. %d - Pops the 128 off the stack and returns it, in ASCII format, to the in-progress calculation of ia, the input data stream pipeline for ASCII jobs.