167
167
void gc_conses ();
168
168
int kbhit ();
169
169
static inline lisp callfunc (lisp f , lisp args , lisp * envp , lisp e , int noeval );
170
+ int lispreadchar (char * chp );
171
+
172
+ PRIM breakpoint ();
170
173
void error (char * msg );
174
+ static inline int tracep (lisp f );
175
+
171
176
void run (char * s , lisp * envp );
172
177
173
178
PRIM fundef (lisp f );
@@ -1024,13 +1029,19 @@ PRIM evallist(lisp e, lisp* envp) {
1024
1029
return r ;
1025
1030
}
1026
1031
1027
- static inline int tracep (lisp f );
1032
+ #define MAX_STACK 80
1033
+
1034
+ static struct stack {
1035
+ lisp e ;
1036
+ lisp * envp ;
1037
+ } stack [MAX_STACK ];
1038
+
1028
1039
1029
1040
// dummy function that doesn't eval, used instead of eval
1030
1041
static PRIM noEval (lisp x , lisp * envp ) { return x ; }
1031
1042
1032
1043
PRIM primapply (lisp ff , lisp args , lisp * envp , lisp all , int noeval ) {
1033
- //printf("PRIMAPPLY "); princ(ff); princ(args); terpri();
1044
+ //printf("PRIMAPPLY "); princ(ff); putchar(' '); princ(args); putchar(' '); princ(*envp ); terpri();
1034
1045
int n = GETPRIMNUM (ff );
1035
1046
lisp (* e )(lisp x , lisp * envp ) = (noeval && n > 0 ) ? noEval : evalGC ;
1036
1047
int an = abs (n );
@@ -1799,7 +1810,7 @@ PRIM with_putc(lisp* envp, lisp args) {
1799
1810
int myputc (int c ) {
1800
1811
recurse ++ ;
1801
1812
if (recurse > 1 ) error ("with-putc called with function that calls putc - prohibited!" );
1802
- lisp r = callfunc (fn , cons (mkint (c ), nil ), envp , nil , 1 );
1813
+ lisp r = callfunc (fn , cons (mkint (c ), nil ), envp , nil , 1 );
1803
1814
recurse -- ;
1804
1815
return getint (r );
1805
1816
}
@@ -2118,7 +2129,12 @@ static inline lisp eval_hlp(lisp e, lisp* envp) {
2118
2129
}
2119
2130
2120
2131
// This may return a immediate, this allows tail recursion evalGC will reduce it.
2132
+
2133
+ stack [level ].e = f ;
2134
+ stack [level ].envp = envp ;
2121
2135
lisp r = callfunc (f , cdr (e ), envp , e , 0 );
2136
+ stack [level ].e = nil ;
2137
+ stack [level ].envp = nil ;
2122
2138
2123
2139
// we replace it after as no error was generated...
2124
2140
if (f != orig ) {
@@ -2203,25 +2219,20 @@ int needGC();
2203
2219
// #772 0x08052d58 in readeval ()
2204
2220
// #773 0x08048b57 in main ()
2205
2221
2206
- #define MAX_STACK 80
2207
-
2208
- static struct stack {
2209
- lisp e ;
2210
- lisp * envp ;
2211
- } stack [MAX_STACK ];
2212
-
2213
2222
// TODO: because of tail call optimization, we can't tell where the error occurred as it's not relevant on the stack???
2214
- PRIM print_detailed_stack () {
2223
+ PRIM print_detailed_stack (int curr ) {
2215
2224
int l ;
2216
2225
// TODO: DONE but too much: using fargs of f can use .envp to print actual arguments!
2217
2226
for (l = 0 ; l < level + 5 ; l ++ ) {
2218
2227
if (!stack [l ].e && !stack [l ].envp ) break ;
2219
2228
2220
2229
if (!l ) terpri ();
2230
+ if (curr && l == curr - 1 ) printf ("==>" );
2221
2231
printf ("%4d : " , l );
2222
- prin1 (stack [l ].e ); printf (" ==> " );
2232
+ prin1 (stack [l ].e ); printf (" ENV: " );
2223
2233
2224
2234
lisp f = car (stack [l ].e );
2235
+ if (!f ) f = stack [l ].e ;
2225
2236
lisp * envp = stack [l ].envp ;
2226
2237
lisp env = envp ? * envp : nil ; // env before
2227
2238
while (f && IS (f , symboll ) && !IS (f , func ) && !IS (f , thunk ) && !IS (f , prim ) && !IS (f , immediate )) {
@@ -2250,7 +2261,7 @@ PRIM print_detailed_stack() {
2250
2261
printf (" ... ] " );
2251
2262
} else {
2252
2263
printf (" ... ] " );
2253
- printf (" ...car did not evaluate to a function... (it's an %s)\n" , f ? tag_name [TAG (f )] : "nil" );
2264
+ printf (" ...car did not evaluate to a function... (it's %s)\n" , f ? tag_name [TAG (f )] : "nil" );
2254
2265
break ;
2255
2266
}
2256
2267
terpri ();
@@ -2597,7 +2608,7 @@ PRIM load(lisp* envp, lisp name, lisp verbosity) {
2597
2608
2598
2609
// no gcc style innner functions with outer variables.. .:-(
2599
2610
int evalIt (void * p , char * s , char * filename , int startno , int endno , int v ) {
2600
- if (!s || !s [0 ] || s [0 ] == ';' ) return ;
2611
+ if (!s || !s [0 ] || s [0 ] == ';' ) return 0 ;
2601
2612
if (v > 1 ) printf ("\n========================= %s :%d-%d>\n%s\n" , filename , startno , endno , s );
2602
2613
lisp * envp = p ;
2603
2614
jmp_buf saved ;
@@ -3422,7 +3433,21 @@ lisp lisp_init() {
3422
3433
// http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-user/Command_002dLine-Debugger.html#Command_002dLine-Debugger
3423
3434
// TODO: set-trace! set-break! http://www.lilypond.org/doc/v2.19/Documentation/contributor/debugging-scheme-code
3424
3435
DEFPRIM (pstack , 0 , print_detailed_stack );
3425
-
3436
+ DEFPRIM (break , 0 , breakpoint );
3437
+ // unbound: foo
3438
+ // (restart 3) ask and return other value
3439
+ // (restart 2) ask for value and set it
3440
+ // (restart 1) return to top-level
3441
+ // (bkpt datum arg...) breakpoint
3442
+ // (pa) print actual arguments
3443
+ // (apropos "str") list matching functions
3444
+ // (where) one letter command loop
3445
+ // u(p) d(own) g(o)N
3446
+ // (continue)
3447
+ // (break) (break func)
3448
+ // *proc* *args* *result*
3449
+ // Single stepping: e(val), RETURN, d(ebug)
3450
+
3426
3451
// flash stuff - experimental
3427
3452
DEFPRIM (flash , 2 , flash );
3428
3453
DEFPRIM (flashit , 1 , flashit );
@@ -3474,6 +3499,10 @@ void help(lisp* envp) {
3474
3499
printf ("Type 'help' to get this message again\n" );
3475
3500
}
3476
3501
3502
+ PRIM breakpoint () {
3503
+ error (NULL );
3504
+ return nil ;
3505
+ }
3477
3506
// TODO: make it take one lisp parameter?
3478
3507
// TODO: https://groups.csail.mit.edu/mac/ftpdir/scheme-7.4/doc-html/scheme_17.html#SEC153
3479
3508
void error (char * msg ) {
@@ -3482,29 +3511,80 @@ void error(char* msg) {
3482
3511
3483
3512
// restore output to stdout, if error inside print function we're screwed otherwise!
3484
3513
writeputc = origputc ;
3485
-
3486
3514
terpri ();
3515
+
3516
+ // make sure that we don't blow the stack if we get error in the error function!
3487
3517
if (error_level == 0 ) {
3488
3518
error_level ++ ;
3489
- if (level ) { printf ("%%%s\nBacktrace: " , msg ); print_stack (); terpri (); }
3490
- print_detailed_stack ();
3491
- printf ("%s -- see above!\n" , msg );
3519
+ if (!msg ) { // breakpoint
3520
+ int elsave = error_level ; error_level = 0 ;
3521
+ print_stack (); terpri ();
3522
+ int l = level > 0 ? level : 0 ;
3523
+ void print_env (int d ) {
3524
+ l += d ;
3525
+ if (l < 0 ) l = 0 ;
3526
+ if (!stack [l ].envp ) l -= d ;
3527
+ printf (" STACK: " ); print_stack (); terpri ();
3528
+ printf ("CURRENT: " ); prin1 (stack [l ].e ); terpri ();
3529
+ if (stack [l ].envp ) {
3530
+ printf (" ENV: " );
3531
+ prin1 (_env (stack [l ].envp , nil )); terpri ();
3532
+ }
3533
+ }
3534
+ print (stack [l ].e ); terpri ();
3535
+ char * ln = NULL ;
3536
+ while (1 ) {
3537
+ if (ln ) free (ln );
3538
+ printf ("debug %d] " , l - 1 ); fflush (stdout );
3539
+ char * ln = readline_int ("" , READLINE_MAXLEN , lispreadchar );
3540
+ printf ("---------\n" );
3541
+ if (!ln ) break ;
3542
+ if (!strcmp (ln , "q" )) break ;
3543
+ if (!strcmp (ln , "h" ) || !strcmp (ln , "?" )) {
3544
+ printf ("Debug help: q(uit) h(elp) p(rint env) u(p) d(own) b(ack)t(race) EXPR\n" );
3545
+ continue ;
3546
+ }
3547
+ if (!strcmp (ln , "p" )) { print_env (0 ); continue ; }
3548
+ if (!strcmp (ln , "u" )) { print_env (-1 ); continue ; }
3549
+ if (!strcmp (ln , "d" )) { print_env (+1 ); continue ; }
3550
+ if (!strcmp (ln , "bt" )) { print_detailed_stack (l ); continue ; }
3551
+ lisp r = reads (ln );
3552
+ jmp_buf save ;
3553
+ memcpy (save , lisp_break , sizeof (save ));
3554
+ if (setjmp (lisp_break ) == 0 ) {
3555
+ // continue deeper on the stack
3556
+ level ++ ;
3557
+ prin1 (evalGC (r , stack [l ].envp )); terpri ();
3558
+ level -- ;
3559
+ } else {
3560
+ // TODO() if any error above (like aslfkjasdf) it'll mess up the stack?
3561
+ printf ("\n%%back....from error/break\n" );
3562
+ memcpy (lisp_break , save , sizeof (save ));
3563
+ }
3564
+ }
3565
+ if (ln ) free (ln );
3566
+ error_level = elsave ;
3567
+ } else {
3568
+ if (level ) { printf ("%%%s\nBacktrace: " , msg ); print_stack (); terpri (); }
3569
+ print_detailed_stack (0 );
3570
+ printf ("%s!\n" , msg );
3571
+ }
3492
3572
error_level -- ;
3493
3573
} else {
3494
3574
error_level = 0 ;
3495
3575
printf ("%% error(): error inside error... recovering...\n" );
3496
3576
}
3497
3577
3498
3578
if (memcmp (lisp_break , empty , sizeof (empty ))) { // contains valid value
3499
- // reset stack
3500
- level = 0 ;
3501
- stack [ 0 ]. e = nil ;
3502
- stack [0 ].envp = NULL ;
3503
-
3579
+ // Don't reset stack here, where we return could possibly where
3580
+ // TODO: reset stack - cleanup? this doesn't handle recursive errors/debug
3581
+ // level = 0 ;
3582
+ // stack[0].e = nil ;
3583
+ // stack[0].envp = NULL;
3504
3584
longjmp (lisp_break , 1 );
3505
3585
// does not continue!
3506
3586
} else {
3507
- printf ("%%%% error(): NOT inside setjmp, continuing, ...possibly bad \n" );
3587
+ // printf("%% At toplevel \n");
3508
3588
// exit(77);
3509
3589
}
3510
3590
}
@@ -3522,7 +3602,9 @@ void run(char* s, lisp* envp) {
3522
3602
blockGC = 0 ;
3523
3603
level = 0 ;
3524
3604
trace_level = 0 ;
3525
- printf ("%%%% type 'help' to get help\n" );
3605
+ stack [0 ].e = nil ;
3606
+ stack [0 ].envp = NULL ;
3607
+ printf ("\n%%%% type 'help' to get help\n" );
3526
3608
}
3527
3609
// disable longjmp
3528
3610
memset (lisp_break , 0 , sizeof (lisp_break ));
@@ -3612,7 +3694,7 @@ int kbhit() {
3612
3694
3613
3695
int ms = clock_ms ();
3614
3696
int update = 0 ;
3615
- // update every s
3697
+ // update every s for printing status
3616
3698
if (ms - last_ms > 1000 ) {
3617
3699
int tms = (lisp_ticks - last_ticks ) / (ms - last_ms );
3618
3700
if (tms > max_ticks_per_ms ) max_ticks_per_ms = tms ;
@@ -3632,6 +3714,8 @@ int kbhit() {
3632
3714
if (thechar == 'C' - 64 ) {
3633
3715
int c = thechar ;
3634
3716
thechar = 0 ;
3717
+ printf ("^C\n" );
3718
+ // This will longjmp back if there is is a stack
3635
3719
error ("CTRL-C" );
3636
3720
// error only returns if couln't longjmp to setjmp position, so keep the ctrl-c
3637
3721
thechar = c ;
@@ -3668,6 +3752,7 @@ void readeval(lisp* envp) {
3668
3752
char * ln = readline_int ("lisp> " , READLINE_MAXLEN , lispreadchar );
3669
3753
global_envp = NULL ;
3670
3754
3755
+ // TODO: get rid of special unquoted commands at toplevel?
3671
3756
if (!ln ) {
3672
3757
break ;
3673
3758
} else if (strncmp (ln , ";" , 1 ) == 0 ) {
@@ -3726,7 +3811,7 @@ void readeval(lisp* envp) {
3726
3811
free (ln );
3727
3812
}
3728
3813
3729
- printf ("OK , bye!\n" );
3814
+ printf ("^D\nOK , bye!\n" );
3730
3815
}
3731
3816
3732
3817
void treads (char * s ) {
0 commit comments