[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Please help with BinSCII



On Wed, 28 Jun 2000 09:20:51 -0500, Rubywand <rubywand@swbell.net>
wrote:

>     Nope; did not forget. You need to fuss with the stack cleanup CALL when
>an ONERR triggers inside a subroutine. The above program uses no subroutines.

See below.

>     Trying to handle both LF and CR/LF makes a nice demo but slows down
>execution for the intended application-- i.e. to just change LF's to CR's.

Well, looking at our two programs, I'm pretty sure mine will either
run at the same speed or faster than yours.  Mine also isn't limited
by the size of the available memory.

>     Neither the POKE 216,0 (ONERR terminate) nor the CALL -3288 stack
>cleanup are necessary here. The POKE 216,0 illustrates good practice; but,
>the CALL -3288 is excessively pedantic in a short program with no subs.

The stack cleanup for subroutines in an Applesoft program is done with
the POP command.  If you do a GOSUB, Applesoft puts the return address
on the stack so that when you use the RETURN command it will know
where to continue running the program.  POP removes that information
from the stack.

When an ONERR GOTO statement is executed it puts information on the
stack so that Applesoft will know where to go back to if you use the
RESUME command.  If you don't do the CALL -3288, that info doesn't
come off the stack so your program will end with a stack imbalance.
This can cause your system to crash for no apparent reason some time
in the future unless you reboot your machine after having run your
program.

I just tested this and every time you run a program where an ONERR
GOTO gets executed, the stack pointer is moved by two bytes.  You NEED
to either put the CALL -3288 in your program to clean up the stack or
you need to tell users to reboot the system or have your program do it
automatically when the program finishes to avoid possible problems.

By the way, it looks like the POKE 216,0 may not be needed as doing a
syntax error at the prompt after a doing an ONERR GOTO without the
POKE doesn't seem to cause a problem.  However, this doesn't mean that
something bad isn't happening, it just doesn't look like it.  :-)  It
is still good programming practice to put the POKE in and it is a good
idea to always have both the POKE and CALL somewhere in your program
so that people learning to program that might look at your source can
get a better grasp of when and why they should be used.

>     Getting rid of the RAM buffer is definitely worthwhile. On the other
>hand, it looks like the code you use is going to produce a BINSCIIX file
>filled with nothing but CR's.

Oops.  You are correct.  Like I said, I didn't test it, I just typed
it into my news reader.  Here is a corrected version.

100 ONERR GOTO 210
110 D$ = CHR$(4)
120 PRINT D$;"OPEN BINSCII.EXE"
130 PRINT D$;"OPEN BINSCIIX"
140 PRINT D$;"READ BINSCII.EXE"
150 LC$ = C$:GET C$
160 IF C$ = CHR$(10) AND LC$ = CHR$(13) THEN 150
170 PRINT D$;"WRITE BINSCIIX"
180 IF C$ = CHR$(10) THEN PRINT CHR$(13);: GOTO 140
190 PRINT C$;
200 GOTO 140
210 POKE 216,0: CALL -3288
220 PRINT D$;"CLOSE"
230 END

In this case, line 160 checks to see if the current character is a
line feed and if the character before it was a carriage return.  If
this is true it means we are dealing with a CR/LF end of line marker
so we can safely ignore all the line feeds so it just gets the next
character in the source file.

In line 180, because we are ignoring the line feed from files with
CR/LF as the end of line marker, we know that this line will only be
executed if the end of line marker is either carriage return or line
feed only.  If it is a line feed, we put a carriage return in the
destination file.  All other characters, including carriage return,
simply fall through to line 190 and are added to the destination file.

The reason line 180 has its own PRINT command and goes back to get the
next character rather than using lines 190-200 to do that is so that
the last character variable LC$ doesn't get messed up.  If I were to
change C$ into a carriage return, then in a file with line feed as the
end of line marker, if there was more than one line feed in a row (the
file has blank lines in it) then every second line feed would be
ignore because line 160 would see the current character as a line feed
and the last character as a carriage return when the last character
was actually a line feed.

I'm pretty sure this version will work okay.  :-)

+------------------------------------------------------------------------+
| Jeff Blakeney - Dean of the Apple II University in A2Pro on Delphi     |
|                    Delphi Apple II Forums Web Pages                    |
| A2: http://www.delphi.com/apple2   A2Pro: http://www.delphi.com/a2pro  |
+------------------------------------------------------------------------+