Jim (abc@def.ghi) wrote: (code snipped) : The reason you are getting "RETURN WITHOUT GOSUB" is because there was : no GOSUB! You used OnERR GOTO! You can't RETURN from a GOTO! You : either need an OnERR GOSUB, or just use a GOTO xxx where xxx is : wherever you want to return to. : Jim I snipped the code, but you should look more closely. Schematically it was something like this (presented as if in Assembly)-- begin Start the program ; Say hello. main Make things happen ; Main program loop...do stuff. GOSUB readfile ; jump to read file routine. ret1 Manipulate file ; RETURN should come back here. INPUT "Again?";Y$ ; Do it all again? IF Y$<>"N" THEN main ; Yes; repeat main loop. END ; Else end main loop. readfile err = 6 ; Simulate FILE NOT FOUND. goto errhand ; Don't wait for the error. read1 open file ; Stuff that can cause read file ; the expected non-fatal close file ; and unexpected fatal errors. file exists = true ; Tell main loop file exists. RETURN ; Will return to ret1. errhand if err=6 then fnf ; =FILE NOT FOUND error. print "Fatal error!" ; unexpected error! STOP ; stop here! fnf file exists = false ; Tell main loop file !exists. REM POKE 216,0 ; Turn off ONERR handling. RETURN ; Will return to ret1. This bit of meta-code is more or less what was attempted. Notice that at "readfile" we don't wait for an error, we just jump to the error handler at "errhand". Since err was set to 6, "errhand"'s test for an expected error will succeed, branching to the non-fatal-error handler "fnf" which sets a "no file" flag and executes a RETURN. That RETURN will go back to ret1, which is exactly where we want it to go. The presence of a GOTO in there in the "readfile" routine makes no difference. We don't want to return to "read1" anyway! So if that code works (and I assure you, if you translate it into proper Applesoft, it will), then why does this code fail: begin Start the program ; Say hello. main Make things happen ; Main program loop...do stuff. GOSUB readfile ; jump to read file routine. ret1 Manipulate file ; RETURN should come back here. INPUT "Again?";Y$ ; Do it all again? IF Y$<>"N" THEN main ; Yes; repeat main loop. END ; Else end main loop. readfile err = 0 ; Applesoft will set the error code. onerr goto errhand ; Call handler if something goes wrong. read1 open file ; Stuff that can cause read file ; the expected non-fatal close file ; and unexpected fatal errors. file exists = true ; Tell main loop file exists. RETURN ; Will return to ret1. errhand if err=6 then fnf ; =FILE NOT FOUND error. print "Fatal error!" ; unexpected error! STOP ; stop here! fnf file exists = false ; Tell main loop file !exists. POKE 216,0 ; Turn off ONERR handling. RETURN ; Will generate ?RETURN WITHOUT GOSUB. It's exactly the same, except that now the GOTO is conditional...it will only be taken if something goes wrong. This means the code in "read1" will actually be executed, and if successful will hit the first RETURN and go back to ret1. If something in "read1" generates an error, control goes to errhand, if the error was not #6 the program will crash with a "BREAK IN ";errhand+2. If the error WAS a #6, the FILE NOT FOUND that we expect, we go to the non-fatal error handler at fnf, which sets the no-file flag, turns off error handling, and then promptly...generates a ?RETURN WITHOUT GOSUB error. Structurally, nothing has changed. There is no POP statement in there to clear the GOSUB, we are still ultimately reaching the error handler via the original GOSUB to "readfile", so why doesn't it work? Clearly, the reason is that when Applesoft triggers the error handler and leaps to "errhand", it clears the stack, POPping the GOSUB address from "main" and leaving the RETURN from "fnf" with no place to go. Applesoft does not have an ONERR GOSUB, which is sensible for two reasons. First and most obviously because it is silly...most recoverable errors require some recovery procedure, and without knowing exactly where the error happened you wouldn't want to go back there! Second, since the GOSUB stack apparently gets trashed in the error trapping process, it wouldn't work anyway! Most critically, it could put you into a situation where you have an unknown number of GOSUB nesting layers, which would cause an otherwise perfect program to either generate a ?RETURN WITHOUT GOSUB error, a ?NEXT WITHOUT FOR error, or to leave extra data lying on the stack to cause trouble. The moral, then, is that if you have non-fatal errors to trap with ONERR GOTO, do not put them in subroutines, and do not put them in FOR...NEXT loops. If you have routines that routinely generate non-fatal errors which must be called from various points in the program, consider doing it this way to simulate the GOSUB-- REM MAIN PROGRAM LOOP 10 SRC=1:GOTO fread 15 (do stuff) 290 SRC=2:GOTO fread 300 (do stuff) 540 SRC=3:GOTO fread 550 (do stuff) 620 SRC=4:GOTO fread 621 (do stuff) 740 SRC=5:GOTO fread REM FILE READ ROUTINE...USE ME A LOT fread ON ERR GOTO frerr UNLOCK F$ OPEN F$ READ F$ get data CLOSE F$ RET=0 ; return code = success POKE 216,0 frexit ON SRC GOTO 15,300,550,621,63990 frerr POKE 216,0 RET=errcode GOTO frexit 63990 (end program) I had to throw in that last little trick...line 740 calls the "subroutine" at fread, but when the routine returns it returns to 63990 instead of to 740+n. Ordinary GOSUB can't do that trick! 8-) --Dave Althoff, ][. -- /-\ _ *** Respect rides. They do not respect you. *** /XXX\ /X\ /X\_ _ /X\__ _ _ _____ /XXXXX\ /XXX\ _/XXXX\_ /X\ /XXXXX\ /X\ /X\ /XXXXX _/XXXXXXX\__/XXXXX\/XXXXXXXX\_/XXX\_/XXXXXXX\__/XXX\_/XXX\_/\_/XXXXXX