You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1186 lines
41 KiB

1 month ago
  1. % Copyright (C) 2001-2023 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % Initialization file for Level 2 resource machinery.
  16. % When this is run, systemdict is still writable,
  17. % but (almost) everything defined here goes into level2dict.
  18. level2dict begin
  19. (BEGIN RESOURCES) VMDEBUG
  20. % We keep track of (global) instances with another entry in the resource
  21. % dictionary, an .Instances dictionary. For categories with implicit
  22. % instances, the values in .Instances are the same as the keys;
  23. % for other categories, the values are [instance status size].
  24. % Note that the dictionary that defines a resource category is stored
  25. % in global VM. The PostScript manual says that each category must
  26. % manage global and local instances separately. However, objects in
  27. % global VM other than systemdict can't reference objects in local VM.
  28. % This means that the resource category dictionary, which would otherwise be
  29. % the obvious place to keep track of the instances, can't be used to keep
  30. % track of local instances. Instead, we define a dictionary in local VM
  31. % called localinstancedict, in which the key is the category name and
  32. % the value is the analogue of .Instances for local instances.
  33. % We don't currently implement automatic resource unloading.
  34. % When and if we do, it should be hooked to the garbage collector.
  35. % However, Ed Taft of Adobe says their interpreters don't implement this
  36. % either, so we aren't going to worry about it for a while.
  37. currentglobal //false setglobal
  38. systemdict /localinstancedict 5 dict
  39. .forceput % localinstancedict is local, systemdict is global
  40. //true setglobal
  41. /.emptydict 0 dict readonly def
  42. setglobal
  43. % Resource category dictionaries have the following keys (those marked with
  44. % * are optional):
  45. % Standard, defined in the Red Book:
  46. % Category (name)
  47. % *InstanceType (name)
  48. % DefineResource
  49. % <key> <instance> DefineResource <instance>
  50. % UndefineResource
  51. % <key> UndefineResource -
  52. % FindResource
  53. % <key> FindResource <instance>
  54. % ResourceStatus
  55. % <key> ResourceStatus <status> <size> true
  56. % <key> ResourceStatus false
  57. % ResourceForAll
  58. % <template> <proc> <scratch> ResourceForAll -
  59. % *ResourceFileName
  60. % <key> <scratch> ResourceFileName <filename>
  61. % Additional, specific to our implementation:
  62. % .Instances (dictionary)
  63. % .LocalInstances
  64. % - .LocalInstances <dict>
  65. % .GetInstance
  66. % <key> .GetInstance <instance> -true-
  67. % <key> .GetInstance -false-
  68. % .CheckResource
  69. % <key> <value> .CheckResource <key> <value> <ok>
  70. % (or may give an error if not OK)
  71. % .DoLoadResource
  72. % <key> .DoLoadResource <key> (may give an error)
  73. % .LoadResource
  74. % <key> .LoadResource - (may give an error)
  75. % .ResourceFile
  76. % <key> .ResourceFile <file> -true-
  77. % <key> .ResourceFile <key> -false-
  78. % .ResourceFileStatus
  79. % <key> .ResourceFileStatus 2 <vmusage> -true-
  80. % <key> .ResourceFileStatus -false-
  81. % All the above procedures expect that the top dictionary on the d-stack
  82. % is the resource dictionary.
  83. % Define enough of the Category category so we can define other categories.
  84. % The dictionary we're about to create will become the Category
  85. % category definition dictionary.
  86. % .findcategory and .resourceexec are only called from within the
  87. % implementation of the resource 'operators', so they don't have to worry
  88. % about cleaning up the stack if they fail (the interpreter's stack
  89. % protection machinery for pseudo-operators takes care of this).
  90. % Note that all places that look up categories must use .findcategory
  91. % so that the command in case of error will be correct rather than an
  92. % internal invocation of findresource.
  93. /.findcategory { % <name> .findcategory -
  94. % (pushes the category on the dstack)
  95. /Category .findresource begin % note: *not* findresource
  96. } .internalbind def
  97. % If an error occurs within the logic of a resource operator (after operand
  98. % acquisition and checking), the Adobe interpreters report the operator name,
  99. % not the operator object, as the command in $error. For this reason, and
  100. % this reason only, all resource operators must wrap their logic code in
  101. % /<opername> cvx { ...logic... } .errorexec
  102. % The Category resource signals /undefined rather than /undefinedresource,
  103. % both when referenced implicitly (to look up the category for a general
  104. % resource operation) and when it is accessed directly (/Category /xxx
  105. % findresource). Because of this, all resource operators must use
  106. % .undefinedresource rather than signalling undefinedresource directly.
  107. /.undefinedresource { % <command> .undefinedresource -
  108. /Category dup load eq { /undefined } { /undefinedresource } ifelse
  109. signaloperror
  110. } .internalbind def
  111. /.resourceexec { % <key> /xxxResource .resourceexec -
  112. % (also pops the category from the dstack)
  113. load exec end
  114. } .internalbind def
  115. % .getvminstance treats instances on disk as undefined.
  116. /.getvminstance { % <key> .getvminstance <instance> -true-
  117. % <key> .getvminstance -false-
  118. .GetInstance {
  119. dup 1 get 2 ne { //true } { pop //false } ifelse
  120. } {
  121. //false
  122. } ifelse
  123. } .internalbind def
  124. 20 dict begin
  125. % Standard entries
  126. /Category /Category def
  127. /InstanceType /dicttype def
  128. /DefineResource {
  129. .CheckResource {
  130. dup /Category 3 index cvlit .growput
  131. dup [ exch 0 -1 ] exch
  132. .Instances 4 2 roll put
  133. % Make the Category dictionary read-only. We will have to
  134. % use .forceput / .forceput later to replace the dummy,
  135. % empty .Instances dictionary with the real one later.
  136. readonly
  137. }{
  138. /defineresource cvx /typecheck signaloperror
  139. } ifelse
  140. } .internalbind odef
  141. /FindResource % (redefined below)
  142. { .Instances exch get 0 get
  143. } .internalbind def
  144. % Additional entries
  145. /.Instances 30 dict def
  146. .Instances /Category [currentdict 0 -1] put
  147. /.LocalInstances 0 dict def
  148. /.GetInstance
  149. { .Instances exch .knownget
  150. } .internalbind def
  151. /.CheckResource
  152. { dup gcheck currentglobal and
  153. { /DefineResource /FindResource /ResourceForAll /ResourceStatus
  154. /UndefineResource }
  155. { 2 index exch known and }
  156. forall
  157. not { /defineresource cvx /invalidaccess signaloperror } if
  158. //true
  159. } .internalbind def
  160. .Instances end begin % for the base case of findresource
  161. (END CATEGORY) VMDEBUG
  162. % Define the resource operators. We use the "stack protection" feature of
  163. % odef to make sure the stacks are restored properly on an error.
  164. % This requires that the operators not pop anything from the stack until
  165. % they have executed their logic successfully. We can't make this
  166. % work for resourceforall, because the procedure it executes mustn't see
  167. % the operands of resourceforall on the stack, but we can make it work for
  168. % the others.
  169. % findresource is the only operator that needs to bind //Category.
  170. % We define its contents as a separate procedure so that .findcategory
  171. % can use it without entering another level of pseudo-operator.
  172. /.findresource { % <key> <category> findresource <instance>
  173. 2 copy dup /Category eq
  174. { pop //Category 0 get begin } { //.findcategory exec } ifelse
  175. /FindResource //.resourceexec exec exch pop exch pop
  176. } .internalbind
  177. end % .Instances of Category
  178. def
  179. /findresource {
  180. % See above re .errorexec.
  181. 1 .argindex % also catch stackunderflow
  182. dup type /stringtype eq { cvn } if % for CET 23-13-04
  183. 3 1 roll exch pop
  184. dup type /nametype ne {
  185. /findresource .systemvar /typecheck signalerror
  186. } if
  187. /findresource cvx //.findresource .errorexec
  188. } .internalbind odef
  189. /defineresource { % <key> <instance> <category> defineresource <instance>
  190. 2 .argindex 2 index 2 index % catch stackunderflow
  191. % See above re .errorexec.
  192. /defineresource cvx {
  193. //.findcategory exec
  194. currentdict /InstanceType known {
  195. dup type InstanceType ne {
  196. dup type /packedarraytype eq InstanceType /arraytype eq and
  197. not { /defineresource cvx /typecheck signaloperror } if
  198. } if
  199. } if
  200. /DefineResource //.resourceexec exec
  201. 4 1 roll pop pop pop
  202. } .errorexec
  203. } .internalbind odef
  204. % We must prevent resourceforall from automatically restoring the stacks,
  205. % because we don't want the stacks restored if proc causes an error or
  206. % executes a 'stop'. On the other hand, resourceforall is defined in the
  207. % PLRM as an operator, so it must have type /operatortype. We hack this
  208. % by taking advantage of the fact that the interpreter optimizes tail
  209. % calls, so stack protection doesn't apply to the very last token of an
  210. % operator procedure.
  211. /resourceforall1 { % <template> <proc> <scratch> <category> resourceforall1 -
  212. dup //.findcategory exec
  213. /ResourceForAll load
  214. % Stack: <template> <proc> <scratch> <category> proc
  215. exch pop % pop the category
  216. exec end
  217. } .forcebind def
  218. /resourceforall { % <template> <proc> <scratch> <category> resourceforall1 -
  219. //resourceforall1 exec % see above
  220. } .forcebind odef
  221. /resourcestatus { % <key> <category> resourcestatus <status> <size> true
  222. % <key> <category> resourcestatus false
  223. {
  224. 0 .argindex type /nametype ne {
  225. % CET 23-26 wants typecheck here, not undefineresource that happens
  226. % without the check.
  227. /resourcestatus cvx /typecheck signalerror
  228. } if
  229. 2 copy //.findcategory exec /ResourceStatus //.resourceexec exec
  230. { 4 2 roll pop pop //true } { pop pop //false } ifelse
  231. } stopped {
  232. % Although resourcestatus is an operator, Adobe uses executable name
  233. % for error reporting. CET 23-26
  234. /resourcestatus cvx $error /errorname get signalerror
  235. } if
  236. } .forcebind odef
  237. /undefineresource { % <key> <category> undefineresource -
  238. 0 .argindex type /nametype ne {
  239. /undefinedresource cvx /typecheck signaloperror
  240. } if
  241. 1 .argindex 1 index % catch stackunderflow
  242. { //.findcategory exec /UndefineResource //.resourceexec exec pop pop
  243. } stopped {
  244. % Although undefineresource is an operator, Adobe uses executable name
  245. % here but uses operator for the errors above. CET 23-33
  246. /undefineresource cvx $error /errorname get signalerror
  247. } if
  248. } .forcebind odef
  249. % Define the system parameters used for the Generic implementation of
  250. % ResourceFileName.
  251. systemdict begin
  252. % - .default_resource_dir <string>
  253. /.default_resource_dir {
  254. /LIBPATH .systemvar {
  255. dup .file_name_current eq {
  256. pop
  257. } {
  258. (Resource) rsearch {
  259. exch concatstrings
  260. exch pop
  261. .file_name_separator concatstrings exit
  262. } {
  263. pop
  264. } ifelse
  265. } ifelse
  266. } forall
  267. } .internalbind def
  268. % <path> <name> <string> .resource_dir_name <path> <name> <string>
  269. /.resource_dir_name
  270. { systemdict 2 index .knownget {
  271. exch pop
  272. systemdict 1 index undef
  273. } {
  274. dup () ne {
  275. .file_name_directory_separator concatstrings
  276. } if
  277. 2 index exch //false
  278. .file_name_combine not {
  279. (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print =
  280. /.default_resource_dir cvx /configurationerror signalerror
  281. } if
  282. } ifelse
  283. } .internalbind def
  284. currentdict /pssystemparams known not {
  285. /pssystemparams 10 dict readonly def
  286. } if
  287. pssystemparams begin
  288. //.default_resource_dir exec
  289. /FontResourceDir (Font) //.resource_dir_name exec
  290. readonly currentdict 3 1 roll .forceput % pssys'params is r-o
  291. /GenericResourceDir () //.resource_dir_name exec
  292. readonly currentdict 3 1 roll .forceput % pssys'params is r-o
  293. pop % .default_resource_dir
  294. /GenericResourcePathSep
  295. .file_name_separator readonly currentdict 3 1 roll .forceput % pssys'params is r-o
  296. currentdict (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forceput % pssys'params is r-o
  297. currentdict (%diskGenericResourceDir) cvn (/Resource/) readonly .forceput % pssys'params is r-o
  298. end
  299. end
  300. % Check if GenericResourceDir presents in LIBPATH.
  301. % The value of GenericResourceDir must end with directory separator.
  302. % We use .file_name_combine to check it.
  303. % Comments use OpenVMS syntax, because it is the most complicated case.
  304. (x) pssystemparams /GenericResourcePathSep get
  305. (y) concatstrings concatstrings dup length % (x]y) l1
  306. pssystemparams /GenericResourceDir get dup length exch % (x]y) l1 l2 (dir)
  307. 3 index //true .file_name_combine not {
  308. exch
  309. (File name ) print print ( cant combine with ) print =
  310. /GenericResourceDir cvx /configurationerror signaloperror
  311. } if
  312. dup length % (x]y) l1 l2 (dir.x]y) l
  313. 4 2 roll add % (x]y) (dir.x]y) l ll
  314. ne {
  315. (GenericResourceDir value does not end with directory separator.\n) =
  316. /GenericResourceDir cvx /configurationerror signaloperror
  317. } if
  318. pop pop
  319. pssystemparams dup /GenericResourceDir get exch /GenericResourcePathSep get
  320. (Init) exch (gs_init.ps) concatstrings concatstrings concatstrings
  321. status {
  322. pop pop pop pop
  323. } {
  324. (\n*** Warning: GenericResourceDir doesn't point to a valid resource directory.) =
  325. ( the -sGenericResourceDir=... option can be used to set this.\n) =
  326. flush
  327. } ifelse
  328. % Define the generic algorithm for computing resource file names.
  329. /.rfnstring 8192 string def
  330. /.genericrfn % <key> <scratch> <prefix> .genericrfn <filename>
  331. { 3 -1 roll //.rfnstring cvs concatstrings exch copy
  332. } .internalbind def
  333. % Define the Generic category.
  334. /Generic mark
  335. % Standard entries
  336. % We're still running in Level 1 mode, so dictionaries won't expand.
  337. % Leave room for the /Category entry.
  338. /Category //null
  339. % Implement the body of Generic resourceforall for local, global, and
  340. % external cases. 'args' is [template proc scratch resdict].
  341. /.enumerateresource { % <key> [- <proc> <scratch>] .enumerateresource -
  342. 1 index type dup /stringtype eq exch /nametype eq or {
  343. exch 1 index 2 get cvs exch
  344. } if
  345. % Use .setstackprotect to prevent the stacks from being restored if
  346. % an error occurs during execution of proc.
  347. 1 get //false .setstackprotect exec //true .setstackprotect
  348. } .internalbind def
  349. /.localresourceforall { % <key> <value> <args> .localr'forall -
  350. exch pop
  351. 2 copy 0 get .stringmatch { //.enumerateresource exec } { pop pop } ifelse
  352. } .internalbind def
  353. /.globalresourceforall { % <key> <value> <args> .globalr'forall -
  354. exch pop
  355. 2 copy 0 get .stringmatch {
  356. dup 3 get begin .LocalInstances end 2 index known not {
  357. //.enumerateresource exec
  358. } {
  359. pop pop
  360. } ifelse
  361. } {
  362. pop pop
  363. } ifelse
  364. } .internalbind def
  365. /.externalresourceforall { % <filename> <len> <args> .externalr'forall -
  366. 3 1 roll 1 index length 1 index sub getinterval exch
  367. dup 3 get begin .Instances .LocalInstances end
  368. % Stack: key args insts localinsts
  369. 3 index known {
  370. pop pop pop
  371. } {
  372. 2 index known { pop pop } { //.enumerateresource exec } ifelse
  373. } ifelse
  374. } .internalbind def
  375. /DefineResource dup {
  376. .CheckResource
  377. { dup [ exch 0 -1 ]
  378. % Stack: key value instance
  379. currentglobal
  380. { //false setglobal 2 index UndefineResource % remove local def if any
  381. //true setglobal
  382. .Instances dup //.emptydict eq {
  383. pop 3 dict
  384. % As noted above, Category dictionaries are read-only,
  385. % so we have to use .forceput here.
  386. currentdict /.Instances 2 index .forceput % Category dict is read-only
  387. } executeonly if
  388. } executeonly
  389. { .LocalInstances dup //.emptydict eq
  390. { pop 3 dict localinstancedict Category 2 index put
  391. }
  392. if
  393. }
  394. ifelse
  395. % Stack: key value instance instancedict
  396. 3 index 2 index .growput
  397. % Now make the resource value read-only.
  398. 0 2 copy get { readonly } //.internalstopped exec pop
  399. dup 4 1 roll put exch pop exch pop
  400. } executeonly
  401. { /defineresource cvx /typecheck signaloperror
  402. }
  403. ifelse
  404. } .forcebind .makeoperator % executeonly to prevent access to .forceput
  405. /UndefineResource
  406. { { dup 2 index .knownget
  407. { dup 1 get 1 ge
  408. { dup 0 //null put 1 2 put pop pop }
  409. { pop exch .undef }
  410. ifelse
  411. }
  412. { pop pop
  413. }
  414. ifelse
  415. }
  416. currentglobal
  417. { 2 copy .Instances exch exec
  418. }
  419. if .LocalInstances exch exec
  420. } .forcebind
  421. % Because of some badly designed code in Adobe's CID font downloader that
  422. % makes findresource and resourcestatus deliberately inconsistent with each
  423. % other, the default FindResource must not call ResourceStatus if there is
  424. % an instance of the desired name already defined in VM.
  425. /FindResource {
  426. dup //null eq {
  427. % CET 13-06 wants /typecheck for "null findencoding" but
  428. % .knownget doesn't fail on null
  429. /findresource cvx /typecheck signaloperror
  430. } if
  431. dup //.getvminstance exec {
  432. exch pop 0 get
  433. } {
  434. dup ResourceStatus {
  435. pop 1 gt {
  436. .DoLoadResource //.getvminstance exec not {
  437. /findresource cvx //.undefinedresource exec
  438. } if 0 get
  439. } {
  440. .GetInstance pop 0 get
  441. } ifelse
  442. } {
  443. /findresource cvx //.undefinedresource exec
  444. } ifelse
  445. } ifelse
  446. } .forcebind
  447. % Because of some badly designed code in Adobe's CID font downloader, the
  448. % definition of ResourceStatus for Generic and Font must be the same (!).
  449. % We patch around this by using an intermediate .ResourceFileStatus procedure.
  450. /ResourceStatus {
  451. dup .GetInstance {
  452. exch pop dup 1 get exch 2 get //true
  453. } {
  454. .ResourceFileStatus
  455. } ifelse
  456. } .forcebind
  457. /.ResourceFileStatus {
  458. .ResourceFile { closefile 2 -1 //true } { pop //false } ifelse
  459. } .internalbind
  460. /ResourceForAll {
  461. % Construct a new procedure to hold the arguments.
  462. % All objects constructed here must be in local VM to avoid
  463. % a possible invalidaccess.
  464. currentdict 4 .localvmpackedarray % [template proc scratch resdict]
  465. % We must pop the resource dictionary off the dict stack
  466. % when doing the actual iteration, and restore it afterwards.
  467. .currentglobal not {
  468. .LocalInstances length 0 ne {
  469. % We must do local instances, and do them first.
  470. //.localresourceforall {exec} 0 get 3 .localvmpackedarray cvx
  471. .LocalInstances exch {forall} 0 get 1 index 0 get
  472. currentdict end 3 .execn begin
  473. } if
  474. } if
  475. % Do global instances next.
  476. //.globalresourceforall {exec} 0 get 3 .localvmpackedarray cvx
  477. .Instances exch cvx {forall} 0 get 1 index 0 get
  478. currentdict end 3 .execn begin
  479. mark % args [
  480. Category .namestring .file_name_separator concatstrings
  481. 2 index 0 get % args [ (c/) (t)
  482. 1 index length 3 1 roll % args [ l (c/) (t)
  483. concatstrings % args [ l (c/t)
  484. [
  485. //true /LIBPATH .systemvar 3 index
  486. .generate_dir_list_templates_with_length % args (t) [ l [(pt) Lp ...]
  487. % also add on the Resources as specified by the GenericResourceDir
  488. //true [ currentsystemparams /GenericResourceDir get]
  489. counttomark 1 add index .generate_dir_list_templates_with_length
  490. ] exch pop
  491. dup length 1 sub 0 exch 2 exch { % args [ l [] i
  492. 2 copy get % args [ l [] i (pt)
  493. exch 2 index exch 1 add get % args [ l [] (pt) Lp
  494. 3 index add
  495. exch % args [ l [] Lp (pt)
  496. { % args [ l [] Lp (pf)
  497. dup length % args [ l [] Lp (pf) Lpf
  498. 2 index sub % args [ l [] Lp (pf) Lf
  499. 2 index exch % args [ l [] Lp (pf) Lp Lf
  500. getinterval cvn dup % args [ l [] Lp /n /n
  501. 5 2 roll % args [ /n /n l [] Lp
  502. } //.rfnstring filenameforall
  503. pop % args [ /n1 /n1 ... /nN /nN l []
  504. } for % args [ /n1 /n1 ... /nN /nN l []
  505. pop pop
  506. .dicttomark % An easy way to exclude duplicates. % args <</n/n>>
  507. % {
  508. { pop } 0 get
  509. 2 index 2 get { cvs 0 } aload pop 5 index
  510. //.externalresourceforall {exec} 0 get
  511. % }
  512. 7 .localvmpackedarray cvx
  513. 3 2 roll pop % args
  514. { forall } 0 get
  515. currentdict end 2 .execn begin
  516. } .forcebind
  517. /ResourceFileName { % /in (scr) --> (p/c/n)
  518. exch //.rfnstring cvs % (scr) (n)
  519. /GenericResourcePathSep getsystemparam exch % (scr) (/) (n)
  520. Category .namestring % (scr) (/) (n) (c)
  521. 3 1 roll % (scr) (c) (/) (n)
  522. concatstrings concatstrings % (scr) (c/n)
  523. /GenericResourceDir getsystemparam 1 index % (scr) (c/n) (p/) (c/n)
  524. concatstrings % (scr) (c/n) (p/c/n)
  525. dup status {
  526. pop pop pop pop exch pop % (scr) (p/c/n)
  527. } {
  528. exch
  529. .libfile
  530. {//true}
  531. {
  532. pop dup .libfile
  533. {//true}
  534. {//false}
  535. ifelse
  536. } ifelse
  537. {
  538. dup .filename pop
  539. exch closefile
  540. exch pop
  541. }
  542. {pop}
  543. ifelse
  544. } ifelse
  545. exch copy % (p/c/n)
  546. } .forcebind
  547. % Additional entries
  548. % Unfortunately, we can't create the real .Instances dictionary now,
  549. % because if someone copies the Generic category (which pp. 95-96 of the
  550. % 2nd Edition Red Book says is legitimate), they'll wind up sharing
  551. % the .Instances. Instead, we have to create .Instances on demand,
  552. % just like the entry in localinstancedict.
  553. % We also have to prevent anyone from creating instances of Generic itself.
  554. /.Instances //.emptydict
  555. /.LocalInstances
  556. { localinstancedict Category .knownget not { //.emptydict } if
  557. } .internalbind
  558. /.GetInstance
  559. { currentglobal
  560. { .Instances exch .knownget }
  561. { .LocalInstances 1 index .knownget
  562. { exch pop //true }
  563. { .Instances exch .knownget }
  564. ifelse
  565. }
  566. ifelse
  567. } .internalbind
  568. /.CheckResource
  569. { //true
  570. } .internalbind
  571. /.vmused {
  572. % - .vmused <usedvalue>
  573. % usedvalue = vmstatus in global + vmstatus in local.
  574. 0 2 {
  575. .currentglobal not .setglobal
  576. vmstatus pop exch pop add
  577. } repeat
  578. } .internalbind odef
  579. /.DoLoadResource {
  580. % .LoadResource may push entries on the operand stack.
  581. % It is an undocumented feature of Adobe implementations,
  582. % which we must match for the sake of some badly written
  583. % font downloading code, that such entries are popped
  584. % automatically.
  585. count 1 index cvlit //.vmused
  586. % Stack: key count litkey memused
  587. {.LoadResource} 4 1 roll 4 .execn
  588. % Stack: ... count key memused
  589. //.vmused exch sub
  590. 1 index //.getvminstance exec not {
  591. pop dup //.undefinedresource exec % didn't load
  592. } if
  593. dup 1 1 put
  594. 2 3 -1 roll put
  595. % Stack: ... count key
  596. exch count 1 sub exch sub {exch pop} repeat
  597. } .internalbind
  598. /.LoadResource
  599. { dup .ResourceFile
  600. { exch pop currentglobal
  601. { //.runresource exec }
  602. { //true setglobal { //.runresource exec } stopped //false setglobal { stop } if }
  603. ifelse
  604. }
  605. { dup //.undefinedresource exec
  606. }
  607. ifelse
  608. } .internalbind
  609. /.ResourceFile
  610. {
  611. Category //.rfnstring cvs length % key l
  612. dup //.rfnstring dup length 2 index sub % key l l (buf) L-l
  613. 3 2 roll exch getinterval % key l ()
  614. .file_name_directory_separator exch copy length add % key l1
  615. dup //.rfnstring dup length 2 index sub % key l1 l1 (buf) L-l
  616. 3 2 roll exch getinterval % key l1 ()
  617. 2 index exch cvs length add % key l2
  618. //.rfnstring exch 0 exch getinterval % key (relative_path)
  619. .libfile {
  620. exch pop //true
  621. } {
  622. pop
  623. currentdict /ResourceFileName known {
  624. mark 1 index //.rfnstring { ResourceFileName } //.internalstopped exec {
  625. cleartomark //false
  626. } {
  627. (r) { file } //.internalstopped exec {
  628. cleartomark //false
  629. } {
  630. exch pop exch pop //true
  631. } ifelse
  632. } ifelse
  633. } {
  634. pop //false
  635. } ifelse
  636. } ifelse
  637. } .internalbind
  638. .dicttomark
  639. /Category defineresource pop
  640. % Fill in the rest of the Category category.
  641. /Category /Category findresource dup
  642. /Generic /Category findresource begin {
  643. /FindResource /ResourceForAll /ResourceStatus /.ResourceFileStatus
  644. /UndefineResource /ResourceFileName
  645. /.ResourceFile /.LoadResource /.DoLoadResource
  646. } { dup load put dup } forall
  647. pop readonly pop end
  648. (END GENERIC) VMDEBUG
  649. % Define the fixed categories.
  650. mark
  651. % Non-Type categories with existing entries.
  652. /ColorSpaceFamily
  653. { } % These must be deferred, because optional features may add some.
  654. /Emulator
  655. mark EMULATORS { <00> search { exch pop cvn exch }{ cvn exit } ifelse } .forcebind loop //.packtomark exec
  656. /Filter
  657. { } % These must be deferred, because optional features may add some.
  658. /IODevice
  659. % Loop until the .getiodevice gets a rangecheck.
  660. errordict /rangecheck 2 copy get
  661. errordict /rangecheck { pop stop } put % pop the command
  662. mark 0 { {
  663. dup .getiodevice dup //null eq { pop } { exch } ifelse 1 add
  664. } loop} //.internalstopped exec
  665. pop pop pop //.packtomark exec
  666. 4 1 roll put
  667. //.clearerror exec
  668. % Type categories listed in the Red Book.
  669. /ColorRenderingType
  670. { } % These must be deferred, because optional features may add some.
  671. /FMapType
  672. { } % These must be deferred, because optional features may add some.
  673. /FontType
  674. { } % These must be deferred, because optional features may add some.
  675. /FormType
  676. { } % These must be deferred, because optional features may add some.
  677. /HalftoneType
  678. { } % These must be deferred, because optional features may add some.
  679. /ImageType
  680. { } % Deferred, optional features may add some.
  681. /PatternType
  682. { } % Deferred, optional features may add some.
  683. % Type categories added since the Red Book.
  684. /setsmoothness where {
  685. pop /ShadingType { } % Deferred, optional features may add some.
  686. } if
  687. counttomark 2 idiv
  688. { mark
  689. % Standard entries
  690. % We'd like to prohibit defineresource,
  691. % but because optional features may add entries, we can't.
  692. % We can at least require that the key and value match.
  693. /DefineResource
  694. { currentglobal not
  695. { /defineresource cvx /invalidaccess signaloperror }
  696. { 2 copy ne
  697. { /defineresource cvx /rangecheck signaloperror }
  698. { dup .Instances 4 -2 roll .growput }
  699. ifelse
  700. }
  701. ifelse
  702. } .internalbind
  703. /UndefineResource
  704. { /undefineresource cvx /invalidaccess signaloperror } .internalbind
  705. /FindResource
  706. { .Instances 1 index .knownget
  707. { exch pop }
  708. { /findresource cvx //.undefinedresource exec }
  709. ifelse
  710. } .internalbind
  711. /ResourceStatus
  712. { .Instances exch known { 0 0 //true } { //false } ifelse } .internalbind
  713. /ResourceForAll
  714. /Generic //.findcategory exec /ResourceForAll load end
  715. % Additional entries
  716. counttomark 2 add -1 roll
  717. dup length dict dup begin exch { dup def } forall end
  718. % We'd like to make the .Instances readonly here,
  719. % but because optional features may add entries, we can't.
  720. /.Instances exch
  721. /.LocalInstances % used by ResourceForAll
  722. 0 dict def
  723. .dicttomark /Category defineresource pop
  724. } repeat pop
  725. (END FIXED) VMDEBUG
  726. % Define the other built-in categories.
  727. /.definecategory % <name> -mark- <key1> ... <valuen> .definecategory -
  728. { counttomark 2 idiv 2 add % .Instances, Category
  729. /Generic /Category findresource dup maxlength 3 -1 roll add
  730. dict .copydict begin
  731. counttomark 2 idiv { def } repeat pop % pop the mark
  732. currentdict end /Category defineresource pop
  733. } .internalbind def
  734. /ColorRendering mark /InstanceType /dicttype .definecategory
  735. % ColorSpace is defined below
  736. % Encoding is defined below
  737. % Font is defined below
  738. /Form mark /InstanceType /dicttype .definecategory
  739. /Halftone mark /InstanceType /dicttype .definecategory
  740. /Pattern mark /InstanceType /dicttype .definecategory
  741. /ProcSet mark /InstanceType /dicttype .definecategory
  742. % Added since the Red Book:
  743. /ControlLanguage mark /InstanceType /dicttype .definecategory
  744. /HWOptions mark /InstanceType /dicttype .definecategory
  745. /Localization mark /InstanceType /dicttype .definecategory
  746. /PDL mark /InstanceType /dicttype .definecategory
  747. % CIDFont, CIDMap, and CMap are defined in gs_cidfn.ps
  748. % FontSet is defined in gs_cff.ps
  749. % IdiomSet is defined in gs_ll3.ps
  750. % InkParams and TrapParams are defined in gs_trap.ps
  751. (END MISC) VMDEBUG
  752. % Define the OutputDevice category.
  753. /OutputDevice mark
  754. /InstanceType /dicttype
  755. /.Instances mark
  756. %% devicedict is not created yet so here we employ a technique similar to
  757. %% that used to create it, in order to get the device names. We run a loop
  758. %% executing .getdevice with incremental numbers until we get an error.
  759. %% The devicedict creation only stops on a rangecheck, we stop on any error.
  760. %% We need to use .internalstopped, not stopped or we get an invalidacces
  761. %% later in this file. Instances of /OutputDevice are dictionaries, and the
  762. %% only required key is a /PageSize. The array of 4 numbers are minimum to
  763. %% maximum and are matches for the Adobe Acrobat Distiller values.
  764. 0
  765. {
  766. {dup .getdevice .devicename cvn 1 dict dup /PageSize [1 1 14400 14400] put [exch readonly 0 -1] 3 -1 roll 1 add} loop
  767. } //.internalstopped exec pop
  768. %% Remove the count, and the duplicate, from the stack
  769. pop pop
  770. .dicttomark
  771. .definecategory
  772. % Define the ColorSpace category.
  773. /.defaultcsnames mark
  774. /DefaultGray 0
  775. /DefaultRGB 1
  776. /DefaultCMYK 2
  777. .dicttomark readonly def
  778. % The "hooks" are no-ops here, redefined in LL3.
  779. /.definedefaultcs { % <index> <value> .definedefaultcs -
  780. pop pop
  781. } .internalbind def
  782. /.undefinedefaultcs { % <index> .undefinedefaultcs -
  783. pop
  784. } .internalbind def
  785. /ColorSpace mark
  786. /InstanceType /arraytype
  787. % We keep track of whether there are any local definitions for any of
  788. % the Default keys. This information must get saved and restored in
  789. % parallel with the local instance dictionary, so it must be stored in
  790. % local VM.
  791. userdict /.localcsdefaults //false put
  792. /DefineResource {
  793. 2 copy /Generic /Category findresource /DefineResource get exec
  794. exch pop
  795. exch //.defaultcsnames exch .knownget {
  796. 1 index //.definedefaultcs exec
  797. currentglobal not { .userdict /.localcsdefaults //true put } if
  798. } if
  799. } .internalbind
  800. /UndefineResource {
  801. dup /Generic /Category findresource /UndefineResource get exec
  802. //.defaultcsnames 1 index .knownget {
  803. % Stack: resname index
  804. currentglobal {
  805. //.undefinedefaultcs exec pop
  806. } {
  807. % We removed the local definition, but there might be a global one.
  808. exch .GetInstance {
  809. 0 get //.definedefaultcs exec
  810. } {
  811. //.undefinedefaultcs exec
  812. } ifelse
  813. % Recompute .localcsdefaults by scanning. This is rarely needed.
  814. .userdict /.localcsdefaults //false //.defaultcsnames {
  815. pop .LocalInstances exch known { pop //true exit } if
  816. } forall put
  817. } ifelse
  818. } {
  819. pop
  820. } ifelse
  821. } .internalbind
  822. .definecategory % ColorSpace
  823. % Define the Encoding category.
  824. /Encoding mark
  825. /InstanceType /arraytype
  826. % Handle already-registered encodings, including lazily loaded encodings
  827. % that aren't loaded yet.
  828. /.Instances mark
  829. EncodingDirectory
  830. {dup length 256 eq { [ exch readonly 0 -1 ] } { pop [//null 2 -1] } ifelse
  831. } forall
  832. .dicttomark
  833. /.ResourceFileDict mark
  834. EncodingDirectory
  835. { dup length 256 eq { pop pop } { 0 get } ifelse
  836. } forall
  837. .dicttomark
  838. /ResourceFileName
  839. { .ResourceFileDict 2 index .knownget
  840. { exch copy exch pop }
  841. { /Generic /Category findresource /ResourceFileName get exec }
  842. ifelse
  843. } .internalbind
  844. .definecategory % Encoding
  845. % Make placeholders in level2dict for the redefined Encoding operators,
  846. % so that they will be swapped properly when we switch language levels.
  847. /.findencoding /.findencoding load def
  848. /findencoding /findencoding load def
  849. /.defineencoding /.defineencoding load def
  850. (END ENCODING) VMDEBUG
  851. % Define the Font category.
  852. /.fontstatusaux { % <fontname> .fontstatusaux <fontname> <found>
  853. { % Create a loop context just so we can exit it early.
  854. % Check Fontmap.
  855. Fontmap 1 index .knownget
  856. { //true }
  857. { .nativeFontmap 1 index .knownget } ifelse
  858. {
  859. {
  860. dup type /nametype eq {
  861. .fontstatus { pop //null exit } if
  862. } {
  863. dup type /dicttype eq {/Path .knownget pop} if
  864. dup type /stringtype eq {
  865. findlibfile { closefile pop //null exit } if pop
  866. } {
  867. % Procedure, assume success.
  868. pop //null exit
  869. } ifelse
  870. } ifelse
  871. } forall dup //null eq { pop //true exit } if
  872. } if
  873. dup / eq { //false exit } if % / throws an error from findlibfile
  874. % Convert names to strings; give up on other types.
  875. dup type /nametype eq { .namestring } if
  876. dup type /stringtype ne { //false exit } if
  877. % Check the resource directory.
  878. dup //.fonttempstring /FontResourceDir getsystemparam .genericrfn
  879. status {
  880. pop pop pop pop //true exit
  881. } if
  882. % Check for a file on the search path with the same name
  883. % as the font.
  884. findlibfile { closefile //true exit } if
  885. % Scan a FONTPATH directory and try again.
  886. //.scannextfontdir exec not { //false exit } if
  887. } loop
  888. } .internalbind def
  889. /.fontstatus { % <fontname> .fontstatus <fontname> <found>
  890. //.fontstatusaux exec
  891. { //true }
  892. {
  893. .buildnativefontmap
  894. { //.fontstatusaux exec }
  895. { //false } ifelse
  896. } ifelse
  897. } .internalbind def
  898. currentdict /.fontstatusaux .undef
  899. /Font mark
  900. /InstanceType /dicttype
  901. /DefineResource
  902. { 2 copy //definefont exch pop
  903. /Generic /Category findresource /DefineResource get exec
  904. } .internalbind
  905. /UndefineResource
  906. { dup //undefinefont
  907. /Generic /Category findresource /UndefineResource get exec
  908. } .internalbind
  909. /FindResource {
  910. dup //.getvminstance exec {
  911. exch pop 0 get
  912. } {
  913. dup ResourceStatus {
  914. pop 1 gt { .loadfontresource } { .GetInstance pop 0 get } ifelse
  915. } {
  916. .loadfontresource
  917. } ifelse
  918. } ifelse
  919. } .internalbind
  920. /ResourceForAll {
  921. { //.scannextfontdir exec not { exit } if } loop
  922. /Generic /Category findresource /ResourceForAll get exec
  923. } .forcebind
  924. /.ResourceFileStatus {
  925. .fontstatus { pop 2 -1 //true } { pop //false } ifelse
  926. } .internalbind
  927. /.loadfontresource {
  928. dup //.vmused exch
  929. % Hack: rebind .currentresourcefile so that all calls of
  930. % definefont will know these are built-in fonts.
  931. currentfile {pop //findfont exec} .execasresource % (findfont is a procedure)
  932. exch //.vmused exch sub
  933. % stack: name font vmused
  934. % findfont has the prerogative of not calling definefont
  935. % in certain obscure cases of font substitution.
  936. 2 index //.getvminstance exec {
  937. dup 1 1 put
  938. 2 3 -1 roll put
  939. } {
  940. pop
  941. } ifelse exch pop
  942. } systemdict /CETMODE .knownget not {//false} if {.bind}{.internalbind}ifelse
  943. /.Instances FontDirectory length 2 mul dict
  944. .definecategory % Font
  945. % Redefine font "operators".
  946. /.definefontmap
  947. { /Font /Category findresource /.Instances get
  948. dup 3 index known
  949. { pop
  950. }
  951. { 2 index
  952. % Make sure we create the array in global VM.
  953. .currentglobal //true .setglobal
  954. [//null 2 -1] exch .setglobal
  955. .growput
  956. }
  957. ifelse
  958. //.definefontmap exec
  959. } .internalbind def
  960. /definefont {
  961. { /Font defineresource } stopped {
  962. /definefont cvx $error /errorname get signalerror
  963. } if
  964. } .internalbind odef
  965. /undefinefont {
  966. /Font undefineresource
  967. } .internalbind odef
  968. % The Red Book requires that findfont be a procedure, not an operator,
  969. % but it still needs to restore the stacks reliably if it fails.
  970. /.findfontop {
  971. { /Font findresource } stopped {
  972. pop /findfont cvx $error /errorname get signalerror
  973. } if
  974. } .internalbind odef
  975. /findfont {
  976. .findfontop
  977. } .internalbind def % Must be a procedure, not an operator
  978. % Remove initialization utilities.
  979. currentdict /.definecategory .undef
  980. currentdict /.emptydict .undef
  981. end % level2dict
  982. % Convert deferred resources after we finally switch to Level 2.
  983. /.fixresources {
  984. % Encoding resources
  985. EncodingDirectory
  986. { dup length 256 eq
  987. { /Encoding defineresource pop }
  988. { pop pop }
  989. ifelse
  990. } forall
  991. /.findencoding {
  992. { /Encoding findresource } stopped {
  993. pop /findencoding cvx $error /errorname get signalerror
  994. } if
  995. } .internalbind def
  996. /findencoding /.findencoding load def % must be a procedure
  997. /.defineencoding { /Encoding defineresource pop } .internalbind def
  998. % ColorRendering resources and ProcSet
  999. systemdict /ColorRendering .knownget {
  1000. /ColorRendering exch /ProcSet defineresource pop
  1001. systemdict /ColorRendering undef
  1002. /DefaultColorRendering currentcolorrendering /ColorRendering defineresource pop
  1003. } if
  1004. % ColorSpace resources
  1005. systemdict /CIEsRGB .knownget {
  1006. /sRGB exch /ColorSpace defineresource pop
  1007. systemdict /CIEsRGB undef
  1008. } if
  1009. systemdict /CIEsRGBICC .knownget {
  1010. /sRGBICC exch /ColorSpace defineresource pop
  1011. systemdict /CIEsRGBICC undef
  1012. } if
  1013. systemdict /CIEsGRAYICC .knownget {
  1014. /sGrayICC exch /ColorSpace defineresource pop
  1015. systemdict /CIEsGRAYICC undef
  1016. } if
  1017. systemdict /CIEesRGBICC .knownget {
  1018. /esRGBICC exch /ColorSpace defineresource pop
  1019. systemdict /CIEesRGBICC undef
  1020. } if
  1021. systemdict /CIErommRGBICC .knownget {
  1022. /rommRGBICC exch /ColorSpace defineresource pop
  1023. systemdict /CIErommRGBICC undef
  1024. } if
  1025. % ColorSpaceFamily resources
  1026. colorspacedict { pop dup /ColorSpaceFamily defineresource pop } forall
  1027. % Filter resources
  1028. filterdict { pop dup /Filter defineresource pop } forall
  1029. % FontType and FMapType resources
  1030. buildfontdict { pop dup /FontType defineresource pop } forall
  1031. mark
  1032. buildfontdict 0 known { 2 3 4 5 6 7 8 } if
  1033. buildfontdict 9 known { 9 } if
  1034. counttomark { dup /FMapType defineresource pop } repeat pop
  1035. % FormType resources
  1036. .formtypes { pop dup /FormType defineresource pop } forall
  1037. % HalftoneType resources
  1038. .halftonetypes { pop dup /HalftoneType defineresource pop } forall
  1039. % ColorRenderingType resources
  1040. .colorrenderingtypes {pop dup /ColorRenderingType defineresource pop} forall
  1041. % ImageType resources
  1042. .imagetypes { pop dup /ImageType defineresource pop } forall
  1043. % PatternType resources
  1044. .patterntypes { pop dup /PatternType defineresource pop } forall
  1045. % Make the fixed resource categories immutable.
  1046. /.shadingtypes where {
  1047. pop .shadingtypes { pop dup /ShadingType defineresource pop } forall
  1048. } if
  1049. [ /ColorSpaceFamily /Emulator /Filter /IODevice /ColorRenderingType
  1050. /FMapType /FontType /FormType /HalftoneType /ImageType /PatternType
  1051. /.shadingtypes where { pop /ShadingType } if
  1052. ] {
  1053. /Category findresource
  1054. dup /.Instances get readonly pop
  1055. .LocalInstances readonly pop
  1056. readonly pop
  1057. } forall
  1058. % clean up
  1059. systemdict /.fixresources undef
  1060. } .internalbind def
  1061. %% Replace 1 (gs_resmp.ps)
  1062. (gs_resmp.ps) dup runlibfile VMDEBUG
  1063. [
  1064. /.default_resource_dir
  1065. /.resource_dir_name
  1066. /.fonttempstring /.scannextfontdir % from gs_fonts.ps
  1067. ] systemdict .undefinternalnames
  1068. [
  1069. /.definedefaultcs
  1070. /.undefinedefaultcs
  1071. /.defaultcsnames
  1072. /.enumerateresource
  1073. /.externalresourceforall
  1074. /.getvminstance
  1075. /.globalresourceforall
  1076. /.localresourceforall
  1077. /resourceforall1
  1078. /.resourceexec
  1079. /.undefinedresource
  1080. /.vmused
  1081. ] dup level2dict .undefinternalnames
  1082. systemdict .undefinternalnames