home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / gs403osk.tgz / gs403osk.tar / gs_setpd.ps < prev    next >
Text File  |  1996-10-21  |  21KB  |  638 lines

  1. %    Copyright (C) 1994, 1996 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % The current implementation of setpagedevice has the following limitations:
  16. %   - It doesn't attempt to "interact with the user" for Policy = 2.
  17. % jw note -- this file hacked - gs_setpd.ps.bak in this directory is
  18. % the original version.  Search jw for hacks.  
  19.  
  20. languagelevel 1 .setlanguagelevel
  21. level2dict begin
  22.  
  23. % ---------------- Redefinitions ---------------- %
  24.  
  25. % Redefine .beginpage and .endpage so that they call BeginPage and
  26. % EndPage respectively if appropriate.
  27.  
  28. /.beginpage
  29.  { .currentshowpagecount
  30.     { .currentpagedevice pop /BeginPage .knownget { exec } { pop } ifelse }
  31.    if
  32.  } bind odef
  33.  
  34. /.endpage
  35.  { .currentshowpagecount
  36.     { exch .currentpagedevice pop /EndPage .knownget
  37.        { exec }
  38.        { exch pop 2 ne }
  39.       ifelse
  40.     }
  41.     { 2 ne
  42.     }
  43.    ifelse
  44.  } bind odef
  45.  
  46. % Define interpreter callouts for handling gstate-saving operators,
  47. % to make sure that they create a page device dictionary for use by
  48. % the corresponding gstate-restoring operator.
  49. % We'd really like to avoid the cost of doing this, but we don't see how.
  50. % The names %gsavepagedevice, %savepagedevice, %gstatepagedevice,
  51. % %copygstatepagedevice, and %currentgstatepagedevice are known to the
  52. % interpreter.
  53.  
  54. (%gsavepagedevice) cvn
  55.  { currentpagedevice pop gsave
  56.  } bind def
  57.  
  58. (%savepagedevice) cvn
  59.  { currentpagedevice pop save
  60.  } bind def
  61.  
  62. (%gstatepagedevice) cvn
  63.  { currentpagedevice pop gstate
  64.  } bind def
  65.  
  66. (%copygstatepagedevice) cvn
  67.  { currentpagedevice pop copy
  68.  } bind def
  69.  
  70. (%currentgstatepagedevice) cvn
  71.  { currentpagedevice pop currentgstate
  72.  } bind def
  73.  
  74. % Define interpreter callouts for handling gstate-restoring operators
  75. % when the current page device needs to be changed.
  76. % The names %grestorepagedevice, %grestoreallpagedevice,
  77. % %restorepagedevice, and %setgstatepagedevice are known to the interpreter.
  78.  
  79. /.installpagedevice
  80.  {  % Since setpagedevice doesn't create new device objects,
  81.     % we must (carefully) reinstall the old parameters in
  82.     % the same device.
  83.    .currentpagedevice pop null currentdevice null .trysetparams
  84.    dup type /booleantype eq
  85.     { pop pop }
  86.     {       % This should never happen!
  87.       DEBUG { (Error in .trysetparams!\n) print pstack flush } if
  88.       cleartomark pop pop pop
  89.       /.installpagedevice cvx /rangecheck signalerror
  90.     }
  91.    ifelse pop pop
  92.    erasepage initgraphics .beginpage
  93.  } bind def
  94.  
  95. /.uninstallpagedevice
  96.  { 2 .endpage { .currentnumcopies false .outputpage } if
  97.    nulldevice
  98.  } bind def
  99.  
  100. (%grestorepagedevice) cvn
  101.  { .uninstallpagedevice grestore .installpagedevice
  102.  } bind def
  103.  
  104. (%grestoreallpagedevice) cvn
  105.  { .uninstallpagedevice grestore .installpagedevice grestoreall
  106.  } bind def
  107.  
  108. (%restorepagedevice) cvn
  109.  { .uninstallpagedevice grestore .installpagedevice restore
  110.  } bind def
  111.  
  112. (%setgstatepagedevice) cvn
  113.  { .uninstallpagedevice setgstate .installpagedevice
  114.  } bind def
  115.  
  116. % Redefine .currentnumcopies so it consults the NumCopies device parameter.
  117. /.numcopiesdict mark
  118.   /NumCopies dup
  119. .dicttomark readonly def
  120.  
  121. /.currentnumcopies
  122.  { currentdevice //.numcopiesdict .getdeviceparams
  123.    dup type /integertype eq
  124.     { exch pop exch pop }
  125.     { cleartomark #copies }
  126.    ifelse
  127.  } bind odef
  128.  
  129. % ---------------- Auxiliary definitions ---------------- %
  130.  
  131. % Define the required attributes of all page devices, and their default values.
  132. % We don't include attributes such as .MediaSize, which all devices
  133. % are guaranteed to supply on their own.
  134. /.defaultpolicies mark
  135.   /PolicyNotFound 1
  136.   /PageSize 0
  137.   /PolicyReport {pop} bind
  138. .dicttomark readonly def
  139. /.requiredattrs mark
  140.   /PageOffset [0 0] readonly
  141. % We define InputAttributes and OutputAttributes with a single
  142. % dummy media type that handles pages of any size.
  143. % Devices that care will override this.
  144.   /InputAttributes mark 0
  145.     mark /PageSize [0 dup 16#7ffff dup] .dicttomark readonly
  146.   .dicttomark readonly
  147.   (%MediaSource) 0
  148.   /OutputAttributes mark 0
  149.     mark .dicttomark readonly
  150.   .dicttomark readonly
  151.   (%MediaDestination) 0
  152.   /Install {.callinstall} bind
  153.   /BeginPage {.callbeginpage} bind
  154.   /EndPage {.callendpage} bind
  155.   /Policies .defaultpolicies
  156. .dicttomark readonly def
  157.  
  158. % Define currentpagedevice so it creates the dictionary on demand if needed,
  159. % adding all the required entries defined just above.
  160. % We have to deal specially with entries that the driver may change
  161. % on its own.
  162. /.dynamicppkeys mark
  163.   /.MediaSize dup       % because it changes when PageSize is set
  164.   /PageCount dup
  165. .dicttomark readonly def
  166. /.makecurrentpagedevice     % - .makecurrentpagedevice <dict>
  167.  { currentdevice null .getdeviceparams
  168.     % In case of duplicate keys, .dicttomark takes the entry
  169.     % lower on the stack, so we can just append the defaults here.
  170.    .requiredattrs { } forall .dicttomark
  171.    dup .setpagedevice
  172.  } bind def
  173. /currentpagedevice
  174.  { .currentpagedevice
  175.     { dup length 0 eq
  176.        { pop .makecurrentpagedevice
  177.        }
  178.        {    % If any of the dynamic keys have changed,
  179.         % we must update the page device dictionary.
  180.      currentdevice //.dynamicppkeys .getdeviceparams .dicttomark
  181.       { % Stack: current key value
  182.         2 index 2 index .knownget { 1 index ne } { true } ifelse
  183.          { 2 index wcheck not
  184.         {   % This is the first entry being updated.
  185.             % Copy the dictionary to make it writable.
  186.           3 -1 roll dup length dict .copydict
  187.           3 1 roll
  188.         }
  189.            if
  190.            2 index 3 1 roll put
  191.          }
  192.          { pop pop
  193.          }
  194.         ifelse
  195.       }
  196.      forall
  197.         % We would like to do a .setpagedevice so we don't keep
  198.         % re-creating the dictionary.  Unfortunately, the effect
  199.         % of this is that if any dynamic key changes (PageCount
  200.         % in particular), we will do the equivalent of a
  201.         % setpagedevice at the next restore or grestore.
  202.         % Therefore, we make the dictionary read-only, but
  203.         % we don't store it away.  I.e., NOT:
  204.         % dup wcheck { .setpagedevice .currentpagedevice pop } if
  205.      readonly
  206.        }
  207.       ifelse
  208.     }
  209.    if
  210.  } bind odef
  211.  
  212. % The implementation of setpagedevice is quite complex.  Currently,
  213. % everything but the media matching algorithm is implemented here.
  214.  
  215. % By default, we only present the requested changes to the device,
  216. % but there are some parameters that require special merging action.
  217. % Define those parameters here, with the procedures that do the merging.
  218. % The procedures are called as follows:
  219. %   <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
  220. /.mergespecial mark
  221.   /InputAttributes
  222.    { dup null eq
  223.       { pop null
  224.       }
  225.       { 3 copy pop .knownget
  226.      { dup null eq
  227.         { pop dup length dict }
  228.         { dup length 2 index length add dict .copydict }
  229.        ifelse
  230.      }
  231.      { dup length dict
  232.      }
  233.         ifelse .copydict readonly
  234.       }
  235.      ifelse
  236.    } bind
  237.   /OutputAttributes 1 index
  238.   /Policies
  239.     { 3 copy pop .knownget
  240.        { dup length 2 index length add dict .copydict }
  241.        { dup length dict }
  242.       ifelse copy readonly
  243.     } bind
  244. .dicttomark readonly def
  245.  
  246. % Define the keys used in input attribute matching.
  247. /.inputattrkeys [
  248.   /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
  249. ] readonly def
  250. % Define other keys used in media selection.
  251. /.inputselectionkeys [
  252.   /MediaPosition /Orientation
  253. ] readonly def
  254.  
  255. % Define the keys used in output attribute matching.
  256. /.outputattrkeys [
  257.   /OutputType
  258. ] readonly def
  259.  
  260. % Define all the parameters that should always be copied to the merged
  261. % dictionary.
  262. /.copiedkeys [
  263.   /OutputDevice
  264.   .mergespecial { pop } forall
  265.   .inputattrkeys aload pop
  266.   .inputselectionkeys aload pop
  267.   .outputattrkeys aload pop
  268. ] readonly def
  269.  
  270. % Define the parameters that should not be presented to the device.
  271. % The procedures are called as follows:
  272. %   <merged> <key> <value> -proc-
  273. % The procedure leaves all its operands on the stack and returns
  274. % true iff the key/value pair should be presented to .putdeviceparams.
  275. /.presentspecial mark
  276.   .dynamicppkeys { pop false } forall
  277.             % We must ignore an explicit request for .MediaSize,
  278.             % because media matching always handles this.
  279.   /.MediaSize false
  280.   /Name false
  281.   /OutputDevice false
  282.   /PageOffset false
  283.   /PageSize false       % obsolete alias for .MediaSize
  284.   /InputAttributes false
  285.   .inputattrkeys
  286.     { dup /PageSize eq
  287.        { pop }
  288.        { { 2 index /InputAttributes .knownget { null eq } { true } ifelse } }
  289.       ifelse
  290.     }
  291.   forall
  292.   .inputselectionkeys { false } forall
  293.   /OutputAttributes false
  294.   .outputattrkeys
  295.     { { 2 index /OutputAttributes .knownget { null eq } { true } ifelse } }
  296.   forall
  297.   /Install false
  298.   /BeginPage false
  299.   /EndPage false
  300.   /Policies false
  301.     % Our extensions:
  302.   /HWColorMap
  303.     {           % HACK: don't transmit the color map, because
  304.             % window systems can change the color map on their own
  305.             % incrementally.  Someday we'll have a better
  306.             % solution for this....
  307.       false
  308.     }
  309.   /ViewerPreProcess false
  310. .dicttomark readonly def
  311.  
  312. % Define access to device defaults.
  313. /.defaultdeviceparams
  314.  { finddevice null .getdeviceparams
  315.  } bind def
  316.  
  317. % Select media (input or output).  The hard work is done in an operator:
  318. %   <pagedict> <attrdict> <policydict> <keys> .matchmedia <key> true
  319. %   <pagedict> <attrdict> <policydict> <keys> .matchmedia false
  320. %   <pagedict> null <policydict> <keys> .matchmedia null true
  321. /.selectmedia       % <orig> <request> <merged> <failed>     <-- retained
  322.             %   <attrdict> <policydict> <attrkeys> <mediakey>
  323.             %   .selectmedia
  324.  { 5 index 5 -2 roll 4 index .matchmedia
  325.         % Stack: orig request merged failed attrkeys mediakey
  326.         %   (key true | false)
  327.     { 4 index 3 1 roll put pop
  328.     }
  329.     {   % Adobe's implementations have a "big hairy heuristic"
  330.     % to choose the set of keys to report as having failed the match.
  331.     % For the moment, we report any keys that are in the request
  332.     % and don't have the same value as in the original dictionary.
  333.       5 index 1 index .knownget
  334.        { 4 index 3 1 roll put }
  335.        { 3 index exch .undef }
  336.       ifelse
  337.        {    % Stack: <orig> <request> <merged> <failed> <attrkey>
  338.      3 index 1 index .knownget
  339.       { 5 index 2 index .knownget { ne } { pop true } ifelse }
  340.       { true }
  341.      ifelse     % Stack: ... <failed> <attrkey> <report>
  342.       { 2 copy /rangecheck put }
  343.      if pop
  344.        }
  345.       forall
  346.     }
  347.    ifelse
  348.  } bind def
  349.  
  350. % Apply Policies to any unprocessed failed requests.
  351. % As we process each request entry, we replace the error name
  352. % in the <failed> dictionary with the policy value,
  353. % and we replace the key in the <merged> dictionary with its prior value
  354. % (or remove it if it had no prior value).
  355. /.applypolicies     % <orig> <merged> <failed> .applypolicies
  356.             %   <orig> <merged'> <failed'>
  357.  { 1 index /Policies get 1 index
  358.     { type /integertype eq
  359.        { pop        % already processed
  360.        }
  361.        { 2 copy .knownget not { 1 index /PolicyNotFound get } if
  362.             % Stack: <orig> <merged> <failed> <Policies> <key>
  363.             %   <policy>
  364.      dup 1 ne
  365.       { % Set errorinfo and signal a configurationerror.
  366.         % Note that we currently treat all Policy values other than 1
  367.         % the same as 0.
  368.         pop dup 4 index exch get 2 array astore
  369.         $error /errorinfo 3 -1 roll put
  370.         cleartomark
  371.         /setpagedevice load /configurationerror signalerror
  372.       }
  373.       { % Roll back the failed request to its previous status.
  374. DEBUG { (Rolling back.\n) print pstack flush } if
  375.         3 index 2 index 3 -1 roll put
  376.         4 index 1 index .knownget
  377.          { 4 index 3 1 roll put }
  378.          { 3 index exch .undef }
  379.         ifelse
  380.       }
  381.      ifelse
  382.        }
  383.       ifelse
  384.     }
  385.    forall pop
  386.  } bind def
  387.  
  388. % Prepare to present parameters to the device, by spreading them onto the
  389. % operand stack and removing any that shouldn't be presented.
  390. /.prepareparams     % <params> .prepareparams -mark- <key1> <value1> ...
  391.  { mark exch dup
  392.     {           % Stack: -mark- key1 value1 ... merged key value
  393.       .presentspecial 2 index .knownget
  394.        { exec { 3 -1 roll } { pop pop } ifelse }
  395.        { 3 -1 roll }
  396.       ifelse
  397.     }
  398.    forall pop
  399.  } bind def
  400.  
  401. % Put device parameters without resetting currentpagedevice.
  402. % (.putdeviceparams clears the current page device.)
  403. /.putdeviceparamsonly   % <device> <Policies|null> <require_all> -mark-
  404.             %   <key1> <value1> ... .putdeviceparamsonly
  405.             % On success: <device> <eraseflag>
  406.             % On failure: <device> <Policies|null> <req_all> -mark-
  407.             %   <key1> <error1> ...
  408.  { .currentpagedevice
  409.     { counttomark 4 add 1 roll .putdeviceparams
  410.       dup type /booleantype eq { 3 } { counttomark 5 add } ifelse -1 roll
  411.       .setpagedevice
  412.     }
  413.     { pop .putdeviceparams
  414.     }
  415.    ifelse
  416.  } bind def
  417.  
  418. % Try setting the device parameters from the merged request.
  419. /.trysetparams      % <merged> <(ignored)> <device> <Policies>
  420.             %   .trysetparams
  421.  { true 4 index .prepareparams
  422.             % Add the computed .MediaSize.
  423.             % Stack: merged (ignored) device Policies -true-
  424.             %   -mark- key1 value1 ...
  425.    counttomark 5 add index .computemediasize
  426.    exch pop exch pop /.MediaSize exch
  427. DEBUG { (Putting.\n) print pstack flush } if
  428.    .putdeviceparamsonly
  429. DEBUG { (Result of putting.\n) print pstack flush } if
  430.  } bind def
  431.  
  432. % Compute the media size and initial matrix from a merged request (after
  433. % media selection).
  434. /.computemediasize  % <request> .computemediasize
  435.             %   <request> <matrix> <[width height]>
  436.  { dup /PageSize get                    % requested page size
  437.    1 index /InputAttributes get
  438.      2 index (%MediaSource) get get /PageSize get   % media size
  439.                             % (may be a range)
  440.    2 index /Policies get
  441.      dup /PageSize .knownget
  442.       { exch pop } { /PolicyNotFound get } ifelse   % PageSize policy,
  443.                             % affects scaling
  444.    3 index /Orientation .knownget not { null } if
  445.    matrix .matchpagesize pop        % (can't fail)
  446.    2 array astore
  447.  } bind def
  448.  
  449. % ---------------- setpagedevice itself ---------------- %
  450.  
  451. /setpagedevice
  452.  { mark exch currentpagedevice
  453.  
  454.         % Check whether we are changing OutputDevice;
  455.         % also handle the case where the current device
  456.         % is not a page device.
  457.         % Stack: mark <request> <current>
  458. DEBUG { (Checking.\n) print pstack flush } if
  459.  
  460.    dup /OutputDevice .knownget
  461.     {       % Current device is a page device.
  462.       2 index /OutputDevice .knownget
  463.        {    % A specific OutputDevice was requested.
  464.      2 copy eq
  465.       { pop pop null }
  466.       { exch pop }
  467.      ifelse
  468.        }
  469.        { pop null
  470.        }
  471.       ifelse
  472.     }
  473.     {       % Current device is not a page device.
  474.         % Use the default device.
  475.       1 index /OutputDevice .knownget not { .defaultdevicename } if
  476.     }
  477.    ifelse
  478.    dup null eq
  479.     { pop
  480.     }
  481.     { exch pop .defaultdeviceparams
  482.         % In case of duplicate keys, .dicttomark takes the entry
  483.         % lower on the stack, so we can just append the defaults here.
  484.       .requiredattrs { } forall .dicttomark
  485.     }
  486.    ifelse
  487.  
  488.         % Check whether a viewer wants to intervene.
  489.         % We must check both the request (which takes precedence)
  490.         % and the current dictionary.
  491.         % Stack: mark <request> <orig>
  492.    exch dup /ViewerPreProcess .knownget
  493.     { exec }
  494.     { 1 index /ViewerPreProcess .knownget { exec } if }
  495.    ifelse exch
  496.  
  497.         % Construct a merged request from the actual request plus
  498.         % any keys that should always be propagated.
  499.         % Stack: mark <request> <orig>
  500. DEBUG { (Merging.\n) print pstack flush } if
  501.  
  502.    exch 1 index length 1 index length add dict
  503.    .copiedkeys
  504.     {       % Stack: <orig> <request> <merged> <key>
  505.       3 index 1 index .knownget { 3 copy put pop } if pop
  506.     }
  507.    forall
  508.         % Stack: <orig> <request> <merged>
  509.    dup 2 index
  510.     {       % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
  511.       .mergespecial 2 index .knownget { exec } if
  512.       put dup
  513.     }
  514.    forall pop
  515.         % Hack: if FIXEDRESOLUTION is true, discard any attempt to
  516.         % change HWResolution.
  517.    FIXEDRESOLUTION { dup /HWResolution .undef } if
  518.  
  519.         % Select input and output media.
  520.         % Stack: mark <orig> <request> <merged>
  521. DEBUG { (Selecting.\n) print pstack flush } if
  522.  
  523.    0 dict   % <failed>
  524.    1 index /InputAttributes .knownget
  525.     { 2 index /Policies get
  526.       .inputattrkeys (%MediaSource) cvn .selectmedia
  527.     } if
  528.    1 index /OutputAttributes .knownget
  529.     { 2 index /Policies get
  530.       .outputattrkeys (%MediaDestination) cvn .selectmedia
  531.      } if
  532.    3 -1 roll 4 1 roll       % temporarily swap orig & request
  533.    .applypolicies
  534.    3 -1 roll 4 1 roll       % swap back
  535.  
  536.         % Construct the new device, and attempt to set its attributes.
  537.         % Stack: mark <orig> <request> <merged> <failed>
  538. DEBUG { (Constructing.\n) print pstack flush } if
  539.  
  540.    currentdevice .devicename 2 index /OutputDevice get eq
  541.     { currentdevice }
  542.     { 1 index /OutputDevice get finddevice }
  543.    ifelse
  544.         %**************** We should copy the device here,
  545.         %**************** but since we can't close the old device,
  546.         %**************** we don't.  This is WRONG.
  547.     %****************copydevice
  548.    2 index /Policies get
  549.    .trysetparams
  550.    dup type /booleantype ne
  551.     {       % The request failed.
  552.         % Stack: ... <orig> <request> <merged> <failed> <device>
  553.         %   <Policies> true mark <name> <errorname> ...
  554. DEBUG { (Recovering.\n) print pstack flush } if
  555.       counttomark 4 add index
  556.       counttomark 2 idiv { dup 4 -2 roll put } repeat
  557.       pop pop pop
  558.         % Stack: mark ... <orig> <request> <merged> <failed> <device>
  559.         %   <Policies>
  560.       6 2 roll 3 -1 roll 4 1 roll
  561.       .applypolicies
  562.       3 -1 roll 4 1 roll 6 -2 roll
  563.       .trysetparams     % shouldn't fail!
  564.       dup type /booleantype ne
  565.        { 2 { counttomark 1 add 1 roll cleartomark } repeat
  566.          /setpagedevice load exch signalerror
  567.        }
  568.       if
  569.     }
  570.    if
  571.  
  572.         % The attempt succeeded.  Install the new device.
  573.         % Stack: mark ... <merged> <failed> <device> <eraseflag>
  574. DEBUG { (Installing.\n) print pstack flush } if
  575.  
  576.    pop 2 .endpage
  577.     { 1 true .outputpage
  578.       (>>setpagedevice, press <return> to continue<<\n) .confirm
  579.     }
  580.    if
  581.         % .setdevice clears the current page device!
  582.    .currentpagedevice pop exch
  583.    .setdevice pop
  584.    .setpagedevice
  585.  
  586.         % Merge the request into the current page device.
  587.         % Stack: mark ... <merged> <failed>
  588.    exch currentpagedevice dup length 2 index length add dict
  589.    .copydict .copydict
  590.         % Initialize the default matrix, taking media matching
  591.         % into account.
  592.    .computemediasize pop initmatrix concat
  593. % jw hack dump this stuff for test -- kwin and vsc drivers choke on it
  594.     currentdevice .devicename /kwin eq currentdevice .devicename /vsc eq or not 
  595.     {  % If running kwin or vsc device, don't do this
  596.        dup /PageOffset .knownget
  597.         {       % Translate by the given number of 1/72" units in device X/Y.
  598.           dup 0 get exch 1 get
  599.           2 index /HWResolution get dup 1 get exch 0 get
  600.           4 -1 roll mul 72 div   3 1 roll mul 72 div
  601.           idtransform translate
  602.         }
  603.        if
  604.      }
  605.     if
  606. % end jw hack
  607.         % We must install the new page device dictionary
  608.         % before calling the Install procedure.
  609.    dup .setpagedevice
  610.    .setdefaultscreen    % Set the default screen before calling Install.
  611.    dup /Install .knownget { exec } if
  612.    matrix currentmatrix .setdefaultmatrix
  613.         % Erase and initialize the page.
  614.    erasepage initgraphics
  615.    .beginpage
  616.  
  617.         % Clean up, calling PolicyReport if needed.
  618.         % Stack: mark ... <failed> <merged>
  619. DEBUG { (Finishing.\n) print pstack flush } if
  620.  
  621.    exch dup length 0 ne
  622.     { 1 index /Policies get /PolicyReport get
  623.       counttomark 1 add 2 roll cleartomark
  624.       exec
  625.     }
  626.     { cleartomark
  627.     }
  628.    ifelse
  629.  
  630.  } odef
  631.  
  632. end             % level2dict
  633. .setlanguagelevel
  634.