Question

Is there a maximum size for a postscript array ?

I wrote a PS document containing containing an array that is displayed in ghostview without any problem.

But when the number of items in this array increases, ghostview raises the following exception:

ERROR: /stackoverflow in -file-
Operand stack:
   --nostringval--
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1   3   %oparray_pop   1   3   %oparray_pop   1   3   %oparray_pop   1   3   %oparray_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push
Dictionary stack:
   --dict:1122/1686(ro)(G)--   --dict:0/20(G)--   --dict:122/200(L)--
Current allocation mode is local
Last OS error: 2
Current file position is 301163
ESP Ghostscript 815.02: Unrecoverable error, exit code 1
Was it helpful?

Solution

There is a maximum array length: 65535. This is also the maximum string length. But that doesn't appear to be the problem here.

Postscript Level 2 removed the limit on stack size, so it should automatically expand to whatever size the virtual memory system can manage. If you're getting a /stackoverflow error; you need to upgrade your interpreter to at least the Level 2 (1991) standard.

Edit: That said, there are ways to work around the problem if upgrading isn't an option.

The limit most likely occurs because the stack is being statically allocated. If you have access to the source code, you can simply increase the size and recompile the interpreter. The limit quoted in the PLRM 1ed is 500.

Another option is to change the way you work with the stack (harder). If you cannot construct a 1000 element array using [] or {} you can still allocate the array (1000 array) and fill it with slices constructed normally (dup dup 0 [ 0 1 .. 450 ] putinterval dup dup 450 [ 451 452 .. 900 ] putinterval dup dup 900 [ 901 902 .. 999 ] putinterval). Remember, marks take up space on the stack too; and certain operators are really procedures and they will need stack space to operate.

Edit: If the arrays are truly huge, array slices may run you up against total memory limits; because if you don't have growing stacks, you probably don't have garbage collection either. The above method leaves 1000 arrays elements used and inaccessible in VM. Using packedarray for the slices might forstall this problem somewhat.

The next step would be to write a procedure that works like a hybrid of putinterval and packedarray that can load data into an array without creating temporary arrays. This may run slower since we're reimplementing low-level functionality at a higher level.

Here's a first stab. It reads ahead (using currentfile token) and puts each element into subsequent positions of the array. arrayfill must be the last word on the source line (like image) so currentfile can find the first element (the remainder of the source line is in an internal scanner buffer).

% array index count  arrayfill(NL)  array
% elem_0 elem_1 ..
% elem_count-1
/arrayfill { %a i c
    1 index add 1 sub %a ini fin
    1 exch { %a i
        2 copy %a i a i
        currentfile token pop %a i a i el
        put %a i
        pop %a
    } for
} def

%example
5 array 0 5 arrayfill
(0) (1) (2) (3) (4)
{=} forall
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top