[comp.lang.postscript] commenting out blocks of code

greid@adobe.com (Glenn Reid) (08/24/89)

I've been writing serious PostScript code for over 4 years
and I just thought of this.  I wonder what that means....

There is only one comment mechanism in PostScript, which
is the % character.  It comments through the end of the
line.  So, to comment out a block of code, you do
something like this:

% /F { %def
%     findfont
%     exch scalefont
%     setfont
% } bind def

In fact, I've written an emacs macro to do this very
thing, and also to delete them as necessary.

Yesterday it dawned on me that there is another mechanism
for effectively commenting out blocks of code that is a
lot easier.  It doesn't really comment out the code, but
it keeps it from executing, which amounts to the same thing,
since you typically only do it while you're debugging:

{	% <--------- add this line
 /F { %def
    findfont
    exch scalefont
    setfont
 } bind def
} pop 	% <--------- also this line

It's only two lines, regardless of the number of lines in
between (assuming you don't overflow the operand stack,
that is).  Reminiscent of Pascal comments, methinks.

Since procedure bodies are always constructed as arrays
with deferred execution, you just force the code into a
procedure then pop it from the stack.  It works with
essentially all PostScript constructs in between, with
the exception of mismatched (), <>, or {} delimiters
and perhaps something else.

Since { is easy to miss, I now use something a little more
noticeable, like this:

{ %%%%%%%%%%%

} pop %%%%%%%

Just thought I would pass this on.  I suppose the rest
of you have been using this technique for years :-)

Glenn Reid
Adobe Systems

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

In article <1100@adobe.UUCP> greid@adobe.COM () writes:
>Yesterday it dawned on me that there is another mechanism
>for effectively commenting out blocks of code that is a
>lot easier.  It doesn't really comment out the code, but
>it keeps it from executing, which amounts to the same thing,
>since you typically only do it while you're debugging:
>
>{	% <--------- add this line
> /F { %def
>    findfont
>    exch scalefont
>    setfont
> } bind def
>} pop 	% <--------- also this line
>
>It's only two lines, regardless of the number of lines in
>between (assuming you don't overflow the operand stack,
>that is).  Reminiscent of Pascal comments, methinks.

But this wastes memory. The procedure which is popped is still in VM
although unreachable. Even better method is:

save {	% <--------- add this line
 /F { %def
    findfont
    exch scalefont
    setfont
 } bind def
} pop restore	% <--------- also this line

But this might still be slow, because the interpreter must scan all
tokens and generate new name objects and insert them into name-object
hash lists etc.

There is one more problem whith this approach. If there are
immediately evaluated names which are not defined, an error occurs. My
solution for commenting out large chunks of arbitrary text is in the
end of this article.

By the way, did you know that it is possible to generate VMerror by
"put"ing new values into an existent array which is under save:

/A 10000 array def
/S save def
0 1 9999
{
  A exch 1 put    % This put causes VMerror if memory is very short at
                  % this time because there is no memory to save the info
                  % about a changed location.
} for

I begun to think this possibility to cause VMerror after I had thought
how save/restore machinery must be implemented. I think I guessed
right. When a save is executed:

1.     A global savelevel variable is incremented.
2.     Top pointer of VM heap is saved in save stack

When an array element, a location in memory space of a dict (but not a
section of a string) is modified and the savelevel of this object is
below the current savelevel and this memory location has not yet been
saved in this savelevel:

The address and ol contents of this memory location is saved, so that
its contents can be later restored.

When restore is executed:

1.   restore examines the savelevel of the save object.
2.   Save chain is scanned and every address/contents pair above the
     save level. All memory locations are restored into their previous
     states.

The fact that is not mentioned in any PostScript books is that after a
save, modifying previous arrays and dicts consumes VM and is also
slower than modifying arrays which are created after the last save.

Although there is a section ERRORS under all PostScript operators,
ERRORS section doesn't tell all possible errors which may occur during
each operator.

In my opinionm, it would be a good thing to publish a book on Adobes
PostScript implementation. I think it would be valuable information
for PostScript users. All PostScript clone makers have probably
reverse-engineered Adobes implementation. Trade secrets this book
might reveal ahave not been any secrets for a long time.

	Antti Louko

Here is my skipblock procset:

%%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- str3 stoppedreadline not
      { pop pop exit} if
      pop pop
    } loop
  } if
} bind def

/skipblock {
  /-save- save def
  /str 60 string def
  /str2 60 string def
  /str3 60 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

Usage is as follows:

% The text following skipblock is completely ignored until a matching
% EndProcSet:
skipblock
%BeginProcSet: foobar1
This text is ignored and it is not evaluated.
%EndProcSet: foobar1
(This stuff is evaluated normally)

If somebody want to put this idea in a book, please do so, as long as
you mention somewhere in the book, who brought this idea up!!!

geof@apolling (Geof Cooper) (08/26/89)

In article <1100@adobe.UUCP> greid@adobe.COM () writes:
>{ %%%%%%%%%%%
>
>} pop %%%%%%%

The only problem you might encounter is the limit described in the
green book on the length of arrays that can be generated by the parser
so you might get a limitcheck on processing a very long "comment".
Since you wrote the green book, I guess you know about that one.

- Geof

greid@adobe.com (Glenn Reid) (08/27/89)

In article <4300@imagen.UUCP> geof@apolling (Geof Cooper) writes:
>In article <1100@adobe.UUCP> greid@adobe.COM () writes:
>>{ %%%%%%%%%%%
>>
>>} pop %%%%%%%
>
>The only problem you might encounter is the limit described in the
>green book on the length of arrays that can be generated by the parser
>so you might get a limitcheck on processing a very long "comment".
>Since you wrote the green book, I guess you know about that one.
>
>- Geof

Yeah, I vaguely remember that part of the green book :-)

You're right about that (except that it raises a stackoverflow on
our implementations, not a limitcheck, I think).

Luckily this is a limit you don't run into very often, but if you
were commenting out a big block of stuff that was machine-generated
(and hence had no { } arrays inside it) you would have problems,
it's true.  That's where a technique that just reads and discards
a bunch of data up through some %%Flag comes in handy, although it
is enough more work that I think just deleting with a text editor
probably starts to look more appealing.

Heck, none of us on this newsgroup ever needs to comment anything
out anyway, do we?  Doesn't it usually work the first time?

Thought so,
 Glenn