使用打印机冒号文件转义序列计算页面宽度
您可以使用打印机冒号文件转义序列计算页面宽度。
IBM® 4029 LaserPrinter 上 ASCII 队列的打印机冒号文件使用工作属性 wW定义页面宽度 (以字符计)。 按照 lsvirprt (请参阅 虚拟打印机定义 以获取更多信息) 命令的格式, wW 定义如下:
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>%Cw 检查命令行中是否使用了 w 标志;如果是,那么将 1 推送到堆栈,否则将 0 推送到堆栈。 在这个例子中,命令行中未使用 w 标志,所以将 0 推送到堆栈。 %t 检查堆栈上是否有为 true(非零)的值,如果未找到,那么执行 %e(else)构造 %I_w。
_w 属性定义为 %IwX,由 lsvirprt 命令格式化,如下所示。
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对 _w 的计算从将 _z 的值(页面方向)推送到堆栈开始。 此示例中使用的作业提交命令 qprt -a1 -Pasc -fp -p12
-scourier -C -N3 /etc/motd指定了 z 值 1,因此会将 1 推送到堆栈上。 %{1} 将另一个 1 推送到堆栈上,之后 %& 会将前两个值 (均为1) 从堆栈中弹出,并对这两个值执行按位 AND 运算。 将按位与 (AND) 操作的结果 1 推送到堆栈。
注意:此测试是按位与 (AND) 操作,而不是测试是否相等的简单测试,这是因为 z 标志的合法值是 0、1、2 和 3,与适用于所打印的页面的 90 度旋转的合法次数相对应。
下一个 %t 在堆栈上找到一个 true(非零)值,因此在进一步解析 _w 之前将解析 then 子句和 %GwK。
按照 lsvirprt的格式, wK 定义如下:
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对 wK 的计算从将 _Q 的值(即为输入纸张来源的纸张大小覆盖)推送到堆栈开始。 _Q 的值定义为 %IwQ。 此时,在 Wk 的计算中,正在 对 wJ 进行计算,即尝试确定 wQ 和 Wu 的值。 在单个作业提交命令的上下文 中,wQ 和 Wu 的最终值将不会改变,因为最终值是从不同的属性计算请求得到的。 由此 可使用先前计算得到的值:将 1 用于 wQ,将 1 用于 Wu。
被返回到正在进行的 wK 计算的 1 是 _Q的值,并 被推送到堆栈。 它将立即从堆栈中弹出并存储在内部变量 Q中。 已确定为 1的 吴将再次推送到堆栈。 %{3} 将 3 推送到堆栈上,然后 %< 会将前两个值 ( 3 和 1) 从堆栈中弹出,并检查弹出的第二个值是否小于弹出的第一个值。 现在 是 1 小于 3,所以将 1 推送到堆栈。 %t 找到 1 ,然后输入 if-then-else-then-else-then-else ... 查找要与为 队列 (_Q)计算的纸张大小值配对的整数的序列。
%gq 从内部变量 q 获取 _Q 的已存储的值,并将其推送到 堆栈。 %{1} 将 1 推送到堆栈。 %= 将顶端 的两个值(两个 1)弹出堆栈,检查它们是否相等,结果相等;那么将 1 推送到堆栈。 %t 找到 1,于是对 %{3200} 求值,从而 将 3200 推送到堆栈。 除了剩余的打印机冒号文件转义序列的最后一行中定义 wK 的内容以外,其他部分中对 wK 的计算都将失败。 最后的转义序列 %d 将顶端的 值 3200 弹出堆栈,并以 ASCII 码的格式将其返回到正在进行的 wX 计算。
返回到正在进行的 wX 计算的 3200 是 wK的值,并 被推送到堆栈。 将跳过 else 子句中的 %GwJ 并且 %; 会终止 if-then-else 序列。 在 wJ 计算的这一点,属性定义的剩余部分将处理影响页面长度(以行数为单位)的因子,例如垂直行密度。 然而 在计算页面宽度时,我们所关心的是字符间距和是否选择了双倍宽度打印。
评估的下一个转义序列为 %G_p。 这将访存 (_P) 属性的值,该属性定义此队列的间距 (以每英寸字符数为单位)。 此队列的缺省值是 10,但此示例中使用的命令行指定字符间距 为 12(-p12),所以将 12 推送到堆栈。 %{17} 将 17 推送到堆栈。 %= 将顶部的两个值(17 和 12)弹出堆栈,并检查它们是否相等,结果不相等;那么将 0 推送到堆栈。 %t 会查找 0 (false 值) ,并对以下 else 子句进行评估。 %G_p 再次将 12 推送到堆栈上。 %{10} 将 10 推送到堆栈。 %* 将顶端的两个 值(一个 12 和一个 10)弹出堆栈,将它们相乘;将得到 的 120 推送到堆栈。 %; 终止这个 if-then-else 序列。
以下 %* 将顶端的两个值(一个 120 和一个 3200)弹出堆栈并将它们相乘;将得到的 384000 推送到堆栈。 %G_W 获取 _W 的 值并将其推送到堆栈;_W 是关系到是否需要双倍宽度打印的“是”(1)或非(0)的问题。 缺省值是 0,不能在命令行覆盖它,所以将 0 推送到堆栈。 %t 找到 0 于是执行 else 子句。 %{3000} 将 3000 推送到堆栈。 %; 终止这个 if-then-else 序列。 以下 %/ 将顶端的两个值(一 个 3000 和一个 384000)弹出堆栈并用第一个弹出的值除第二个弹出的值;将得到 的 128 推送到堆栈。 %d 将顶端的值 128 弹出堆栈并 以 ASCII 码的格式将其返回到正在进行的 wW 的计算中。
返回到 wW 的进行中计算的 128 是 _w的值。 最初在确定 ia 属性 (ASCII 作业的输入数据流管道) 的值时引用了 wW 的值。 数字128取代了%IwW,因此 "pioformat的-!标志值变成了 "/usr/lib/lpd/pio/fmtrs/piof5202 -l48 -w128。 -w128 可以在作为此讨论基础的来自 piobe 的原始诊断消息中看到; 它是 qdaemon 代表 piobe发送的邮件的 PIPELINE OF FILTER 部分的一部分。
以下“页面宽度计算”图描述了用于获取以字符数为单位的页面宽度的最终数值的堆栈操作(如上所述)。 以下编号的步骤对应于图中 各列最左边的数字,并为此特定序列(升序)、冒号文件和命令行定义页面宽度(以字符数为单位)的打印机冒号文件转义序列的求值提供逐步的描述。

