Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

You may call me by my name, Wirth, or by my value, Worth. -- Nicklaus Wirth


devel / comp.lang.postscript / formatted string output

SubjectAuthor
o formatted string outputluser droog

1
formatted string output

<eaea87c8-b7b9-4d5a-86ff-e38fe0850d92n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=10029&group=comp.lang.postscript#10029

  copy link   Newsgroups: comp.lang.postscript
X-Received: by 2002:ad4:4f12:0:b0:5ef:57cc:641d with SMTP id fb18-20020ad44f12000000b005ef57cc641dmr2953811qvb.1.1684945188760;
Wed, 24 May 2023 09:19:48 -0700 (PDT)
X-Received: by 2002:a05:6870:7709:b0:196:74ca:432a with SMTP id
dw9-20020a056870770900b0019674ca432amr91940oab.4.1684945188452; Wed, 24 May
2023 09:19:48 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!3.eu.feeder.erje.net!feeder.erje.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer02.ams4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.postscript
Date: Wed, 24 May 2023 09:19:48 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=24.107.184.18; posting-account=G1KGwgkAAAAyw4z0LxHH0fja6wAbo7Cz
NNTP-Posting-Host: 24.107.184.18
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <eaea87c8-b7b9-4d5a-86ff-e38fe0850d92n@googlegroups.com>
Subject: formatted string output
From: luser.dr...@gmail.com (luser droog)
Injection-Date: Wed, 24 May 2023 16:19:48 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 8104
 by: luser droog - Wed, 24 May 2023 16:19 UTC

With a little tweak, the string interpolation function becomes a
pretty close analog of sprintf. The function 'format' takes a
format string and yields an output string. A percent sign in
the format indicates the start of an interpolated value. The next
token following the percent sign is scanned from the format
string (consuming exactly one terminating whitespace character
unless the token is delimited by one of the PostScript
delimiters []()<>/%). If the token is a /nametype object, it is loaded
and converted into a string and spliced into the output at that
point. If the token is an /integertype object, it is used to index
up the stack past the location of the format string in the original
stack picture as it looked when 'format' was called. So %1 refers
to the first thing on the stack just below the format string. But only
the format string is popped by the format function and these other
objects referenced by stack position are not removed.

12 (%1) format % 12 (12)

/a 4 def
(%a) format % (4)
(%a ) format % (4) %% if there's a space, it's gon' get eaten
(%a ) format % (4 )

So this gives you the power of a sprintf to access a variable number
of arguments -- without needing to create an array to hold them or to
bracket the arguments with a bare mark. It might be useful to write
a variant that pops extra objects up to the highest integer reference.

(There's also a few versions of an 'rforall' loop that goes backwards
through a string or array because it happened in the same file.)

