1048 lines · 33.9 KB · Text
RawDownload
%    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.