Basic Renumber

This file is part of and Miscellaneous Programs. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068

This program is a BASIC renumbering utility that operates in two distinct parts. Lines 9949–9956 implement a line-listing display routine that walks through program memory using the system variable at address 23635–23636 (PROG, the start-of-BASIC pointer) to read and print each line number and its tokenised source. Lines 9957–9998 form the renumbering engine: it prompts for a start number and step, then scans the program body from address 26710 (stored in `bs`) to patch line headers via direct POKE operations and resolve all GO TO and GO SUB targets (token bytes 236 and 237) by scanning the ASCII digits before the embedded five-byte floating-point literal (token 14). The renumberer searches backward through digit characters to reconstruct the referenced line number, locates it in the program, calculates its new number, and prints the updated value — notably it prints rather than POKEs the GO TO/GO SUB arguments, meaning the user sees what needs changing rather than having them automatically rewritten. The program saves itself with SAVE “BASRENUM” at line 9999.


Program Structure

The listing splits cleanly into two functional sections, both residing at the top of the line-number space (9949–9999) so they can coexist with any user program loaded below them:

  1. Lister (9949–9956): Reads the PROG system variable from addresses 23635–23636, iterates through the tokenised program body, and prints each line with its line number right-aligned at column 4-LEN STR$ l.
  2. Renumberer (9957–9998): Accepts a start number and step, walks the program from the hard-coded base address stored in bs (26710), rewrites line-header bytes with POKE, and identifies but only prints GO TO / GO SUB targets rather than patching them automatically.

Key Variables

VariableRole
gByte pointer into program memory; also reused as new start line number
lCurrent line number (lister) / decimal place accumulator (renumberer)
bsHard-coded base address of the program to renumber (26710)
ffRenumber step size
mRunning new line number counter
iByte pointer used by the renumberer scan loop
j, k, nOffset counter, target line number, and ordinal index of matched line
hToken discriminator: 1 = GO TO (236), 2 = GO SUB (237)

Memory Layout Assumptions

The lister uses the standard system variable PROG held as a 16-bit little-endian word at 23635–23636. Each BASIC line in memory follows the layout: [high byte of line no.][low byte of line no.][length low][length high][tokens…][0x0D]. The lister reconstructs the line number as PEEK g * 256 + PEEK (g+1) (big-endian), advances g by 4 to skip the header, then prints tokens until it encounters a newline byte (13).

The renumberer hard-codes bs = 26710 as the start of the target program. This means the utility and the program being renumbered must coexist in memory at a known layout; the constant would need manual adjustment for a different host address.

Token Detection Idioms

The five-byte floating-point embedded number is detected by token byte 14. The renumberer skips these literals in the lister (line 9952) and uses their presence as an anchor when reconstructing a GO TO / GO SUB argument (line 9974–9977).

GO TO and GO SUB are identified by their token codes 236 and 237 respectively. The boolean expression on line 9965 exploits the fact that 1 AND condition evaluates to 1 or 0, giving h the value 1, 2, or 0 — a compact multi-way flag without IF chains.

The keyword strings on line 9969 use string multiplication by a boolean: (" GO TO " AND h=1) produces the string when true, or an empty string when false — a classic Spectrum BASIC string-selection idiom.

Renumbering Algorithm

  1. Walk lines from bs; at each newline (byte 13), check whether the following byte exceeds 34 (i.e., the line number MSB is in range). If above 34, branch to the POKE phase (9990).
  2. For each GO TO / GO SUB found, scan forward up to 5 bytes to locate the embedded float marker (14), then read the ASCII digit characters backward to reconstruct the decimal target line number k.
  3. Count how many lines from bs have a header value less than k to find ordinal n, then compute the new target as g + n * ff.
  4. Print (do not POKE) the new target value — the user must manually correct GO TO / GO SUB arguments or use a companion editor.
  5. The POKE phase (9990–9998) iterates all lines and rewrites the two-byte big-endian line number in each header, splitting the new value into high byte (j) and low byte (g after repeated subtraction of 256).

