Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.postscript > #1793
| Newsgroups | comp.lang.postscript |
|---|---|
| Date | 2014-02-13 21:24 -0800 |
| Message-ID | <0c67addf-ee33-4159-877f-d20f0138c9be@googlegroups.com> (permalink) |
| Subject | debugger cracks loops |
| From | luser- -droog <mijoryx@yahoo.com> |
This is a re-write of the debugger, simplified and condensed, and sorely
lacking useful comments. But it appears to solve the conundrum of
interfacing into loops: treat them like any other overridden operator.
%/get {pstack/ = //get} def
%/oldifelse /ifelse load def
%/ifelse {pstack/ = oldifelse} def
%errordict/typecheck{ pstack }put
<<
/nextobject null
/stack 500 array
/ptr -1
/trace false
/step false
/steppstack true
/enddefbegin { currentdict 3 1 roll end def begin }
>> begin /dbdict currentdict def
% push and pop the dbdict<stack>
/pushs { % proc|file pushs
//dbdict /ptr 2 copy get 1 add put
//dbdict /stack get //dbdict /ptr get 3 -1 roll put % dbdict<stack>[++dbdict<ptr>] = _
} def
/pops {
//dbdict /ptr get 0 ge {
//dbdict /stack get //dbdict /ptr get get % dbdict<stack>[dbdict<ptr>]
dup type /filetype eq {closefile}{pop} ifelse
//dbdict /ptr 2 copy get 1 sub put % --dbdict<ptr>
} if
} def
% executable source type handlers
/nametype {
//pops exec
true
} def
/filetype {
token
} def
/stringtype {
token {
exch
//dbdict /stack get //dbdict /ptr get 3 -1 roll put
true
}{
false
} ifelse
} def
/arraytype {
dup length 0 gt {
dup 0 get exch
dup length 1 gt {
//dbdict /stack get //dbdict /ptr get 3 -1 roll
1 1 index length 1 sub getinterval put
}{
pop
//pops exec
} ifelse
true
}{
//pops exec
false
} ifelse
} def
/getnextobject {
//dbdict /nextobject get
dup null eq {
pop
//dbdict /ptr get 0 ge {
//dbdict /stack get //dbdict /ptr get get
//dbdict 1 index type get exec
}{
false
} ifelse
}{ true } ifelse
} def
/addoper { 1 index dup load type /operatortype eq { 1 index }{pop} ifelse } def
/operators <<
/run { (r) file //pushs exec } addoper
/if { exch { //pushs exec }{ pop } ifelse } addoper
/ifelse { 3 2 roll not { exch } if pop //pushs exec } addoper
/loop {
/loop cvx //pushs exec
dup 1 array astore cvx //pushs exec
//pushs exec
} addoper
/repeat {
exch dup 0 eq { pop pop }{
/repeat cvx //pushs exec
1 sub 2 copy exch 2 array astore cvx //pushs exec
pop //pushs exec
} ifelse
} addoper
/exit {
%dumpstack
{
//dbdict /stack get //dbdict /ptr get -1 0 { % stack index
2 copy get % stack index object
dup /loop eq {
//dbdict /ptr 4 3 roll 1 sub put pop stop
}{
dup /repeat eq {
//dbdict /ptr 4 3 roll 1 sub put pop stop
}{
pop
} ifelse
} ifelse
pop
} for
} stopped not { /exit cvx /unregistered signalerror } if
pop
} addoper
>> def
/debugheart {
//operators 1 index known {
//operators exch get exec
}{
load
dup type /arraytype eq {
dup length 0 eq { pop } //pushs ifelse
}{
exec
} ifelse
} ifelse
} def
/stepcommands <<
(n) 0 get { %next
/stepon load //pushs exec stepoff //debugheart exec }
/default 1 index
(c) 0 get { stepoff //debugheart exec } %continue
(b) 0 get { pop skip } %bypass
(s) 0 get //debugheart % :)
(q) 0 get { pop exit } %quit
>> def
/stepheart {
(step: )print dup ==only
( defined as ) print
dup { load } stopped { pop (/undefined)= }{ == } ifelse
(execute step? (continue|next|bypass|step|quit)?) print flush
(%lineedit)(r){file}stopped{ %EOF
pop ()= exit
}{
read { %something typed
//stepcommands exch
2 copy known not { pop /default } if
get //stepcommands /default 2 index put
exec
}{ %blank line
//stepcommands /default get exec
}ifelse
}ifelse
} def
/errmsg {
(Error /) print
$error /errorname get dup length string cvs print
( occurred attempting to execute ) print
} def
/handerr {
$error /errorname get /invalidexit eq {
exit
}{
(db:)print
//errmsg exec
//dbdict /nextobject get ==
(Stack:\n)print pstack
{
(db-error>) print flush
(%lineedit)(r) file cvx exec
} stopped {
$error /errorname get dup /invalidexit ne
exch /undefinedfilename ne and {
//errmsg exec (user command\n) print
} if
} if
} ifelse
} def
/debugloop {
//getnextobject exec
{
//dbdict /nextobject 3 -1 roll put
{
//dbdict /nextobject get
//dbdict /trace get { dup ==only //dbdict /cstack get exec } if
dup xcheck {
dup type /arraytype ne {
//dbdict /step get
//stepheart
//debugheart
ifelse
} if
} if % else leave on stack
//dbdict /nextobject null put
} stopped //handerr if
}{ % no objects
//pops exec
//dbdict /nextobject null put
//dbdict /ptr get 0 lt { exit } if %% <------ 'exit'
} ifelse
} def
/cstack { ( %|- )print
count dup 1 add copy -1 1{ -1 roll ==only ( )print }for
pop / = } def
/skip {
//dbdict /nextobject null put
} enddefbegin
/traceon {
//dbdict /trace true put
} enddefbegin
/traceoff {
//dbdict /trace false put
} enddefbegin
/stepon {
//dbdict /step true put
} enddefbegin
/stepoff {
//dbdict /step false put
} enddefbegin
/debug { % source debug -
//dbdict 1 index type known not { /debug cvx /typecheck signalerror } if
//pushs exec
//debugloop loop
} enddefbegin
/dumpstack {
//dbdict /stack get
0 1 //dbdict /ptr get {
2 copy get ==
pop
} for
pop
} enddefbegin
end
traceon
( 1 2 3 add add
6 eq { 8 9 add = } { 9 10 add = } ifelse
) debug
/ =
stepon
{ 1 2 3 add add
6 eq { 7 } if
9 {
5
count 4 gt {
exit
} if
} repeat
{ 55 exit } loop
undefin
(continuation) =
} debug
And a trace of an interactive session, executing the test fragments:
GPL Ghostscript 9.06 (2012-08-08)
Copyright (C) 2012 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
1 %|- 1
2 %|- 1 2
3 %|- 1 2 3
add %|- 1 2 3 add
add %|- 1 5 add
6 %|- 6 6
eq %|- 6 6 eq
{8 9 add =} %|- true {8 9 add =}
{9 10 add =} %|- true {8 9 add =} {9 10 add =}
ifelse %|- true {8 9 add =} {9 10 add =} ifelse
8 %|- 8
9 %|- 8 9
add %|- 8 9 add
= %|- 17 =
17
1 %|- 1
2 %|- 1 2
3 %|- 1 2 3
add %|- 1 2 3 add
step: add defined as --add--
execute step? (continue|next|bypass|step|quit)?c
add %|- 1 5 add
6 %|- 6 6
eq %|- 6 6 eq
{7} %|- true {7}
if %|- true {7} if
7 %|- 7
9 %|- 7 9
{5 count 4 gt {exit} if} %|- 7 9 {5 count 4 gt {exit} if}
repeat %|- 7 9 {5 count 4 gt {exit} if} repeat
5 %|- 7 5
count %|- 7 5 count
4 %|- 7 5 2 4
gt %|- 7 5 2 4 gt
{exit} %|- 7 5 false {exit}
if %|- 7 5 false {exit} if
8 %|- 7 5 8
{5 count 4 gt {exit} if} %|- 7 5 8 {5 count 4 gt {exit} if}
repeat %|- 7 5 8 {5 count 4 gt {exit} if} repeat
5 %|- 7 5 5
count %|- 7 5 5 count
4 %|- 7 5 5 3 4
gt %|- 7 5 5 3 4 gt
{exit} %|- 7 5 5 false {exit}
if %|- 7 5 5 false {exit} if
7 %|- 7 5 5 7
{5 count 4 gt {exit} if} %|- 7 5 5 7 {5 count 4 gt {exit} if}
repeat %|- 7 5 5 7 {5 count 4 gt {exit} if} repeat
5 %|- 7 5 5 5
count %|- 7 5 5 5 count
4 %|- 7 5 5 5 4 4
gt %|- 7 5 5 5 4 4 gt
{exit} %|- 7 5 5 5 false {exit}
if %|- 7 5 5 5 false {exit} if
6 %|- 7 5 5 5 6
{5 count 4 gt {exit} if} %|- 7 5 5 5 6 {5 count 4 gt {exit} if}
repeat %|- 7 5 5 5 6 {5 count 4 gt {exit} if} repeat
5 %|- 7 5 5 5 5
count %|- 7 5 5 5 5 count
4 %|- 7 5 5 5 5 5 4
gt %|- 7 5 5 5 5 5 4 gt
{exit} %|- 7 5 5 5 5 true {exit}
if %|- 7 5 5 5 5 true {exit} if
exit %|- 7 5 5 5 5 exit
{55 exit} %|- 7 5 5 5 5 {55 exit}
loop %|- 7 5 5 5 5 {55 exit} loop
55 %|- 7 5 5 5 5 55
exit %|- 7 5 5 5 5 55 exit
undefin %|- 7 5 5 5 5 55 undefin
db:Error /undefined occurred attempting to execute undefin
Stack:
undefin
55
5
5
5
5
7
db-error>skip
(continuation) %|- 7 5 5 5 5 55 undefin (continuation)
= %|- 7 5 5 5 5 55 undefin (continuation) =
continuation
GS<7>
Back to comp.lang.postscript | Previous | Next — Next in thread | Find similar | Unroll thread
debugger cracks loops luser- -droog <mijoryx@yahoo.com> - 2014-02-13 21:24 -0800
Re: debugger cracks loops luser- -droog <mijoryx@yahoo.com> - 2014-02-14 11:17 -0800
Re: debugger cracks loops luser- -droog <mijoryx@yahoo.com> - 2014-02-15 01:20 -0800
Re: debugger cracks loops luser- -droog <mijoryx@yahoo.com> - 2014-02-15 11:45 -0800
csiph-web