% Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.% % This software is provided AS-IS with no warranty, either express or% implied.% % This software is distributed under license and may not be copied,% modified or distributed except as expressly authorized under the terms% of the license contained in the file LICENSE in this distribution.% % For more information about licensing, please refer to% http://www.ghostscript.com/licensing/. For information on% commercial licensing, go to http://www.artifex.com/licensing/ or% contact Artifex Software, Inc., 101 Lucas Valley Road #110,% San Rafael, CA 94903, U.S.A., +1(415)492-9861. % $Id: gs_res.ps,v 1.38 2004/10/26 17:07:18 igor Exp $% Initialization file for Level 2 resource machinery.% When this is run, systemdict is still writable,% but (almost) everything defined here goes into level2dict. level2dict begin (BEGIN RESOURCES) VMDEBUG % We keep track of (global) instances with another entry in the resource% dictionary, an .Instances dictionary. For categories with implicit% instances, the values in .Instances are the same as the keys;% for other categories, the values are [instance status size]. % Note that the dictionary that defines a resource category is stored% in global VM. The PostScript manual says that each category must% manage global and local instances separately. However, objects in% global VM other than systemdict can't reference objects in local VM.% This means that the resource category dictionary, which would otherwise be% the obvious place to keep track of the instances, can't be used to keep% track of local instances. Instead, we define a dictionary in local VM% called localinstancedict, in which the key is the category name and% the value is the analogue of .Instances for local instances. % We don't currently implement automatic resource unloading.% When and if we do, it should be hooked to the garbage collector.% However, Ed Taft of Adobe says their interpreters don't implement this% either, so we aren't going to worry about it for a while. currentglobal false setglobal systemdict begin /localinstancedict 5 dict .forcedef % localinstancedict is local, systemdict is globalend true setglobal/.emptydict 0 dict readonly defsetglobal % Resource category dictionaries have the following keys (those marked with% * are optional):% Standard, defined in the Red Book:% Category (name)% *InstanceType (name)% DefineResource% <key> <instance> DefineResource <instance>% UndefineResource% <key> UndefineResource -% FindResource% <key> FindResource <instance>% ResourceStatus% <key> ResourceStatus <status> <size> true% <key> ResourceStatus false% ResourceForAll% <template> <proc> <scratch> ResourceForAll -% *ResourceFileName% <key> <scratch> ResourceFileName <filename>% Additional, specific to our implementation:% .Instances (dictionary)% .LocalInstances% - .LocalInstances <dict>% .GetInstance% <key> .GetInstance <instance> -true-% <key> .GetInstance -false-% .CheckResource% <key> <value> .CheckResource <key> <value> <ok>% (or may give an error if not OK)% .DoLoadResource% <key> .DoLoadResource <key> (may give an error)% .LoadResource% <key> .LoadResource - (may give an error)% .ResourceFile% <key> .ResourceFile <file> -true-% <key> .ResourceFile <key> -false-% .ResourceFileStatus% <key> .ResourceFileStatus 2 <vmusage> -true-% <key> .ResourceFileStatus -false-% All the above procedures expect that the top dictionary on the d-stack% is the resource dictionary. % Define enough of the Category category so we can define other categories.% The dictionary we're about to create will become the Category% category definition dictionary. % .findcategory and .resourceexec are only called from within the% implementation of the resource 'operators', so they doesn't have to worry% about cleaning up the stack if they fail (the interpreter's stack% protection machinery for pseudo-operators takes care of this)./.findcategory { % <name> .findcategory - % (pushes the category on the dstack) /Category findresource begin} bind def /.resourceexec { % <key> /xxxResource .resourceexec - % (also pops the category from the dstack) load exec end} bind def % .getvminstance treats instances on disk as undefined./.getvminstance { % <key> .getvminstance <instance> -true- % <key> .getvminstance -false- .GetInstance { dup 1 get 2 ne { true } { pop false } ifelse } { false } ifelse} bind def 20 dict begin % Standard entries /Category /Category def/InstanceType /dicttype def /DefineResource { .CheckResource { dup /Category 3 index cvlit .growput dup [ exch 0 -1 ] exch .Instances 4 2 roll put % Make the Category dictionary read-only. We will have to % use .forceput / .forcedef later to replace the dummy, % empty .Instances dictionary with the real one later. readonly } { /defineresource load /typecheck signalerror } ifelse} bind def/FindResource % (redefined below) { .Instances exch get 0 get } bind def % Additional entries /.Instances 30 dict def.Instances /Category [currentdict 0 -1] put /.LocalInstances 0 dict def/.GetInstance { .Instances exch .knownget } bind def/.CheckResource { dup gcheck currentglobal and { /DefineResource /FindResource /ResourceForAll /ResourceStatus /UndefineResource } { 2 index exch known and } forall not { /defineresource load /invalidaccess signalerror } if true } bind def .Instances end begin % for the base case of findresource (END CATEGORY) VMDEBUG % Define the resource operators. We use the "stack protection" feature of% odef to make sure the stacks are restored properly on an error.% This requires that the operators not pop anything from the stack until% they have executed their logic successfully. We can't make this% work for resourceforall, because the procedure it executes mustn't see% the operands of resourceforall on the stack, but we can make it work for% the others. % findresource is the only operator that needs to bind //Category./findresource { % <key> <category> findresource <instance> 2 copy dup /Category eq { pop //Category 0 get begin } { .findcategory } ifelse /FindResource .resourceexec exch pop exch pop} bindend % .Instances of Categoryodef /defineresource { % <key> <instance> <category> defineresource <instance> 3 copy .findcategory currentdict /InstanceType known { dup type InstanceType ne { dup type /packedarraytype eq InstanceType /arraytype eq and not { /defineresource load /typecheck signalerror } if } if } if /DefineResource .resourceexec 4 1 roll pop pop pop} bind odef% We must prevent resourceforall from automatically restoring the stacks,% because we don't want the stacks restored if proc causes an error or% executes a 'stop'. On the other hand, resourceforall is defined in the% PLRM as an operator, so it must have type /operatortype. We hack this% by taking advantage of the fact that the interpreter optimizes tail% calls, so stack protection doesn't apply to the very last token of an% operator procedure./resourceforall1 { % <template> <proc> <scratch> <category> resourceforall1 - dup /Category findresource begin /ResourceForAll load % Stack: <template> <proc> <scratch> <category> proc exch pop % pop the category exec end} bind def/resourceforall { % <template> <proc> <scratch> <category> resourceforall1 - //resourceforall1 exec % see above} bind odef/resourcestatus { % <key> <category> resourcestatus <status> <size> true % <key> <category> resourcestatus false 2 copy .findcategory /ResourceStatus .resourceexec { 4 2 roll pop pop true } { pop pop false } ifelse} bind odef/undefineresource { % <key> <category> undefineresource - 2 copy .findcategory /UndefineResource .resourceexec pop pop} bind odef % Define the system parameters used for the Generic implementation of% ResourceFileName.systemdict begin % - .default_resource_dir <string>/.default_resource_dir { .file_name_parent .file_name_directory_separator concatstrings (Resource) concatstrings /LIBPATH .systemvar { dup .file_name_current eq { pop } { 1 index false .file_name_combine { exch pop exit } { pop pop } ifelse } ifelse } forall} bind def % <path> <name> <string> .resource_dir_name <path> <name> <string>/.resource_dir_name{ systemdict 2 index .knownget { exch pop systemdict 1 index undef } { dup () ne { .file_name_directory_separator concatstrings } if 2 index exch false .file_name_combine not { (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print = /.default_resource_dir /configurationerror .signalerror } if } ifelse} bind def currentdict /pssystemparams known not { /pssystemparams 10 dict readonly def} ifpssystemparams begin .default_resource_dir /FontResourceDir (Font) .resource_dir_name readonly .forcedef % pssys'params is r-o /GenericResourceDir () .resource_dir_name readonly .forcedef % pssys'params is r-o pop % .default_resource_dir /GenericResourcePathSep .file_name_separator readonly .forcedef % pssys'params is r-o (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forcedef % pssys'params is r-o (%diskGenericResourceDir) cvn (/Resource/) readonly .forcedef % pssys'params is r-oendend % Check if GenericResourceDir presents in LIBPATH. % The value of GenericResourceDir must end with directory separator.% We use .file_name_combine to check it. % Comments use OpenVMS syntax, because it is the most complicated case.(x) pssystemparams /GenericResourcePathSep get(y) concatstrings concatstrings dup length % (x]y) l1pssystemparams /GenericResourceDir get dup length exch % (x]y) l1 l2 (dir)3 index true .file_name_combine not { exch (File name ) print print ( cant combine with ) print = /GenericResourceDir cvx /configurationerror signalerror} ifdup length % (x]y) l1 l2 (dir.x]y) l4 2 roll add % (x]y) (dir.x]y) l llne { (GenericResourceDir value does not end with directory separator.\n) = /GenericResourceDir cvx /configurationerror signalerror} ifpop pop % Define the generic algorithm for computing resource file names./.rfnstring 8192 string def/.genericrfn % <key> <scratch> <prefix> .genericrfn <filename> { 3 -1 roll //.rfnstring cvs concatstrings exch copy } bind def % Define a procedure for making a packed array in local VM./.localpackedarray { % <obj1> ... <objn> <n> .localpackedarray <packedarray> .currentglobal false .setglobal 1 index 2 add 1 roll packedarray exch .setglobal} bind def % Define the Generic category. /Generic mark % Standard entries % We're still running in Level 1 mode, so dictionaries won't expand.% Leave room for the /Category entry./Category null % Implement the body of Generic resourceforall for local, global, and% external cases. 'args' is [template proc scratch resdict]./.enumerateresource { % <key> [- <proc> <scratch>] .enumerateresource - 1 index type dup /stringtype eq exch /nametype eq or { exch 1 index 2 get cvs exch } if % Use .setstackprotect to prevent the stacks from being restored if % an error occurs during execution of proc. 1 get false .setstackprotect exec true .setstackprotect} bind def/.localresourceforall { % <key> <value> <args> .localr'forall - exch pop 2 copy 0 get .stringmatch { .enumerateresource } { pop pop } ifelse} bind def/.globalresourceforall { % <key> <value> <args> .globalr'forall - exch pop 2 copy 0 get .stringmatch { dup 3 get begin .LocalInstances end 2 index known not { .enumerateresource } { pop pop } ifelse } { pop pop } ifelse} bind def/.externalresourceforall { % <filename> <len> <args> .externalr'forall - 3 1 roll 1 index length 1 index sub getinterval exch dup 3 get begin .Instances .LocalInstances end % Stack: key args insts localinsts 3 index known { pop pop pop } { 2 index known { pop pop } { .enumerateresource } ifelse } ifelse} bind def /DefineResource { .CheckResource { dup [ exch 0 -1 ] % Stack: key value instance currentglobal { false setglobal 2 index UndefineResource % remove local def if any true setglobal .Instances dup //.emptydict eq { pop 3 dict % As noted above, Category dictionaries are read-only, % so we have to use .forcedef here. /.Instances 1 index .forcedef % Category dict is read-only } if } { .LocalInstances dup //.emptydict eq { pop 3 dict localinstancedict Category 2 index put } if } ifelse % Stack: key value instance instancedict 3 index 2 index .growput % Now make the resource value read-only. 0 2 copy get { readonly } .internalstopped pop dup 4 1 roll put exch pop exch pop } { /defineresource load /typecheck signalerror } ifelse} .bind executeonly % executeonly to prevent access to .forcedef/UndefineResource { { dup 2 index .knownget { dup 1 get 1 ge { dup 0 null put 1 2 put pop pop } { pop exch .undef } ifelse } { pop pop } ifelse } currentglobal { 2 copy .Instances exch exec } if .LocalInstances exch exec } bind% Because of some badly designed code in Adobe's CID font downloader that% makes findresource and resourcestatus deliberately inconsistent with each% other, the default FindResource must not call ResourceStatus if there is% an instance of the desired name already defined in VM./FindResource { dup .getvminstance { exch pop 0 get } { dup ResourceStatus { pop 1 gt { .DoLoadResource .getvminstance not { /findresource load /undefinedresource signalerror } if 0 get } { .GetInstance pop 0 get } ifelse } { /findresource load /undefinedresource signalerror } ifelse } ifelse} bind% Because of some badly designed code in Adobe's CID font downloader, the% definition of ResourceStatus for Generic and Font must be the same (!).% We patch around this by using an intermediate .ResourceFileStatus procedure./ResourceStatus { dup .GetInstance { exch pop dup 1 get exch 2 get true } { .ResourceFileStatus } ifelse} bind/.ResourceFileStatus { .ResourceFile { closefile 2 -1 true } { pop false } ifelse} bind/ResourceForAll { % Construct a new procedure to hold the arguments. % All objects constructed here must be in local VM to avoid % a possible invalidaccess. currentdict 4 .localpackedarray % [template proc scratch resdict] % We must pop the resource dictionary off the dict stack % when doing the actual iteration, and restore it afterwards. .currentglobal not { .LocalInstances length 0 ne { % We must do local instances, and do them first. //.localresourceforall {exec} 0 get 3 .localpackedarray cvx .LocalInstances exch {forall} 0 get 1 index 0 get currentdict end 3 .execn begin } if } if % Do global instances next. //.globalresourceforall {exec} 0 get 3 .localpackedarray cvx .Instances exch cvx {forall} 0 get 1 index 0 get currentdict end 3 .execn begin mark % args [ Category .namestring .file_name_separator concatstrings 2 index 0 get % args [ (c/) (t) dup length 3 1 roll % args [ l (c/) (t) concatstrings % args [ l (c/t) [ /LIBPATH .systemvar 2 index .generate_dir_list_templates % args (t) [ l [(pt)] % also add on the Resources as specified by the GenericResourceDir [ currentsystemparams /GenericResourceDir get] counttomark 1 add index .generate_dir_list_templates % Resource files on OpenVMS requires a separate template (gs:[dir.*]*) [ currentsystemparams /GenericResourceDir get] counttomark 1 add index .file_name_separator (*) concatstrings concatstrings .generate_dir_list_templates ] exch pop { % args [ l (pt) dup length 2 index sub exch % args [ l Lp (pt) { % args [ l Lp (pf) dup length % args [ l Lp (pf) Lpf 2 index sub % args [ l Lp (pf) Lf 2 index exch % args [ l Lp (pf) Lp Lf getinterval cvn dup % args [ l Lp /n /n 4 2 roll % args [ /n /n l Lp } //.rfnstring filenameforall pop % args [ l /n1 /n1 ... /nN /nN l } forall % args [ l /n1 /n1 ... /nN /nN pop .dicttomark % An easy way to exclude duplicates. % args <</n/n>> % { { pop } 0 get 2 index 2 get { cvs 0 } aload pop 5 index //.externalresourceforall {exec} 0 get % } 7 .localpackedarray cvx 3 2 roll pop % args { forall } 0 get currentdict end 2 .execn begin} bind/ResourceFileName { % /in (scr) exch //.rfnstring cvs % (scr) (n) /GenericResourcePathSep getsystemparam exch % (scr) (/) (n) Category .namestring % (scr) (/) (n) (c) 3 1 roll % (scr) (c) (/) (n)Lines 1–500 of 1048. Load more
% Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved. % % This software is provided AS-IS with no warranty, either express or % implied. % % This software is distributed under license and may not be copied, % modified or distributed except as expressly authorized under the terms % of the license contained in the file LICENSE in this distribution. % % For more information about licensing, please refer to % http://www.ghostscript.com/licensing/. For information on % commercial licensing, go to http://www.artifex.com/licensing/ or % contact Artifex Software, Inc., 101 Lucas Valley Road #110, % San Rafael, CA 94903, U.S.A., +1(415)492-9861. % $Id: gs_res.ps,v 1.38 2004/10/26 17:07:18 igor Exp $ % Initialization file for Level 2 resource machinery. % When this is run, systemdict is still writable, % but (almost) everything defined here goes into level2dict. level2dict begin (BEGIN RESOURCES) VMDEBUG % We keep track of (global) instances with another entry in the resource % dictionary, an .Instances dictionary. For categories with implicit % instances, the values in .Instances are the same as the keys; % for other categories, the values are [instance status size]. % Note that the dictionary that defines a resource category is stored % in global VM. The PostScript manual says that each category must % manage global and local instances separately. However, objects in % global VM other than systemdict can't reference objects in local VM. % This means that the resource category dictionary, which would otherwise be % the obvious place to keep track of the instances, can't be used to keep % track of local instances. Instead, we define a dictionary in local VM % called localinstancedict, in which the key is the category name and % the value is the analogue of .Instances for local instances. % We don't currently implement automatic resource unloading. % When and if we do, it should be hooked to the garbage collector. % However, Ed Taft of Adobe says their interpreters don't implement this % either, so we aren't going to worry about it for a while. currentglobal false setglobal systemdict begin /localinstancedict 5 dict .forcedef % localinstancedict is local, systemdict is global end true setglobal /.emptydict 0 dict readonly def setglobal % Resource category dictionaries have the following keys (those marked with % * are optional): % Standard, defined in the Red Book: % Category (name) % *InstanceType (name) % DefineResource % <key> <instance> DefineResource <instance> % UndefineResource % <key> UndefineResource - % FindResource % <key> FindResource <instance> % ResourceStatus % <key> ResourceStatus <status> <size> true % <key> ResourceStatus false % ResourceForAll % <template> <proc> <scratch> ResourceForAll - % *ResourceFileName % <key> <scratch> ResourceFileName <filename> % Additional, specific to our implementation: % .Instances (dictionary) % .LocalInstances % - .LocalInstances <dict> % .GetInstance % <key> .GetInstance <instance> -true- % <key> .GetInstance -false- % .CheckResource % <key> <value> .CheckResource <key> <value> <ok> % (or may give an error if not OK) % .DoLoadResource % <key> .DoLoadResource <key> (may give an error) % .LoadResource % <key> .LoadResource - (may give an error) % .ResourceFile % <key> .ResourceFile <file> -true- % <key> .ResourceFile <key> -false- % .ResourceFileStatus % <key> .ResourceFileStatus 2 <vmusage> -true- % <key> .ResourceFileStatus -false- % All the above procedures expect that the top dictionary on the d-stack % is the resource dictionary. % Define enough of the Category category so we can define other categories. % The dictionary we're about to create will become the Category % category definition dictionary. % .findcategory and .resourceexec are only called from within the % implementation of the resource 'operators', so they doesn't have to worry % about cleaning up the stack if they fail (the interpreter's stack % protection machinery for pseudo-operators takes care of this). /.findcategory { % <name> .findcategory - % (pushes the category on the dstack) /Category findresource begin } bind def /.resourceexec { % <key> /xxxResource .resourceexec - % (also pops the category from the dstack) load exec end } bind def % .getvminstance treats instances on disk as undefined. /.getvminstance { % <key> .getvminstance <instance> -true- % <key> .getvminstance -false- .GetInstance { dup 1 get 2 ne { true } { pop false } ifelse } { false } ifelse } bind def 20 dict begin % Standard entries /Category /Category def /InstanceType /dicttype def /DefineResource { .CheckResource { dup /Category 3 index cvlit .growput dup [ exch 0 -1 ] exch .Instances 4 2 roll put % Make the Category dictionary read-only. We will have to % use .forceput / .forcedef later to replace the dummy, % empty .Instances dictionary with the real one later. readonly } { /defineresource load /typecheck signalerror } ifelse } bind def /FindResource % (redefined below) { .Instances exch get 0 get } bind def % Additional entries /.Instances 30 dict def .Instances /Category [currentdict 0 -1] put /.LocalInstances 0 dict def /.GetInstance { .Instances exch .knownget } bind def /.CheckResource { dup gcheck currentglobal and { /DefineResource /FindResource /ResourceForAll /ResourceStatus /UndefineResource } { 2 index exch known and } forall not { /defineresource load /invalidaccess signalerror } if true } bind def .Instances end begin % for the base case of findresource (END CATEGORY) VMDEBUG % Define the resource operators. We use the "stack protection" feature of % odef to make sure the stacks are restored properly on an error. % This requires that the operators not pop anything from the stack until % they have executed their logic successfully. We can't make this % work for resourceforall, because the procedure it executes mustn't see % the operands of resourceforall on the stack, but we can make it work for % the others. % findresource is the only operator that needs to bind //Category. /findresource { % <key> <category> findresource <instance> 2 copy dup /Category eq { pop //Category 0 get begin } { .findcategory } ifelse /FindResource .resourceexec exch pop exch pop } bind end % .Instances of Category odef /defineresource { % <key> <instance> <category> defineresource <instance> 3 copy .findcategory currentdict /InstanceType known { dup type InstanceType ne { dup type /packedarraytype eq InstanceType /arraytype eq and not { /defineresource load /typecheck signalerror } if } if } if /DefineResource .resourceexec 4 1 roll pop pop pop } bind odef % We must prevent resourceforall from automatically restoring the stacks, % because we don't want the stacks restored if proc causes an error or % executes a 'stop'. On the other hand, resourceforall is defined in the % PLRM as an operator, so it must have type /operatortype. We hack this % by taking advantage of the fact that the interpreter optimizes tail % calls, so stack protection doesn't apply to the very last token of an % operator procedure. /resourceforall1 { % <template> <proc> <scratch> <category> resourceforall1 - dup /Category findresource begin /ResourceForAll load % Stack: <template> <proc> <scratch> <category> proc exch pop % pop the category exec end } bind def /resourceforall { % <template> <proc> <scratch> <category> resourceforall1 - //resourceforall1 exec % see above } bind odef /resourcestatus { % <key> <category> resourcestatus <status> <size> true % <key> <category> resourcestatus false 2 copy .findcategory /ResourceStatus .resourceexec { 4 2 roll pop pop true } { pop pop false } ifelse } bind odef /undefineresource { % <key> <category> undefineresource - 2 copy .findcategory /UndefineResource .resourceexec pop pop } bind odef % Define the system parameters used for the Generic implementation of % ResourceFileName. systemdict begin % - .default_resource_dir <string> /.default_resource_dir { .file_name_parent .file_name_directory_separator concatstrings (Resource) concatstrings /LIBPATH .systemvar { dup .file_name_current eq { pop } { 1 index false .file_name_combine { exch pop exit } { pop pop } ifelse } ifelse } forall } bind def % <path> <name> <string> .resource_dir_name <path> <name> <string> /.resource_dir_name { systemdict 2 index .knownget { exch pop systemdict 1 index undef } { dup () ne { .file_name_directory_separator concatstrings } if 2 index exch false .file_name_combine not { (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print = /.default_resource_dir /configurationerror .signalerror } if } ifelse } bind def currentdict /pssystemparams known not { /pssystemparams 10 dict readonly def } if pssystemparams begin .default_resource_dir /FontResourceDir (Font) .resource_dir_name readonly .forcedef % pssys'params is r-o /GenericResourceDir () .resource_dir_name readonly .forcedef % pssys'params is r-o pop % .default_resource_dir /GenericResourcePathSep .file_name_separator readonly .forcedef % pssys'params is r-o (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forcedef % pssys'params is r-o (%diskGenericResourceDir) cvn (/Resource/) readonly .forcedef % pssys'params is r-o end end % Check if GenericResourceDir presents in LIBPATH. % The value of GenericResourceDir must end with directory separator. % We use .file_name_combine to check it. % Comments use OpenVMS syntax, because it is the most complicated case. (x) pssystemparams /GenericResourcePathSep get (y) concatstrings concatstrings dup length % (x]y) l1 pssystemparams /GenericResourceDir get dup length exch % (x]y) l1 l2 (dir) 3 index true .file_name_combine not { exch (File name ) print print ( cant combine with ) print = /GenericResourceDir cvx /configurationerror signalerror } if dup length % (x]y) l1 l2 (dir.x]y) l 4 2 roll add % (x]y) (dir.x]y) l ll ne { (GenericResourceDir value does not end with directory separator.\n) = /GenericResourceDir cvx /configurationerror signalerror } if pop pop % Define the generic algorithm for computing resource file names. /.rfnstring 8192 string def /.genericrfn % <key> <scratch> <prefix> .genericrfn <filename> { 3 -1 roll //.rfnstring cvs concatstrings exch copy } bind def % Define a procedure for making a packed array in local VM. /.localpackedarray { % <obj1> ... <objn> <n> .localpackedarray <packedarray> .currentglobal false .setglobal 1 index 2 add 1 roll packedarray exch .setglobal } bind def % Define the Generic category. /Generic mark % Standard entries % We're still running in Level 1 mode, so dictionaries won't expand. % Leave room for the /Category entry. /Category null % Implement the body of Generic resourceforall for local, global, and % external cases. 'args' is [template proc scratch resdict]. /.enumerateresource { % <key> [- <proc> <scratch>] .enumerateresource - 1 index type dup /stringtype eq exch /nametype eq or { exch 1 index 2 get cvs exch } if % Use .setstackprotect to prevent the stacks from being restored if % an error occurs during execution of proc. 1 get false .setstackprotect exec true .setstackprotect } bind def /.localresourceforall { % <key> <value> <args> .localr'forall - exch pop 2 copy 0 get .stringmatch { .enumerateresource } { pop pop } ifelse } bind def /.globalresourceforall { % <key> <value> <args> .globalr'forall - exch pop 2 copy 0 get .stringmatch { dup 3 get begin .LocalInstances end 2 index known not { .enumerateresource } { pop pop } ifelse } { pop pop } ifelse } bind def /.externalresourceforall { % <filename> <len> <args> .externalr'forall - 3 1 roll 1 index length 1 index sub getinterval exch dup 3 get begin .Instances .LocalInstances end % Stack: key args insts localinsts 3 index known { pop pop pop } { 2 index known { pop pop } { .enumerateresource } ifelse } ifelse } bind def /DefineResource { .CheckResource { dup [ exch 0 -1 ] % Stack: key value instance currentglobal { false setglobal 2 index UndefineResource % remove local def if any true setglobal .Instances dup //.emptydict eq { pop 3 dict % As noted above, Category dictionaries are read-only, % so we have to use .forcedef here. /.Instances 1 index .forcedef % Category dict is read-only } if } { .LocalInstances dup //.emptydict eq { pop 3 dict localinstancedict Category 2 index put } if } ifelse % Stack: key value instance instancedict 3 index 2 index .growput % Now make the resource value read-only. 0 2 copy get { readonly } .internalstopped pop dup 4 1 roll put exch pop exch pop } { /defineresource load /typecheck signalerror } ifelse } .bind executeonly % executeonly to prevent access to .forcedef /UndefineResource { { dup 2 index .knownget { dup 1 get 1 ge { dup 0 null put 1 2 put pop pop } { pop exch .undef } ifelse } { pop pop } ifelse } currentglobal { 2 copy .Instances exch exec } if .LocalInstances exch exec } bind % Because of some badly designed code in Adobe's CID font downloader that % makes findresource and resourcestatus deliberately inconsistent with each % other, the default FindResource must not call ResourceStatus if there is % an instance of the desired name already defined in VM. /FindResource { dup .getvminstance { exch pop 0 get } { dup ResourceStatus { pop 1 gt { .DoLoadResource .getvminstance not { /findresource load /undefinedresource signalerror } if 0 get } { .GetInstance pop 0 get } ifelse } { /findresource load /undefinedresource signalerror } ifelse } ifelse } bind % Because of some badly designed code in Adobe's CID font downloader, the % definition of ResourceStatus for Generic and Font must be the same (!). % We patch around this by using an intermediate .ResourceFileStatus procedure. /ResourceStatus { dup .GetInstance { exch pop dup 1 get exch 2 get true } { .ResourceFileStatus } ifelse } bind /.ResourceFileStatus { .ResourceFile { closefile 2 -1 true } { pop false } ifelse } bind /ResourceForAll { % Construct a new procedure to hold the arguments. % All objects constructed here must be in local VM to avoid % a possible invalidaccess. currentdict 4 .localpackedarray % [template proc scratch resdict] % We must pop the resource dictionary off the dict stack % when doing the actual iteration, and restore it afterwards. .currentglobal not { .LocalInstances length 0 ne { % We must do local instances, and do them first. //.localresourceforall {exec} 0 get 3 .localpackedarray cvx .LocalInstances exch {forall} 0 get 1 index 0 get currentdict end 3 .execn begin } if } if % Do global instances next. //.globalresourceforall {exec} 0 get 3 .localpackedarray cvx .Instances exch cvx {forall} 0 get 1 index 0 get currentdict end 3 .execn begin mark % args [ Category .namestring .file_name_separator concatstrings 2 index 0 get % args [ (c/) (t) dup length 3 1 roll % args [ l (c/) (t) concatstrings % args [ l (c/t) [ /LIBPATH .systemvar 2 index .generate_dir_list_templates % args (t) [ l [(pt)] % also add on the Resources as specified by the GenericResourceDir [ currentsystemparams /GenericResourceDir get] counttomark 1 add index .generate_dir_list_templates % Resource files on OpenVMS requires a separate template (gs:[dir.*]*) [ currentsystemparams /GenericResourceDir get] counttomark 1 add index .file_name_separator (*) concatstrings concatstrings .generate_dir_list_templates ] exch pop { % args [ l (pt) dup length 2 index sub exch % args [ l Lp (pt) { % args [ l Lp (pf) dup length % args [ l Lp (pf) Lpf 2 index sub % args [ l Lp (pf) Lf 2 index exch % args [ l Lp (pf) Lp Lf getinterval cvn dup % args [ l Lp /n /n 4 2 roll % args [ /n /n l Lp } //.rfnstring filenameforall pop % args [ l /n1 /n1 ... /nN /nN l } forall % args [ l /n1 /n1 ... /nN /nN pop .dicttomark % An easy way to exclude duplicates. % args <</n/n>> % { { pop } 0 get 2 index 2 get { cvs 0 } aload pop 5 index //.externalresourceforall {exec} 0 get % } 7 .localpackedarray cvx 3 2 roll pop % args { forall } 0 get currentdict end 2 .execn begin } bind /ResourceFileName { % /in (scr) exch //.rfnstring cvs % (scr) (n) /GenericResourcePathSep getsystemparam exch % (scr) (/) (n) Category .namestring % (scr) (/) (n) (c) 3 1 roll % (scr) (c) (/) (n)