Notable Techniques

  • Right-aligning line numbers in the lister via AT PI,4-LEN STR$ l — using PI (truncated to 3) as the row avoids a separate row variable.
  • Skipping floating-point literals with IF PEEK g=14 THEN LET g=g+6 (line 9952) — the token plus 5 bytes of IEEE-like mantissa/exponent.
  • The digit-reconstruction loop (9978–9982) walks right-to-left through ASCII digit bytes, accumulating k using an explicit powers-of-ten multiplier l.
  • PAUSE 0 on line 9956 halts the lister between pages, consistent with the keypress-wait idiom.

Bugs and Anomalies

  • The renumberer only prints GO TO / GO SUB new targets; it does not patch them. The program is therefore a semi-automatic aid rather than a fully automatic renumberer — the user must act on the printed output.

Content

Related Products

Related Articles

Related Content

Image Gallery

Source Code

 9949 LET g=PEEK 23635+PEEK 23636*256
 9950 LET l=PEEK g*256+PEEK (g+1): LET g=g+4
 9951 PRINT AT PI,4-LEN STR$ l;l;
 9952 IF PEEK g=14 THEN LET g=g+6
 9953 IF PEEK g=13 THEN LET l=0
 9954 PRINT CHR$ PEEK g;: LET g=g+1
 9955 IF l THEN GO TO 9952
 9956 PAUSE 0: CLS : GO TO 9950
 9957 LET bs=26710: REM RENUM STARTS HERE 
 9958 INPUT " INPUT start no. ";g: INPUT " THEN INPUT STEP ";ff
 9959 LET m=g: CLS 
 9960 PRINT "Change these lines": LET i=bs+4
 9961 IF PEEK i<>13 THEN GO TO 9965
 9962 IF PEEK (i+1)>34 THEN GO TO 9990
 9963 LET m=m+ff
 9964 LET i=i+5
 9965 LET h=(1 AND PEEK i=236)+(2 AND PEEK i=237)
 9966 IF PEEK i=14 THEN LET i=i+5
 9967 IF h THEN GO SUB 9969
 9968 LET i=i+1: GO TO 9961
 9969 PRINT m;(" GO TO " AND h=1)+(" GO SUB " AND h=2);
 9970 LET h=0
 9971 IF PEEK (i+1)>=48 AND PEEK (i+1)<58 THEN GO TO 9973
 9972 PRINT " * ": RETURN 
 9973 LET j=2
 9974 IF PEEK (i+j)=14 THEN GO TO 9978
 9975 LET j=j+1
 9976 IF j>5 THEN GO TO 9972
 9977 GO TO 9974
 9978 LET l=1: LET k=0
 9979 LET k=k+(PEEK (i+j-1)-48)*l
 9980 LET j=j-1
 9981 IF PEEK (i+j-1)=236 OR PEEK (i+j-1)=237 THEN GO TO 9983
 9982 LET l=l*10: GO TO 9979
 9983 LET j=bs: LET n=0
 9984 IF PEEK j*256+PEEK (j+1)>=k THEN GO TO 9988
 9985 LET n=n+1
 9986 LET j=j+(PEEK (j+2)+PEEK (j+3)*256)+4
 9987 GO TO 9984
 9988 LET k=g+n*ff
 9989 PRINT k: RETURN 
 9990 LET j=0: LET i=bs
 9991 GO SUB 9994
 9992 LET i=i+PEEK (i+2)+PEEK (i+3)*256+4
 9993 GO TO 9991
 9994 IF PEEK i>34 THEN STOP 
 9995 IF g<256 THEN GO TO 9997
 9996 LET j=j+1: LET g=g-256
 9997 POKE i,j: POKE (i+1),g
 9998 LET g=g+ff: RETURN 
 9999 SAVE "BASRENUM"

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top