[comp.lang.postscript] The // operator

marmar@mtk.UUCP (Mark Martino) (05/23/89)

I was reading an article about the innards of PostScript and the author
mentioned an operator whose label is "//".  I put it into a file an ran
it through version 43.0.  It seemed to be recognized by the interpreter
but did not have any effect I could detect.

Is this a real operator?  I could not find it in the red, blue, or green
book.  If it is real, what is it supposed to do?

batcheldern@icosa.dec.com (Ned Batchelder) (05/27/89)

The // construct in PostScript is not an operator; it is more like a name modifier. 
When a name is preceded by the double-slash, its current value is used instead of the

	/a 17 def
	/foo { a } def
	/bar { /a } def
	/baz { //a } def

"foo" is now a procedure which when executed will push the latest value of "a" on the
stack. The procedure actually contains the name "a", and it is looked up when the
procedure is executed.

"bar" is now a procedure which when executed will push the literal name "a" on the stack. No name lookup is performed.

"baz" is now a procedure which when executed will push 17 on the stack. The procedure actually contains the integer 17, because that is the value that "a" had at the time the procedure was defined. The double-slash means "lookup this name, and use its value just as it had appeared in the input". Of course, some values for names may not have a representation
in the input stream, such as dictionaries.

Be careful when using the double-slash (if at all), because older PostScript interpreters don't have it, and there is no way your program will work properly on them.

Ned Batchelder, Digital Equipment Corp., BatchelderN@Hannah.DEC.com

geof@apolling (Geof Cooper) (06/06/89)

In article <2586@shlump.dec.com> batcheldern@icosa.dec.com (Ned Batchelder) writes:
>The // construct in PostScript is not an operator; it is more like a name modifier. 
>When a name is preceded by the double-slash, its current value is used instead of the
>name.

Software developers, be careful how you use this feature.  It is not
possible to test for the existence of a feature if you want to use // in
relation to it.  For example, the latest Apple LaserPrep contains code
of the form:

	if <I'm a LaserWriter> then
		<do some nifty things with funny operators in serverdict>

This is all very well, but the "nifty thing" references LaserWriter
operators in serverdict using the // convention.  This means that those
names must resolve to valid objects on ALL machines, not just the
LaserWriter, since the names are resolved in the scanner independent
of the result of the conditional.

- Geof

alo@kampi.hut.fi (Antti Louko) (06/06/89)

In article <3903@imagen.UUCP> geof@apolling (Geof Cooper) writes:
>Software developers, be careful how you use this feature.  It is not
>possible to test for the existence of a feature if you want to use // in
>relation to it.  For example, the latest Apple LaserPrep contains code
>of the form:
>
>	if <I'm a LaserWriter> then
>		<do some nifty things with funny operators in serverdict>
>
>This is all very well, but the "nifty thing" references LaserWriter
>operators in serverdict using the // convention.  This means that those
>names must resolve to valid objects on ALL machines, not just the
>LaserWriter, since the names are resolved in the scanner independent
>of the result of the conditional.
>
>- Geof

Software developers, you can use this little hack I just put together:
skipblock is a procedure which skips a %%BeginProcSet .. %%EndProcSet
region so that the interpreter won't scan the skipped text.

The only problem is how to get big companies to use this procedure...

    Antti

--------------------------------
%!

%%BeginProcSet: skipblock 1.0 0
/stoppedreadline {
  /savedhandler errordict /rangecheck get def
  errordict /rangecheck { pop stop } put
  { readline } stopped
  errordict /rangecheck /savedhandler load put
  { exch pop true dup }
  { false }
  ifelse
} bind def

/readlinehead {
  /-str- exch def
  /-file- exch def
  -file- -str- stoppedreadline
  {
    {
      -file- (..............) stoppedreadline not
      { pop pop exit} if
      pop pop
    } loop
  } if
} bind def

/skipblock {
  /-save- save def
  /str 600 string def
  /str2 600 string def
  currentfile str readlinehead not { stop } if
  (%%BeginProcSet:) anchorsearch
  { pop /-name- exch def } { stop } ifelse
  {
    currentfile str2 readlinehead not { stop } if
    (%%EndProcSet:) anchorsearch
    { pop -name- eq { exit } if } { pop } ifelse
  } loop
  -save- restore
} bind def
%%EndProcSet: skipblock 1.0 0

%example

skipblock
%%BeginProcSet: foobar
(This stuff should be skipped) ==
(This stuff should be skipped) ==
(This stuff should be skipped) ==
(This stuff should be skipped) ==
%%EndProcSet: foobar
(This stuff should not be skipped) ==
--------------------------------

alo@kampi.hut.fi (Antti Louko) (06/06/89)

PS to my earlier posting:

This is how you can tell if your PostScript interpreter has // feature:

%%BeginProcSet: immediate-test 1.0 0
/has-immediate
(//add) token	% If immediately evaluated names are not implemented
		% this parses as / and /add
{ exch pop / eq not }
{ false } ifelse  % token should always succeed
def
%%EndProcSet: immediate-test 1.0 0