- %Cw - 将 0 推送到堆栈,因为在命令行未使用 w 标志。
- %I_w - 调用对 _w 的求值。
- %G_z- 将 1 推送到堆栈。
- %{1} - 将 1 推送到堆栈。
- %& -将前两个值 (两个 1) 从堆栈中弹出,对这两个值执行按位 AND 运算,并将生成的 1 推送到堆栈中。
- %t - 将 1 弹出堆栈,因为这是一个 TRUE(非零)值,所以将调用对 %GwK 的求值。
- %GwK - 调用对 wK 的求值。
- %G_Q - 调用对 _Q 的求值。
- %GwQ - 调用对 wQ 的求值。
- %GWu - 调用对 Wu 的求值。
- %CO - 将 0 推送到堆栈,因为在命令行上未使用 O 标志。
- %t - 将 0 弹出堆栈,因为这是一个 FALSE(零)值,所以将调用对 %G_u 的求值。 标记为 Wu 的堆栈现在为空。
- %G_u - 将 1 推送到堆栈。
- %d - 将 1 弹出堆栈,并以 ASCII 码的格式将其返回到正在进行的 wQ 计算。
- %{0} - 将 0 推送到堆栈。
- %= - 将 0 和 1 弹出堆栈,比较它们是否相等,并将结果 0 推送到堆栈。
- %t - 将 0 弹出堆栈,因为这是一个 FALSE(零)值,所以将调用 对 %GWu 的求值。
- %GWu - 该值已知,所以将 1 推送到堆栈。
- %{1} - 将 1 推送到堆栈。
- %= - 将两个 1 弹出堆栈,比较它们是否相等,并将得到 的 1 推送到堆栈。
- %t - 将 1 弹出堆栈,因为这是一个 TRUE(非零)值,所以将调用对 %Gs1 的求值。
- %Gs1 - 将 1 推送到堆栈。
- %d - 将 1 弹出堆栈并用 ASCII 码的格式将其返回到正在进行 的 wK 计算。
- %Pq - 将 1 弹出堆栈并将其保存在内部变量 q 中。
- %GWu - 该值已知,所以将 1 推送到堆栈。
- %{3} - 将 3 推送到堆栈。
- %< -将前两个值从堆栈中推出 ( 3 和 1) ,并且由于 1 小于 3,因此会将 1 推送到堆栈。
- %t - 将 1 弹出堆栈,并且由于它是 TRUE(非零)值,因此调用对 %pq 的求值。
- %pq - 将内部变量 q 的值(一个 1)推送到堆栈。
- %{1} - 将 1 推送到堆栈。
- %= - 将顶部的两个值(两个 1)弹出堆栈,比较它们是否相等,并将结果 1 推送到堆栈。
- %t - 将 1 弹出堆栈,因为这是 TRUE(非零)值,所以将调用对 %{3200} 的求值。
- %{3200} - 将 3200 推送到堆栈。
- %d - 将 3200 弹出堆栈并将其返回到正在进行的 _w 计算。
- %G_p - 将 12 推送到堆栈。
- %{17} - 将 17 推送到堆栈。
- %= - 将顶部的两个值(17 和 12)弹出堆栈,比较它们是否相等,并将结果 0 推送到堆栈。
- %t - 将 0 弹出堆栈,因为这是一个 FALSE(零)值,所以将调用对 %G_p 的求值。
- %G_p - 将 12 推送到堆栈。
- %{10} - 将 10 推送到堆栈。
- %* - 将顶部的两个值(10 和 12)弹出堆栈,将它们相乘,并将结果 120 推送到堆栈。
- %* - 将顶部的两个值(120 和 3200)弹出堆栈,将它们相乘,并将结果 384000 推送到堆栈。
- %G_w - 将 0 推送到堆栈。
- %t - 将 0 弹出堆栈,因为这是一个 FALSE(零)值,所以将调用 对 %{3000} 的求值。
- %{3000} - 将 3000 推送到堆栈。
- %/ - 将顶部的两个值(3000 和 384000)弹出堆栈,用弹出的第二个值除以弹出的第一个值,并将结果 128 推送到堆栈。
- %d - 将 128 弹出堆栈,并以 ASCII 码格式将其返回到正在进行的 ia 计算,即用于 ASCII 作业的输入数据流管道。