From: rfd@po.CWRU.Edu (Richard F. Drushel)
Newsgroups: alt.folklore.computers
Subject: Renumbering BASIC programs (was Re: Branching in HLL vs. Assembler)
Date: 1 Sep 1992 20:34:17 GMT
Organization: Case Western Reserve University, Cleveland, OH (USA)
Reply-To: rfd@po.CWRU.Edu (Richard F. Drushel)
NNTP-Posting-Host: slc12.ins.cwru.edu


In a previous article, avg@rodan.UU.NET (Vadim Antonov) says:

>In article <1992Sep1.083701.2898@pollux.lu.se> magnus@thep.lu.se (Magnus Olsson) writes:
>>Speaking of spaghetti code, one common reason for writing spaghetti
>>code was (is?) the lack of a line-renumbering utility in primitive
>>BASICs...
>>
>> [example deleted]
>>
>>Horrible? Yes, of course, but the alternative (manually renumbering
>>maybe hundreds of lines) would be even worse.
>
>And writing a 10-lines long program to do it automatically is 
>obviously above mental abilities of both users and authors of
>such BASIC interpreters.
>
>Not funny.

	Also not so easy--depending upon what dialect of BASIC you
are working with.  To do the equivalent of RENUM newline,oldline,step
you must:

	(1)  Read the target program in line-by-line, excising the
starting line numbers from the string and saving them in a 2-D array.
You may have to do some checking on newline to make sure it's greater
than the last line before oldline, so you don't change the order of
the renumbered lines; otherwise it's an error and you abort.  Otherwise,
fill in the 2nd dimension of the line number table array with the
renumbered counterparts to the original line numbers, using the
oldline, newline and step parameters.  You can't exceed 65535, either.

	(2)  Having made one complete pass through the target program,
rewind back to the start and open the output file.  Start parsing
each line for commands which have line number arguments.  Some flavors
of BASIC have an INSTR$ function which will automatically search for
a specified substring (in this case, a command like GOTO); but most
only give you MID$, so you have to scan along character-by-character
until e.g. you find a "G"; if so then see if it's part of "GOTO" or
"GOSUB" or not.  Again, it depends on what BASIC you've got for how
many different commands take line number arguments.  In MicroSoft
BASIC you have:

	GOTO nnnn
	IF condition THEN nnnn
	IF condition THEN something ELSE nnnn
	ON variable GOTO nnn1,nnn2,...nnnn
	ON variable GOSUB nnn1,nnn2,...nnnn
	GOSUB nnnn
	RETURN [nnnn]
	RESTORE [nnnn]
	RESUME [nnnn]
	RETURN [nnnn]       [] means optional

	(3)  Assuming you've found a keyword, and it's not contained
in a REM statement or as an immediate string or data, extract the
line number string, convert it to a number, and fetch its renumbered
equivalent out of the line number table array.  If the oldline is
not an existing program line (i.e. an orphan due to error or oversight
or the program not being completed), then don't change it, but print a
warning message on the console.

	(4)  Convert the new line number to a string, and write it
to the editing buffer where you're making a copy of the old line as
you parse through it.  When you have finished parsing all of the old
source line, write the new version to the output file.

	(5)  Keep doing this until you reach source EOF, CLOSE the
files, and END.

	If all this can be done in 10 (multi-statement) lines of
reasonable length, I would very much like to see it :)

	And this is, of course, a BASIC program to renumber another
BASIC program.  What goes on inside the interpreter itself is
another can of worms.  Here there isn't really any excuse for not
providing a RENUM command, except in the oldest of memory-starved
systems.  Here you will admittedly find some brain-damaged design.

	In the SmartBASIC interpreter for the Coleco ADAM, source
program lines are parsed into tokens, which are used during actual
interpretation when the program is RUNning.  Internally, there is
a line number table of the form DEFW line1,addr1,...linen,addrn
where line is the line number and addr is a pointer to the tokenized
form of that particular line.  So to RENUM just the starting line
numbers is trivial.  Unfortunately, the internal references in
each tokenized line are *NOT* pointers back to the line number
table, but instead are tokenized representations of the actual line
number.  Worse, SmartBASIC numbers are tokenized as either 1, 2 or 3
bytes depending on value 0-9, 10-255, or 256-65535.  This means that
if you change GOSUB 100 to GOSUB 1000, the tokenized line has to
grow in size by 1 byte--and that means shifting all the other
tokenized lines, and changing all the addr pointers in the line
number table!  An awful lot of LDIRs.  Whereas if the internal
line number references had just been pointers, renumber the line
number table would have been sufficient, and you would not have
to reparse the tokenized lines looking for GOTO and GOSUB tokens.
*THAT* I agree is brain-damaged implementation.
-- 
Rich Drushel ** rfd@po.CWRU.edu *** Biology Ph.D. Student ** Cleveland FreeNet
Co-Sysop, Coleco ADAM Forum --- Assistant Sysop, Science Fiction & Fantasy SIG
"Solda pung apfashat ro des-marno, / Marn ladir o armag noth yeni arno. / Hell
miryat it, / Jambo iat it, / Os lasse wei ticip kati baldo." / Old Ennish poem
Newsgroups: alt.folklore.computers