Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

Rainbow Magazine preflight tool enhanced

Jerry Stratton, May 4, 2022

The Dragon’s Gold

I’ve been silently updating the Rainbow preflight tool (Zip file, 3.2 KB) over the last couple of years, but I just added a feature that I thought worth talking about. I was typing in Charles Husak’s “Quest of the Dragon’s Gold” from the August 1984 Rainbow and the line numbers are all over the place. But between pages 32 and 36 the line number jumps from 2790 to 2840, which seemed excessively odd even for this particular program.

I did a search on the obvious line numbers that might exist to see if there were any GOTOs, GOSUBs, or so on, to the potentially missing section, and didn’t find any. But given how uneven the line numbers were, that wasn’t a great check. It occurred to me that I could have the rainbow script keep track of (a) all of the line numbers in the listing, and (b) all of the line numbers referenced in the code, and then cross reference them.

This was fairly simple to do: there’s a subroutine to collect the line numbers, and a loop that provides a warning for every line number that doesn’t exist. Here’s the subroutine:

[toggle code]

  • sub collectLineReferences {
    • my $lineNumber = shift;
    • my $lineText = shift;
    • $existingLines[$#existingLines+1] = $lineNumber;
    • while ($lineText =~ m/(GO *TO|GO *SUB|THEN) *([0-9]+)/g) {
      • $lineReferences[$#lineReferences+1] = [$lineNumber, $1, $2];
    • }
  • }

And here are the warnings:

[toggle code]

  • #verify that all line number references go to a line that exists
  • %existingLines = map { $_ => 1 } @existingLines;
  • foreach $lineReference (@lineReferences) {
    • ($lineNumber, $referenceType, $referencedLine) = @$lineReference;
    • if (!exists($existingLines{$referencedLine})) {
      • print STDERR "\t$referenceType to non-existent line $referencedLine in $lineNumber\n";
    • }
  • }
Moire pattern start

A moire pattern in PMODE 4.

The bottom line for “Dragon’s Gold” is that the program really does jump from 2790 to 2840, though, unfortunately, the program POKEs machine language code over the listing itself when using Disk BASIC, so I can only run it in emulation anyway. But this should be a useful sanity check for typing errors, as well.

The script will not print multiple warnings for non-existent line numbers that are higher than the maximum line number. That’s likely caused by not having finished typing the program yet. It will warn if there’s only one such high non-existent line, but if there are two or more it will simply report the number of such lines. If you want to see all of the high non-existent lines, use the --warnings switch.

[toggle code]

  • % ~/bin/rainbow moire.txt --warnings
    • THEN to non-existent line 350 in 250
    • GOTO to non-existent line 600 in 260
    • GOSUB to non-existent line 380 in 290
    • THEN to non-existent line 390 in 300
    • GOSUB to non-existent line 430 in 300

There’s also now an option to warn on uneven line number increments. Because Extended Color BASIC has a renumber command, many listings are perfectly regular. Most commonly, they’re all increments of 10, so that’s the default if you just add --regular to the command line. But increments of 1 or 2 are also common because smaller line numbers save memory, so you can also specify the expected increment.

[toggle code]

  • % rainbow --warnings --regular 1 raceday.txt
  • WARNING:
    • LINE 6: uneven increment: 4 to 6
    • LINE 8: uneven increment: 6 to 8
    • LINE 34: uneven increment: 32 to 34
    • LINE 60: uneven increment: 58 to 60
    • LINE 86: uneven increment: 84 to 86
A Day at the Races

Ah, the excitement of a day at the races!

You can also add lines of code that are ignored unless you use the --customize switch. Most of the time when I run this script, I’m running it on Rainbow listings, and immediately using rcheck on the result. Any custom code—such as fixes from later issues—will mean the rcheck checksum is off. With this feature, I can add the custom code and it will be ignored until such time as I give up trying to make the checksums come out correctly.

Custom lines must be preceded by double slashes, as in:

  • 560 I$=INKEY$
  • 570 IFI$=""THEN560
  • //571 IF I$="M" THEN RUN "AUTOEXEC:1"
  • //572 IF I$="Q" THEN END
  • 580 PMODE3,1:PCLS:SCREEN1,1

Lines 571 and 572 will normally be ignored, but if the --customize switch is used, they will be output as is at that point.

Even though this is a Rainbow file, the custom lines should not be broken into 32-character segments. Since these aren’t from the magazine, there’s no need for that.

Lesser changes include:

  • There are some characters that are extremely unlikely in typed text rather than impossible on the CoCo, such as shifted arrows. I’ve moved those from errors to warnings.
  • Checking for mismatched parentheses has been vastly improved. Mismatched parentheses inside of strings are now ignored, as they were often used for lists or other display purposes. Mismatched parentheses are also fine in a DATA statement.
  • The warning about lower case is also unnecessary inside of strings.
  • Warnings about potential errors in PUT/LINE statements has also been improved.
  • There are now warnings if the new subline could potentially be a new line but is interpreted as a continuation of the previous line. This can happen when the previous subline is 32 characters long and the new subline begins with a number and a space.

In response to Rainbow Magazine BASIC program preflight tool: This script takes 32-character lines typed in from Rainbow Magazine BASIC listings and assembles them together into full BASIC lines, doing some rudimentary error-checking along the way.