home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / inne / gs300ini / gs_lev2.ps < prev    next >
Encoding:
Text File  |  1994-08-02  |  27.0 KB  |  946 lines

  1. %    Copyright (C) 1990, 1991, 1992, 1993, 1994 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. % Initialization file for Level 2 functions.
  16. % When this is run, systemdict is still writable,
  17. % but everything defined here goes into level2dict.
  18.  
  19. level2dict begin
  20.  
  21. % ------ Miscellaneous ------ %
  22.  
  23. (<<) cvn /mark load def
  24. (>>) cvn /.dicttomark load odef
  25. /currentsystemparams { mark .currentsystemparams .dicttomark } odef
  26. /currentuserparams { mark .currentuserparams .dicttomark } odef
  27. /deviceinfo { currentdevice getdeviceprops .dicttomark } odef
  28. /languagelevel 2 def
  29. /realtime /usertime load def
  30. % When running in Level 2 mode, this interpreter is supposed to be
  31. % compatible with PostScript version 2010 (I think).
  32. /version (2010) def
  33.  
  34. % Choose an appropriate default binary object format.
  35. currentsystemparams dup
  36. /RealFormat get (IEEE) eq { 1 } { 3 } ifelse
  37. exch /ByteOrder get { 1 add } if
  38. setobjectformat
  39.  
  40. % ------ Virtual memory ------ %
  41.  
  42. /currentglobal /.currentglobal load def
  43. /gcheck /.gcheck load def
  44. /setglobal /.setglobal load def
  45. % We can make the global dictionaries very small, because they auto-expand.
  46. /globaldict currentdict /shareddict .knownget not { 4 dict } if def
  47. /GlobalFontDirectory currentdict SharedFontDirectory .knownget not { 4 dict } if def
  48.  
  49. % ------ IODevices ------ %
  50.  
  51. /currentdevparams { .getdevparams .dicttomark } odef
  52. /setdevparams { mark { } forall counttomark 2 add -1 roll .putdevparams } odef
  53.  
  54. % ------ Job control ------ %
  55.  
  56. serverdict begin
  57.  
  58. % We could protect the job information better, but we aren't attempting
  59. % (currently) to protect ourselves against maliciousness.
  60.  
  61. /.jobsave null def        % top-level save object
  62. /.jobsavelevel 0 def        % save depth of job (0 if .jobsave is null,
  63.                 % 1 otherwise)
  64. /.adminjob true def        % status of current unencapsulated job
  65.  
  66. /exitserver
  67.  { true exch startjob not { /exitserver /invalidaccess signalerror } if
  68.  } bind def
  69.  
  70. end        % serverdict
  71.  
  72. %**************** The definition of startjob is not complete yet, since
  73. % it doesn't clear the exec stack, doesn't reset stdin/stdout,
  74. % doesn't run the job under its own control, and doesn't reset
  75. % other aspects of the interpreter.
  76. /startjob
  77.  { vmstatus pop pop serverdict /.jobsavelevel get eq
  78.    1 index .checkpassword 0 gt and
  79.     { .checkpassword count 2 roll count 2 sub { pop } repeat
  80.       cleardictstack
  81.       serverdict /.jobsave get dup null eq { pop } { restore } ifelse
  82.       exch
  83.        {    % unencapsulated job
  84.      serverdict /.jobsave null put
  85.      serverdict /.jobsavelevel 0 put
  86.      serverdict /.adminjob 3 -1 roll 1 gt put
  87.        }
  88.        {    % encapsulated job
  89.      serverdict /.jobsave save put
  90.      serverdict /.jobsavelevel 1 put
  91.      pop
  92.        }
  93.       ifelse true
  94.     }
  95.     { pop pop false
  96.     }
  97.    ifelse
  98.  } odef
  99.  
  100. % ------ Compatibility ------ %
  101.  
  102. % In Level 2 mode, the following replace the definitions that gs_statd.ps
  103. % installs in statusdict and serverdict.
  104. % Note that statusdict must be allocated in local VM.
  105. % We don't bother with many of these yet, and the ones defined in terms
  106. % of currentsystemparams are cavalier about allocating a dictionary
  107. % in order to retrieve a single element from it....
  108.  
  109. .currentglobal false .setglobal 25 dict exch .setglobal begin
  110. currentsystemparams
  111.  
  112. /.dict1 { exch mark 3 1 roll .dicttomark } bind def
  113.  
  114. /buildtime 1 index /BuildTime get def
  115. /byteorder 1 index /ByteOrder get def
  116. /checkpassword { .checkpassword 0 gt } bind def
  117. /defaulttimeouts
  118.  { currentsystemparams dup
  119.    /JobTimeout .knownget not { 0 } if
  120.    exch /WaitTimeout .knownget not { 0 } if
  121.    currentpagedevice /ManualFeedTimeout .knownget not { 0 } if
  122.  } bind def
  123. dup /DoStartPage known
  124.  { /dostartpage { currentsystemparams /DoStartPage get } bind def
  125.    /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def
  126.  } if
  127. dup /StartupMode known
  128.  { /dosysstart { currentsystemparams /StartupMode get 0 ne } bind def
  129.    /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def
  130.  } if
  131. %****** Setting jobname is supposed to set userparams.JobName, too.
  132. /jobname { currentuserparams /JobName get } bind def
  133. /jobtimeout { currentuserparams /JobTimeout get } bind def
  134. %manualfeed
  135. %manualfeedtimeout
  136. /margins { currentpagedevice /Margins get } bind def
  137. %pagecount
  138. %pagestackorder
  139. /printername
  140.  { currentsystemparams /PrinterName .knownget not { () } if exch copy
  141.  } bind def
  142. %/ramsize { currentsystemparams /RamSize get } bind def
  143. /realformat 1 index /RealFormat get def
  144. /setdefaulttimeouts
  145.  { exch mark /ManualFeedTimeout 3 -1 roll
  146.    /Policies mark /ManualFeedTimeout 0 .dicttomark
  147.    .dicttomark setpagedevice
  148.    /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
  149.  } bind def
  150. /setmargins { /Margins .dict1 setpagedevice } bind def
  151. %setpagestackorder
  152. dup /PrinterName known
  153.  { /setprintername { /PrinterName .dict1 setsystemparams } bind def
  154.  } if
  155. currentuserparams /WaitTimeout known
  156.  { /waittimeout { currentuserparams /WaitTimeout get } bind def
  157.  } if
  158.  
  159. /.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def
  160.  
  161. pop        % currentsystemparams
  162.  
  163. % Flag the current dictionary so it will be swapped when we
  164. % change language levels.  (See zmisc2.c for more information.)
  165. /statusdict currentdict def
  166.  
  167. currentdict end
  168. /statusdict exch def
  169.  
  170. % ------ Page devices ------ %
  171.  
  172. % The implementation of setpagedevice is quite complex.  Currently,
  173. % everything but the media matching algorithm is implemented here.
  174. %**************** Incomplete implementation, see NEWS.
  175.  
  176. % Define the parameters that require special action to merge into the
  177. % combined page device dictionary.  The procedures are called as follows:
  178. %    <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
  179. /.mergespecial mark
  180.   /InputAttributes
  181.    { dup null eq
  182.       { pop null
  183.       }
  184.       { 3 copy pop .knownget
  185.      { dup null eq
  186.         { pop dup length dict }
  187.         { dup length 2 index length add dict copy }
  188.        ifelse
  189.      }
  190.      { dup length dict
  191.      }
  192.         ifelse copy readonly
  193.       }
  194.      ifelse
  195.    } bind
  196.   /OutputAttributes 1 index
  197.   /Policies
  198.     { 3 copy pop .knownget
  199.        { dup length 2 index length add dict copy }
  200.        { dup length dict }
  201.       ifelse copy readonly
  202.     } bind
  203. .dicttomark readonly def
  204.  
  205. % Define the keys used in input attribute matching.
  206. /.inputattrkeys [
  207.   /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
  208. ] readonly def
  209.  
  210. % Define the keys used in output attribute matching.
  211. /.outputattrkeys [
  212.   /OutputType
  213. ] readonly def
  214.  
  215. % Define the parameters that should not be presented to the device.
  216. % The procedures are called as follows:
  217. %    <merged> <key> <value> -proc-
  218. % The procedure leaves all its operands on the stack and returns
  219. % true iff the key/value pair should be presented to .putdeviceparams.
  220. /.presentspecial mark
  221.   /Name false
  222.   /OutputDevice false
  223.   /InputAttributes false
  224.   .inputattrkeys { pop { 2 index /InputAttributes get null eq } } forall
  225.   /OutputAttributes false
  226.   .outputattrkeys { pop { 2 index /OutputAttributes get null eq } } forall
  227.   /Install false
  228.   /BeginPage false
  229.   /EndPage false
  230.   /Policies false
  231. .dicttomark readonly def
  232.  
  233. % Define the required attributes of all page devices.
  234. % We don't include attributes such as PageSize, which all devices
  235. % are guaranteed to supply on their own.
  236. /.requiredattrs mark
  237.   /InputAttributes null
  238.   /OutputAttributes null
  239.   /Install {.callinstall} bind
  240.   /BeginPage {.callbeginpage} bind
  241.   /EndPage {.callendpage} bind
  242.   /Policies mark
  243.     /PolicyNotFound 1
  244.     /PageSize 0
  245.     /PolicyReport {pop} bind
  246.   .dicttomark readonly
  247. .dicttomark readonly def
  248.  
  249. % Define access to device defaults.
  250. /.defaultdevicename
  251.  { 0 .getdevice .devicename
  252.  } bind def
  253. /.defaultdeviceparams
  254.  { finddevice null .getdeviceparams
  255.  } bind def
  256.  
  257. % Select media (input or output).
  258. /.selectmedia        % <orig> <request> <merged> <failed>
  259.             %   (these are retained)
  260.             %   <attrdict> <attrkeys> <mediakey> .selectmedia
  261.  { 4 index 4 -1 roll 3 index .matchmedia
  262.     { 4 index 3 1 roll put pop
  263.     }
  264.     {    % Adobe's implementations have a "big hairy heuristic"
  265.     % to choose the set of keys to report as having failed the match.
  266.     % For the moment, we report any keys that are in the request
  267.     % and don't have the same value as in the original dictionary.
  268.       3 index exch undef
  269.        {    % Stack: <orig> <request> <merged> <failed> <attrkey>
  270.      3 index 1 index .knownget
  271.       { 5 index 2 index .knownget { ne } { pop true } ifelse }
  272.       { true }
  273.      ifelse        % Stack: ... <failed> <attrkey> <report>
  274.       { 2 copy /rangecheck put }
  275.      if pop
  276.        }
  277.       forall
  278.     }
  279.    ifelse
  280.  } bind def
  281.  
  282. % Apply Policies to any unprocessed failed requests.
  283. % As we process each request entry, we replace the error name
  284. % in the <failed> dictionary with the policy value,
  285. % and we remove the key from the <merged> dictionary.
  286. /.applypolicies        % <merged> <failed> .applypolicies <merged'> <failed'>
  287.  { 1 index /Policies get 1 index
  288.     { type /integertype eq
  289.        { pop        % already processed
  290.        }
  291.        { 2 copy .knownget not { 1 index /PolicyNotFound get } if
  292.             % Stack: <merged> <failed> <Policies> <key> <policy>
  293.      dup 1 ne
  294.       {    % Set errorinfo and signal a configurationerror.
  295.         % Note that we currently treat all Policy values other than 1
  296.         % the same as 0.
  297.         pop dup 4 index exch get 2 array astore
  298.         $error /errorinfo 3 -1 roll put
  299.         cleartomark
  300.         /setpagedevice load /configurationerror signalerror
  301.       }
  302.       {    % Ignore the failed request.
  303.         3 index 2 index 3 -1 roll put
  304.         3 index exch undef
  305.       }
  306.      ifelse
  307.        }
  308.       ifelse
  309.     }
  310.    forall pop
  311.  } bind def
  312.  
  313. % Try setting the device parameters from the merged request.
  314. /.trysetparams        % ... <merged> <(ignored)> <device> <Policies>
  315.             %   .trysetparams
  316.  { mark 4 index dup
  317.     {            % Stack: <merged> <key> <value>
  318.       .presentspecial 2 index .knownget
  319.        { exec { 3 -1 roll } { pop pop } ifelse }
  320.        { 3 -1 roll }
  321.       ifelse
  322.     }
  323.    forall pop
  324. DEBUG { (Putting.\n) print pstack flush } if
  325.    .putdeviceparams
  326. DEBUG { (Result of putting.\n) print pstack flush } if
  327.  } bind def
  328.  
  329. % Finally, define setpagedevice.
  330. /setpagedevice
  331.  {
  332.    mark exch currentpagedevice
  333.  
  334.         % Check whether we are changing OutputDevice;
  335.         % also handle the case where the current device
  336.         % is not a page device.
  337.         % Stack: mark <request> <current>
  338. DEBUG { (Checking.\n) print pstack flush } if
  339.  
  340.    dup /OutputDevice .knownget
  341.     {        % Current device is a page device.
  342.       2 index /OutputDevice .knownget
  343.        {    % A specific OutputDevice was requested.
  344.      2 copy eq
  345.       { pop pop null }
  346.       { exch pop }
  347.      ifelse
  348.        }
  349.        { pop null
  350.        }
  351.       ifelse
  352.     }
  353.     {        % Current device is not a page device.
  354.         % Use the default device.
  355.       1 index /OutputDevice .knownget not { .defaultdevicename } if
  356.     }
  357.    ifelse
  358.    dup null eq
  359.     { pop
  360.     }
  361.     { exch pop .defaultdeviceparams
  362.       counttomark 2 idiv .requiredattrs length add dict
  363.       .requiredattrs exch copy
  364.       begin counttomark 2 idiv { def } repeat pop currentdict end
  365.     }
  366.    ifelse
  367.  
  368.         % Merge the current and requested dictionaries.
  369.         % Stack: mark <request> <orig>
  370. DEBUG { (Merging.\n) print pstack flush } if
  371.  
  372.    exch 1 index dup length 2 index length add dict copy
  373.    dup 2 index
  374.     {        % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
  375.       .mergespecial 2 index .knownget { exec } if
  376.       put dup
  377.     }
  378.    forall pop
  379.  
  380.         % Select input and output media.
  381.         % Stack: mark <orig> <request> <merged>
  382. DEBUG { (Selecting.\n) print pstack flush } if
  383.  
  384.    0 dict    % <failed>
  385.    1 index /InputAttributes get .inputattrkeys (%MediaSource) cvn .selectmedia
  386.    1 index /OutputAttributes get .outputattrkeys (%MediaDestination) cvn .selectmedia
  387.    .applypolicies
  388.  
  389.         % Construct the new device, and attempt to set its attributes.
  390.         % Stack: mark <orig> <request> <merged> <failed>
  391. DEBUG { (Constructing.\n) print pstack flush } if
  392.  
  393.    currentdevice .devicename 2 index /OutputDevice get eq
  394.     { currentdevice }
  395.     { 1 index /OutputDevice get finddevice }
  396.    ifelse
  397.         %**************** We should copy the device here,
  398.         %**************** but since we can't close the old device,
  399.         %**************** we don't.  This is WRONG.
  400.     %****************copydevice
  401.    2 index /Policies get
  402.    .trysetparams
  403.    dup type /nametype eq
  404.     {        % The request failed.
  405.         % Stack: ... <failed> <device> <Policies> <mark>
  406.         %   <name> <value> ...
  407.       counttomark 4 add -1 roll
  408.       counttomark 2 idiv { dup 4 -2 roll put } repeat
  409.       exch pop 3 1 roll
  410.         % Stack: mark ... <merged> <failed> <device> <Policies>
  411.       4 2 roll .applypolicies 4 -2 roll
  412.       .trysetparams        % shouldn't fail!
  413.       dup type /booleantype ne
  414.        { 2 { counttomark 1 add 1 roll cleartomark } repeat
  415.          /setpagedevice load exch signalerror
  416.        }
  417.       if
  418.     }
  419.    if
  420.  
  421.         % The attempt succeeded.  Install the new device.
  422.         % Stack: mark ... <merged> <failed> <device> <eraseflag>
  423. DEBUG { (Installing.\n) print pstack flush } if
  424.  
  425.    pop 2 .endpage
  426.     { 1 true .outputpage
  427.       (>>setpagedevice, press <return> to continue<<\n) .confirm
  428.     }
  429.    if
  430.    .setdevice pop
  431.    1 index /Install .knownget { exec } if
  432.    erasepage initgraphics
  433.    1 index .setpagedevice .beginpage
  434.  
  435.         % Clean up, calling PolicyReport if needed.
  436.         % Stack: mark ... <merged> <failed>
  437. DEBUG { (Finishing.\n) print pstack flush } if
  438.  
  439.    dup length 0 ne
  440.     { 1 index /Policies get /PolicyReport get
  441.       counttomark 1 add 2 roll cleartomark
  442.       exec
  443.     }
  444.     { cleartomark
  445.     }
  446.    ifelse
  447.  
  448.  } odef
  449.  
  450. %**************** setpagedevice doesn't work well enough to use yet.
  451. /setpagedevice { pop } odef
  452. statusdict /.setpagesize undef
  453.  
  454. % ------ Painting ------ %
  455.  
  456. % A straightforward definition of execform that doesn't actually
  457. % do any caching.
  458. /execform
  459.  { dup /Implementation known not
  460.     { dup /FormType get 1 ne { /rangecheck signalerror } if
  461.       dup /Implementation null put readonly
  462.     } if
  463.    gsave dup /Matrix get concat
  464.    dup /BBox get aload pop
  465.    exch 3 index sub exch 2 index sub rectclip
  466.    dup /PaintProc get exec
  467.    grestore
  468.  } odef
  469.  
  470. /makepattern
  471.  { currentglobal
  472.     { false setglobal .buildpattern true setglobal }
  473.     { .buildpattern }
  474.    ifelse
  475.    exch dup length 1 add dict copy
  476.    dup /Implementation 4 -1 roll put
  477.    readonly
  478.  } odef
  479.  
  480. /setpattern
  481.  { currentcolorspace 0 get /Pattern ne
  482.     { [ /Pattern currentcolorspace ] setcolorspace } if
  483.    setcolor
  484.  } odef
  485.  
  486. % ------ Resources ------ %
  487.  
  488. (BEGIN RESOURCES) VMDEBUG
  489.  
  490. % We keep track of (global) instances with another entry in the resource
  491. % dictionary, an Instances dictionary.  For categories with implicit
  492. % instances, the values in Instances are the same as the keys;
  493. % for other categories, the values are [instance status size].
  494.  
  495. % Note that the dictionary that defines a resource category is stored
  496. % in global memory.  The PostScript manual says that each category must
  497. % manage global and local instances separately.  However, objects in
  498. % global memory can't reference objects in local memory.  This means
  499. % that the resource category dictionary, which would otherwise be the
  500. % obvious place to keep track of the instances, can't be used to keep
  501. % track of local instances.  Instead, we define a dictionary in local VM
  502. % called localinstancedict, in which the key is the category name and
  503. % the value is the analogue of Instances for local instances.
  504.  
  505. % We don't currently implement automatic resource unloading.
  506. % When we do, it should be hooked to the garbage collector.
  507.  
  508. currentglobal false setglobal systemdict begin
  509.   /localinstancedict 5 dict def
  510. end setglobal
  511. /.emptydict 0 dict readonly def
  512.  
  513. % Resource category dictionaries have the following keys (those marked with
  514. % * are optional):
  515. %    Defined in the Red Book:
  516. %        DefineResource
  517. %        UndefineResource
  518. %        FindResource
  519. %        ResourceStatus
  520. %        ResourceForAll
  521. %        Category
  522. %        *InstanceType
  523. %        *ResourceFileName
  524. %    Specific to our implementation:
  525. %        LocalInstances
  526. %            - LocalInstances <dict>
  527. %        GetInstance
  528. %            <key> GetInstance <instance> -true-
  529. %            <key> GetInstance -false-
  530. %        .CheckResource
  531. %            <value> .CheckResource <ok>
  532. %        .LoadResource
  533. %            <key> .LoadResource - (may give an error)
  534. %        .ResourceFile
  535. %            <key> .ResourceFile <file> -true-
  536. %            <key> .ResourceFile -false-
  537.  
  538. % Define the Category category, except for most of the procedures.
  539. % The dictionary we're about to create will become the Category
  540. % category definition dictionary.
  541.  
  542. 12 dict begin
  543. /Category /Category def
  544. /GetInstance
  545.     { Instances exch .knownget
  546.     } bind def
  547. /LocalInstances [] def
  548. /.CheckResource
  549.     { dup gcheck currentglobal and
  550.        { /DefineResource /FindResource /ResourceForAll /ResourceStatus
  551.          /UndefineResource }
  552.        { 2 index exch known and }
  553.       forall exch pop
  554.     } bind def
  555. /DefineResource
  556.     { dup .CheckResource
  557.        { dup /Category 3 index cvlit .growput readonly
  558.          dup [ exch 0 -1 ] exch
  559.          Instances 4 2 roll put
  560.        }
  561.        { /typecheck signalerror
  562.        }
  563.       ifelse
  564.     } bind def
  565. /FindResource        % (redefined below)
  566.     { Instances exch get 0 get
  567.     } bind def
  568. /Instances 25 dict def
  569. /InstanceType /dicttype def
  570.  
  571. Instances /Category [currentdict 0 -1] put
  572. Instances end begin    % so we can name the Category definition
  573.  
  574. (END CATEGORY) VMDEBUG
  575.  
  576. % Define the resource operators.  I don't see how we can possibly restore
  577. % the stacks after an error, since the procedure may have popped and
  578. % pushed elements arbitrarily....
  579.  
  580. mark
  581. /defineresource
  582.     { /Category findresource dup begin
  583.       /InstanceType known
  584.        { dup type InstanceType ne
  585.          { dup type /packedarraytype eq InstanceType /arraytype eq and
  586.         not { /typecheck signalerror } if } if } if
  587.       /DefineResource load stopped end { stop } if
  588.     }
  589. /findresource
  590.     { dup /Category eq
  591.        { pop //Category 0 get } { /Category findresource } ifelse
  592.       begin
  593.       /FindResource load stopped end { stop } if
  594.     }
  595. /resourceforall
  596.     { /Category findresource begin
  597.       /ResourceForAll load stopped end { stop } if
  598.     }
  599. /resourcestatus
  600.     { /Category findresource begin
  601.       /ResourceStatus load stopped end { stop } if
  602.     }
  603. /undefineresource
  604.     { /Category findresource begin
  605.       /UndefineResource load stopped end { stop } if
  606.     }
  607. end        % Instances
  608. counttomark 2 idiv { bind odef } repeat pop
  609.  
  610. % Define the Generic category.
  611.  
  612. /Generic mark
  613.  
  614. /Instances 0 dict
  615. /LocalInstances        % not a standard entry -- a shared utility
  616.     { localinstancedict Category .knownget not { //.emptydict } if
  617.     } bind
  618. /GetInstance        % not a standard entry -- a shared utility
  619.     { currentglobal
  620.        { Instances exch .knownget }
  621.        { LocalInstances 1 index .knownget
  622.           { exch pop true }
  623.           { Instances exch .knownget }
  624.          ifelse
  625.        }
  626.       ifelse
  627.     } bind
  628. /.CheckResource        % not a standard entry
  629.     { pop true
  630.     } bind
  631. /DefineResource
  632.     { dup .CheckResource
  633.        { { readonly } stopped pop
  634.          dup [ exch 0 -1 ] exch
  635.          currentglobal
  636.           { 2 index UndefineResource    % remove local def if any
  637.         Instances
  638.           }
  639.           { LocalInstances dup //.emptydict eq
  640.              { pop 3 dict localinstancedict Category 2 index put
  641.          }
  642.         if
  643.           }
  644.          ifelse
  645.          4 2 roll .growput
  646.        }
  647.        { /typecheck signalerror
  648.        }
  649.       ifelse
  650.     } bind
  651. /FindResource
  652.     { dup ResourceStatus
  653.        { pop 1 gt        % not in VM
  654.           { dup vmstatus pop exch pop exch
  655.         .LoadResource
  656.         vmstatus pop exch pop exch sub
  657.         1 index GetInstance not
  658.          { pop /undefinedresource signalerror }    % didn't load
  659.         if
  660.         dup 1 1 put
  661.         2 3 -1 roll put
  662.           }
  663.          if
  664.          GetInstance pop        % can't fail
  665.          0 get
  666.        }
  667.        { /undefinedresource signalerror
  668.        }
  669.       ifelse
  670.     } bind
  671. /.LoadResource        % not a standard entry; may fail
  672.     { dup .ResourceFile
  673.        { exch pop currentglobal
  674.           { run }
  675.           { true setglobal { run } stopped false setglobal { stop } if }
  676.          ifelse
  677.        }
  678.        { /undefinedresource signalerror
  679.        }
  680.      ifelse
  681.     } bind
  682. /.ResourceFile        % not a standard entry; returns <file> true or false
  683.     { currentdict /ResourceFileName known
  684.        { mark exch 100 string { ResourceFileName }
  685.          stopped
  686.           { cleartomark false }
  687.           { exch pop findlibfile
  688.          { exch pop true }
  689.          { pop false }
  690.         ifelse
  691.           }
  692.          ifelse
  693.        }
  694.        { pop false }
  695.       ifelse
  696.     } bind
  697. /ResourceForAll
  698.     { % **************** Doesn't present instance groups in
  699.       % **************** the correct order yet.
  700.       % We construct a new procedure so we don't have to use
  701.       % static resources to hold the iteration state.
  702.       3 packedarray        % template, proc, scratch
  703.       { exch pop    % stack contains: key, {template, proc, scratch}
  704.         2 copy 0 get .stringmatch
  705.          { 1 index type dup /stringtype eq exch /nametype eq or
  706.         { 2 copy 2 get cvs
  707.           exch 1 get 3 -1 roll pop
  708.         }
  709.         { 1 get
  710.         }
  711.            ifelse exec
  712.          }
  713.          { pop pop
  714.          }
  715.         ifelse
  716.       } /exec cvx 3 packedarray cvx
  717.       currentglobal LocalInstances length 0 eq or not
  718.        {        % We must do local instances, and do them first.
  719.          /forall cvx 1 index 2 packedarray cvx
  720.          LocalInstances 3 1 roll exec
  721.        }
  722.       if
  723.       Instances exch forall
  724.     } bind
  725. /ResourceStatus
  726.     { dup GetInstance
  727.        { exch pop dup 1 get exch 2 get true }
  728.        { .ResourceFile
  729.           { closefile 2 -1 true }
  730.           { false }
  731.          ifelse
  732.        }
  733.       ifelse
  734.     } bind
  735. /UndefineResource
  736.     {  { dup 2 index .knownget
  737.           { dup 1 get 1 ge
  738.          { dup 0 null put 1 2 put pop pop }
  739.          { pop exch undef }
  740.         ifelse
  741.           }
  742.           { pop pop
  743.           }
  744.          ifelse
  745.        }
  746.       currentglobal
  747.        { 2 copy Instances exch exec
  748.        }
  749.       if LocalInstances exch exec
  750.     } bind
  751.  
  752. % We're still running in Level 1 mode, so dictionaries won't expand.
  753. % Leave room for the /Category entry.
  754. /Category null
  755.  
  756. .dicttomark
  757. /Category defineresource pop
  758.  
  759. % Fill in the rest of the Category category.
  760. /Category /Category findresource dup
  761. /Generic /Category findresource begin
  762.  { /FindResource /ResourceStatus /ResourceForAll /.ResourceFile }
  763.  { dup load put dup } forall
  764. pop readonly pop end
  765.  
  766. (END GENERIC) VMDEBUG
  767.  
  768. % Define the fixed categories.
  769.  
  770. mark
  771.     % Things other than types
  772.  /ColorSpaceFamily
  773.    {/CIEBasedA /CIEBasedABC /DeviceCMYK /DeviceGray /DeviceRGB
  774.     /Indexed /Pattern /Separation
  775.    }
  776.  /Emulator
  777.    {}
  778.  /Filter
  779.    mark systemdict
  780.      { pop =string cvs (.filter_) anchorsearch
  781.         { pop cvn }
  782.         { pop }
  783.        ifelse
  784.      }
  785.     forall
  786.    .packtomark
  787.  /IODevice
  788.     % Loop until the .getiodevice gets a rangecheck.
  789.    errordict /rangecheck 2 copy get
  790.    errordict /rangecheck { pop stop } put    % pop the command
  791.    mark 0 { {dup .getiodevice exch 1 add} loop} stopped pop pop .packtomark
  792.    4 1 roll put
  793.    .clearerror
  794.     % Types
  795.  /ColorRenderingType
  796.    {1}
  797.  /FMapType
  798.    {2 3 4 5 6 7 8}
  799.  /FontType
  800.    [/.buildfont0 where {pop 0} if 1 3]
  801.  /FormType
  802.    {1}
  803.  /HalftoneType
  804.    {1 2 3 4 5}
  805.  /ImageType
  806.    {1}
  807.  /PatternType
  808.    {1}
  809. counttomark 2 idiv
  810.  { 8 dict begin        % 5 procedures, Category, Instances, LocalInstances
  811.    /DefineResource
  812.     { /invalidaccess signalerror } bind def
  813.    /FindResource
  814.     { Instances exch get } bind def
  815.    /LocalInstances    % used by ResourceForAll
  816.     [] def
  817.    /ResourceForAll
  818.     /Generic /Category findresource /ResourceForAll get def
  819.    /ResourceStatus
  820.     { Instances exch known { 0 0 true } { false } ifelse } bind def
  821.    /UndefineResource
  822.     { /invalidaccess signalerror } bind def
  823.    dup length dict dup begin exch { dup def } forall end readonly
  824.    /Instances exch def
  825.    currentdict end /Category defineresource pop
  826.  } repeat pop
  827.  
  828. (END FIXED) VMDEBUG
  829.  
  830. % Define the other built-in categories.
  831.  
  832. /.definecategory    % <name> -mark- <key1> ... <valuen> .definecategory -
  833.  { counttomark 2 idiv 2 add        % Instances, Category
  834.    /Generic /Category findresource dup maxlength 3 -1 roll add dict copy begin
  835.    counttomark 2 idiv { def } repeat pop    % pop the mark
  836.    currentdict /Instances known not { /Instances 10 dict def } if
  837.    currentdict end /Category defineresource pop
  838.  } bind def
  839.  
  840. /ColorRendering mark /InstanceType /dicttype .definecategory
  841. /ColorSpace mark /InstanceType /arraytype .definecategory
  842. /Form mark /InstanceType /dicttype .definecategory
  843. /Halftone mark /InstanceType /dicttype .definecategory
  844. /Pattern mark /InstanceType /dicttype .definecategory
  845. /ProcSet mark /InstanceType /dicttype .definecategory
  846.  
  847. (END MISC) VMDEBUG
  848.  
  849. % Define the Encoding category.
  850.  
  851. /Encoding mark /InstanceType /arraytype
  852.  
  853. % Handle lazily loaded encodings that aren't loaded yet.
  854.  
  855. /Instances mark
  856.   .encodingdict
  857.    { length 256 eq { pop } { [null 2 -1] } ifelse
  858.    } forall
  859. .dicttomark
  860.  
  861. /.ResourceFileDict mark
  862.   .encodingdict
  863.    { dup length 256 eq { pop pop } { 0 get } ifelse
  864.    } forall
  865. .dicttomark
  866.  
  867. /ResourceFileName
  868.  { exch dup .ResourceFileDict exch .knownget
  869.     { exch pop exch copy }
  870.     { exch pop /undefinedresource signalerror }
  871.    ifelse
  872.  } bind
  873.  
  874. .definecategory            % Encoding
  875.  
  876. /.findencoding { /Encoding findresource } bind def
  877. /findencoding /.findencoding load odef
  878. /.defineencoding
  879.  { 2 copy /Encoding defineresource pop
  880.    //.encodingdict 3 1 roll put
  881.  } bind def
  882.  
  883. .encodingdict
  884.  { dup length 256 eq
  885.     { /Encoding defineresource pop }
  886.     { pop pop }
  887.    ifelse
  888.  }
  889. forall
  890.  
  891. (END ENCODING) VMDEBUG
  892.  
  893. % Define the Font category.
  894.  
  895. /Font mark /InstanceType /dicttype
  896.  
  897. /DefineResource
  898.     { 2 copy //definefont exch pop
  899.       /Generic /Category findresource /DefineResource get exec
  900.     } bind
  901. /.LoadResource
  902.     { //findfont pop
  903.     } bind
  904.  
  905. .definecategory            % Font
  906.  
  907. % Make entries for fonts already loaded.
  908. /.resourceFromFontmap
  909.  { /Font /Category findresource begin
  910.    Fontmap
  911.     { pop dup Instances exch known
  912.        { pop }
  913.        { [null 2 -1] Instances 3 1 roll .growput }
  914.       ifelse
  915.     }
  916.    forall
  917.    end
  918.  } bind def
  919. .resourceFromFontmap
  920. /Font /Category findresource begin
  921. FontDirectory
  922.  { dup .gcheck { Instances } { LocalInstances } ifelse
  923.    3 1 roll [exch 0 -1] .growput
  924.  }
  925. forall end
  926.  
  927. % Redefine font "operators".
  928. /.loadFontmap { //.loadFontmap exec .resourceFromFontmap } def
  929.  
  930. /definefont
  931.     { /Font defineresource } bind odef
  932. %**************** Don't redefine findfont yet.
  933. %/findfont
  934. %    { /Font findresource } bind def    % Must be a procedure, not an operator
  935. /undefinefont
  936.     { /Font undefineresource } bind odef
  937.  
  938. % Remove initialization utilities.
  939. currentdict /.definecategory undef
  940. currentdict /.emptydict undef
  941.  
  942. end    % level2dict
  943.