%!
% ... format-string format ... result-string
/format {
[ exch
(%) { % post match
exch token not {exit} if % match rem tok
exch 3 1 roll % rem match tok
fetch [ exch convert % rem match [ (tok)*
} on-matches
join-to-mark
} def

/fetch {
dup type /nametype eq {
load
}{
dup type /integertype eq {
index-past-mark
}{
unrecognized-type-in-format-string
} ifelse
} ifelse
} def

% string seek proc
% where: post match proc post' match [ tok*
/on-matches-v1 {
1 dict begin /proc exch def
({ % string seek
search not {exit} if 3 1 roll % pre post match
//proc exec % pre rem match [ tok*
2 put-below % pre tok* rem match
}) cvx exec end loop
} def

% string seek proc
% where: post match proc post' match [ tok*
/on-matches {
[ exch
{ search not {exit} if 3 1 roll } exch % in loop: % pre post match
% -- call proc -- % % pre rem match [ tok*
{ 2 put-below } % % pre tok* rem match
join-to-mark loop
} def

/curry { % obj {...} curry {obj ...}
dup length 1 add array 1 index xcheck {cvx} if % obj arr dest
dup 0 5 -1 roll put % arr dest
dup 1 4 -1 roll putinterval % dest
} def

/join-to-mark { % [ <obj1> .. <objN> join-to-mark <obj1..objN>
counttomark dup 1 add copy % [ <obj1> .. <objN> n <obj1> .. <objN> n
0 exch { % ... <obj1> .. <objn> len=0
exch length add % ... <obj1> .. <objn-1> len+=#objn
} repeat % [ <obj1> .. <objN> n length
first-after-mark type /stringtype eq
{string}{array} ifelse % [ <obj1> .. <objN> n dest
first-after-mark xcheck {cvx} if
exch 0 exch { % [ <obji> .. <objN> dest pos
snag-first % [ <obji+1> .. <objN> dest pos <obji>
3 copy putinterval % [ <obji+1> .. <objN> dest' pos <obji>
length add % [ <obji+1> .. <objN> dest' pos+=#obji
} repeat % [ dest length
pop exch pop % dest
} def

/put-below { % obj1 .. objN [ obj'1 .. obj'M N put-below obj'1 .. obj'M obj1 .. objN
counttomark % ...(n) [ ...(m) n m+1
exch 1 index add exch 1 sub % ...(n) [ ...(m) n+m+1 m
roll pop % ...(m) ...(n)
} def

/first-after-mark {
counttomark 1 sub index
} def

/snag-first {
counttomark -1 roll
} def

/index-past-mark { % 3 2 1 [ ...(n) 2
counttomark % 3 2 1 [ ...(n) 2 n+1
1 sub % 3 2 1 [ ...(n) 2 n
add % 3 2 1 [ ...(n) 2+n
index
} def

/base (10) cvx def
/convert <<
/default { 256 string cvs }
/stringtype { }
/nametype { dup xcheck not { (/) exch } if
dup length string cvs }
/booleantype { {(true)}{(false)} ifelse }
/marktype { pop (MARK) }
/nulltype { pop (-) }
/savetype { pop (-save-) }
/filetype { pop (-file-) }
/fonttype { pop (-font-) }
/gstatetype { pop (-gstate-) }
/integertype { base 10 eq { 256 string cvs }{
/base load cvlit exch (#) exch base 256 string cvrs
} ifelse }
/arraytype { dup xcheck {
dup length 0 eq { pop ({}) }{
({) exch { convert ( ) }forall pop (})
} ifelse
}{
dup length 0 eq { pop ([]) }{
([) exch { convert ( ) }forall pop (])
} ifelse
} ifelse }
/packedarraytype 1 index
/dicttype {
dup length 0 eq { pop (<<>>) }{
(<<) exch { % key val
exch [ exch convert % val [ (key)*
1 put-below % key* val
( ) exch
convert ( )
} forall pop (>>)
} ifelse
}
>> {
1 index type switch
} curry def

/switch {
2 copy known not { pop /default } if get exec
} def

/rforall-v1 { % array/string proc rforall
1 dict begin /proc exch def /src exch def
/src load length 1 sub -1 0 ({
//src exch get
//proc exec
}) cvx exec end for
} def

/rforall-v2 {
1 index length 1 sub -1 0
[ 6 4 roll
exch {exch get} curry exch
join-to-mark for
} def

/rforall-v3 { % src proc rforall
1 index length 1 sub -1 0 5 3 roll % $ -1 0 src proc
{exch get} exch join curry for % $ -1 0 { //src exch get proc... } for
} def

/rforall { % src proc rforall -
dup length 3 add array cvx % src proc loop
dup 0 4 index put % src proc {src }
dup 1 { exch get } putinterval % src proc {src exch get }
dup 3 4 -1 roll putinterval % src {src exch get proc...}
exch length 1 sub -1 0 4 3 roll % $ -1 0 {src exch get proc...}
for
} def

/join {
[ 3 1 roll join-to-mark
} def

/args {
{exch def} rforall
} def

%{a b c d e}{=} rforall

/a 4 def
/b 12 def
/c {a b} def
/d [a b] def
/e <</a a /b b>> def

(x) 42 (format %a %b %c %d %e %1 %2) format
pstack

$ gsnd interpolate.ps
GPL Ghostscript 9.55.0 (2021-09-27)
Copyright (C) 2021 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
(format 4 12 {a b} [4 12] <</a 4 /b 12>>42x)
42
(x)
GS<3>

1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor