• Challenge: clean up this old script

    From luser droog@21:1/5 to All on Tue May 12 14:34:25 2020
    I found this post on stackoverflow where someone was trying to use some
    old postscript code from the internet and it wasn't quite doing what he
    wanted due to portability issues in the code.

    I'm busy with finals week in school so I can't put in the time to work
    on it. But if anyone is looking for a (light) PS programming effort,
    I the results will be entertaining for the group.

    SO question: https://stackoverflow.com/q/59950318/733077/why-does-this-postscript-ps-file-create-way-more-top-margin-than-specified


    %!
    %
    % From: Jonathan Monsarrat (jgm@cs.brown.edu)
    % Subject: PostScript -> ASCII *and* ASCII -> PostScript programs
    % Newsgroups: comp.lang.postscript
    % Date: 1992-10-01 04:45:38 PST
    %
    % "If anyone is interested, here is an interesting program written by
    % Professor John Hughes here at Brown University that formats ASCII
    % in PostScript without a machine generator of any kind."
    %
    %%%
    %%% Plan:
    %%% Start with an empty string.
    %%% For each character in the input stream,
    %%% check to see if it's a carriage return.
    %%% if so, show the current string and reset it to empty
    %%% if not, add it to the current string.

    /Courier findfont 10 scalefont setfont %% Choose a fixed width font /lineheight
    currentfont /FontBBox get dup %% bbox bbox
    0 2 getinterval %% bbox {xm ym}
    exch %% {xm ym} bbox
    2 2 getinterval %% {xm ym} {xM yM}
    aload pop %% {xm ym} xM yM
    3 2 roll %% xM yM {xm ym}
    aload pop
    currentfont /FontMatrix get %% xM yM xm ym MAT
    transform %% xM yM xm' ym'
    4 2 roll
    currentfont /FontMatrix get %% xm' ym' xM yM MAT
    transform %% xm' ym' xM' yM'
    exch pop %% xm' ym' yM'
    sub %% xm' ym'-yM'
    exch pop %% dy
    neg def

    lineheight pstack pop

    /str 500 string def %% Room to store a long string...
    /empty 500 string def %% An empty string to work with
    /stringindex 0 def %% How far we've filled the string
    /inch {72 mul } def %% A useful tool...
    /pageheight 11 inch def
    /topmargin 1 inch def
    /botmargin 1 inch def
    /leftmargin 1 inch def
    /linesperpage pageheight topmargin sub botmargin sub lineheight div cvi def /linenumber 1 def %% the line we're about to write on

    /newline { %% move to a new line; flush page if necessary
    linenumber linesperpage gt {/linenumber 1 def showpage } if
    leftmargin pageheight topmargin sub linenumber lineheight mul sub moveto
    /linenumber linenumber 1 add def
    } def

    /cleanup { %% print out the last bit of whatever you had there...
    str show showpage
    } def

    /startstring { %% empty the string and reset its counter.
    str 0 empty putinterval
    /stringindex 0 def
    } def

    /showstring { %% print the string on a new line and flush it
    newline
    str show
    startstring
    } def

    pstack

    /addtostring { %% put another character in the string, if there's room
    dup 500 gt {pop}{str exch stringindex exch put
    /stringindex stringindex 1 add def} ifelse
    } def

    %
    % Main program: get characters and deal with them
    %
    {
    currentfile read {}{cleanup exit} ifelse
    dup 10 eq %% if it's a carriage return...
    {pop showstring} %% write out this line of text and start over
    {dup 0 eq %% if it's an end-of-file mark...
    {exit} %% stop!
    {addtostring} %% otherwise, add the character to current string
    ifelse}
    ifelse %% Sample data follows.
    } loop

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luser droog@21:1/5 to luser droog on Wed May 13 17:34:52 2020
    On Tuesday, May 12, 2020 at 4:34:26 PM UTC-5, luser droog wrote:
    I found this post on stackoverflow where someone was trying to use some
    old postscript code from the internet and it wasn't quite doing what he wanted due to portability issues in the code.

    I'm busy with finals week in school so I can't put in the time to work
    on it. But if anyone is looking for a (light) PS programming effort,
    I the results will be entertaining for the group.

    SO question: https://stackoverflow.com/q/59950318/733077/why-does-this-postscript-ps-file-create-way-more-top-margin-than-specified


    %!
    %
    % From: Jonathan Monsarrat (jgm@cs.brown.edu)
    % Subject: PostScript -> ASCII *and* ASCII -> PostScript programs
    % Newsgroups: comp.lang.postscript
    % Date: 1992-10-01 04:45:38 PST
    %
    % "If anyone is interested, here is an interesting program written by
    % Professor John Hughes here at Brown University that formats ASCII
    % in PostScript without a machine generator of any kind."
    %
    %%%
    %%% Plan:
    %%% Start with an empty string.
    %%% For each character in the input stream,
    %%% check to see if it's a carriage return.
    %%% if so, show the current string and reset it to empty
    %%% if not, add it to the current string.


    I got both my finals turned in, so I looked closer at this code.
    It's actually pretty decent overall. I did not make a lot of changes.
    Changed some names, factored out the ++ operation, simplify calculation
    of the leading (nee lineheight). And most importantly replace the
    explicit
    /pageheight 11 inch def
    with your choice between taking the maximum Y value from the page device
    or the clipping path.

    The bizarre "dup 500 gt" I left alone. I can't see that it hurts anything,
    but I can't imagine a situation where it would accomplish anything either.

    Modified version:


    /Courier 10 selectfont
    /leading gsave
    currentfont
    dup /FontMatrix get matrix currentmatrix matrix invertmatrix concat concat
    /FontBBox get aload pop % llx lly urx ury
    dtransform 3 2 roll dtransform % urx' ury' llx' lly'
    exch pop sub exch pop % ury-lly
    grestore def

    /buf 500 string def
    /empty 500 string def
    /ptr 0 def
    /inch {72 mul} def
    /pageheight currentpagedevice /PageSize get 1 get def
    %/pageheight newpath clippath pathbbox 4 1 roll pop pop pop def
    /topmargin 1 inch def
    /botmargin 1 inch def
    /leftmargin 1 inch def
    /linesperpage pageheight topmargin sub botmargin sub leading div cvi def /linenumber 1 def % the line we're about to write on
    /++ {dup load 1 add store} def

    /newline {
    linenumber linesperpage gt {/linenumber 1 def showpage} if
    leftmargin pageheight topmargin sub linenumber leading mul sub moveto
    /linenumber ++
    } def

    /cleanup {
    buf show showpage
    } def

    /startstring {
    buf 0 empty putinterval
    /ptr 0 def
    } def

    /showstring {
    newline
    buf show
    startstring
    } def

    /addtostring {
    dup 500 gt {pop}{
    buf exch ptr exch put
    /ptr ++
    } ifelse
    } def

    {
    currentfile read {}{cleanup exit} ifelse
    dup 10 eq
    {pop showstring}
    {dup 0 eq
    {exit}
    {addtostring}
    ifelse
    }
    ifelse
    } loop

    Show me the money!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ken@21:1/5 to All on Thu May 14 07:53:29 2020
    In article <dfbf4f4d-4b1b-4acb-8b4e-362cc46fc8cc@googlegroups.com>, luser.droog@gmail.com says...

    The bizarre "dup 500 gt" I left alone. I can't see that it hurts
    anything,
    but I can't imagine a situation where it would accomplish anything either.

    I haven't read the code i detail, but surely that is simply preventing
    an overflow of the string, which is defined as a 500 element object ?

    Though I agree it would have to be a very small point size and large
    media width to fit more than 500 characters across it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luser droog@21:1/5 to ken on Thu May 14 07:35:45 2020
    On Thursday, May 14, 2020 at 1:53:32 AM UTC-5, ken wrote:
    In article <dfbf4f4d-4b1b-4acb-8b4e-362cc46fc8cc@googlegroups.com>, luser.droog@gmail.com says...

    The bizarre "dup 500 gt" I left alone. I can't see that it hurts
    anything,
    but I can't imagine a situation where it would accomplish anything either.

    I haven't read the code i detail, but surely that is simply preventing
    an overflow of the string, which is defined as a 500 element object ?

    Though I agree it would have to be a very small point size and large
    media width to fit more than 500 characters across it.

    That's what I thought at first, but no it's comparing the character value
    that just came from `read`. It probably would be a good idea to check the capacity of the string there. The code also expects an EOF indication to
    happen by `read` returning a 0.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luser droog@21:1/5 to luser droog on Fri May 15 09:34:07 2020
    On Wednesday, May 13, 2020 at 7:34:54 PM UTC-5, luser droog wrote:
    On Tuesday, May 12, 2020 at 4:34:26 PM UTC-5, luser droog wrote:
    I found this post on stackoverflow where someone was trying to use some
    old postscript code from the internet and it wasn't quite doing what he wanted due to portability issues in the code.

    I'm busy with finals week in school so I can't put in the time to work
    on it. But if anyone is looking for a (light) PS programming effort,
    I the results will be entertaining for the group.

    SO question: https://stackoverflow.com/q/59950318/733077/why-does-this-postscript-ps-file-create-way-more-top-margin-than-specified


    %!
    %
    % From: Jonathan Monsarrat (jgm@cs.brown.edu)
    % Subject: PostScript -> ASCII *and* ASCII -> PostScript programs
    % Newsgroups: comp.lang.postscript
    % Date: 1992-10-01 04:45:38 PST
    %
    % "If anyone is interested, here is an interesting program written by
    % Professor John Hughes here at Brown University that formats ASCII
    % in PostScript without a machine generator of any kind."
    %
    %%%
    %%% Plan:
    %%% Start with an empty string.
    %%% For each character in the input stream,
    %%% check to see if it's a carriage return.
    %%% if so, show the current string and reset it to empty
    %%% if not, add it to the current string.


    I got both my finals turned in, so I looked closer at this code.
    It's actually pretty decent overall. I did not make a lot of changes.
    Changed some names, factored out the ++ operation, simplify calculation
    of the leading (nee lineheight). And most importantly replace the
    explicit
    /pageheight 11 inch def
    with your choice between taking the maximum Y value from the page device
    or the clipping path.

    The bizarre "dup 500 gt" I left alone. I can't see that it hurts anything, but I can't imagine a situation where it would accomplish anything either.

    Modified version:

    I did some more editing. I wrapped all the main line code in procedures so
    the top level structure is very simple:

    << ... /main { initialize mainloop } ... >> begin main

    I teased out all the definitions which are sensible to modify and put them
    in a procedure called /parameters which is right at the top.

    I think this makes the program easier to scan and read. You no longer need
    to slog through all that initialization code to see what's being
    initialized. And then I squeezed all the short procedures into one-liners
    to make the whole thing shorter overall.

    New modified version:


    << % wrap everything in a dictionary

    /parameters { % user modifiable
    /buflength 500 def
    /topmargin 1 inch def
    /botmargin 1 inch def
    /leftmargin 1 inch def
    /Courier 10 selectfont
    }

    /main { initialize mainloop }

    /initialize {

    parameters

    /leading gsave
    currentfont
    dup /FontMatrix get matrix currentmatrix matrix invertmatrix concat concat
    /FontBBox get aload pop % llx lly urx ury
    dtransform 3 2 roll dtransform % urx' ury' llx' lly'
    exch pop sub exch pop % ury-lly
    grestore def

    /buf buflength string def
    /empty buflength string def
    /ptr 0 def

    /pageheight currentpagedevice /PageSize get 1 get def
    %/pageheight newpath clippath pathbbox 4 1 roll pop pop pop def
    /linesperpage pageheight topmargin sub botmargin sub leading div cvi def
    /linenumber 1 def % the line we're about to write on
    }

    /mainloop {
    {
    currentfile read {}{cleanup exit} ifelse
    dup 10 eq {
    pop showstring
    }{
    addtostring %dup 0 eq {exit}{addtostring} ifelse
    } ifelse
    } loop
    }

    /newline {
    linenumber linesperpage gt {/linenumber 1 def showpage} if
    leftmargin pageheight topmargin sub linenumber leading mul sub moveto
    /linenumber ++
    }

    /cleanup { linenumber 1 gt { buf show showpage } if }
    /startstring { buf 0 empty putinterval /ptr 0 def }
    /showstring { newline buf show startstring }
    /addtostring { ptr buf length ge {pop}{ buf exch ptr exch put /ptr ++ } ifelse }

    /inch {72 mul}
    /++ {dup load 1 add store}
    begin main
    Text immediately following will be printed on the output device.
    Use explicit newlines to trigger carriage returns.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)