Structured SuperBasic Version 2.5

Authors

Publication

Pub Details

Date

Pages

See all articles from QL Hacker's Journal 22

Structured SuperBasic (SSB) has been sitting on my shelf for a number of years without having any upgrades. I really only upgrade SSB when there is a new feature that I need SSB to support. Since I’ve had the Pointer Environment (PE) for just over a year, I’ve always wanted to do some programming supporting it. Only recently have I picked up two utilites that will help me do this; QMENU and EasyPointer II.

My intention is to create a version of SSB that will work under the PE. But, before I could get there, I needed to upgrade SSB to give me some new features. Version 2.5 provides some of these features and is designed to have a limited life until version 3.0 comes out. There will be a version 2.6. I’ve finally decided to use a few ToolKit II extensions in SSB, hoping to make it better. Version 2.6 will incorporate these extensions.

The biggest upgrade in version 2.5 is the support of conditional “compilation.” Anyone familiar with the C Preprocessor is familiar with conditional compilation. Through the use of #DEFINE, #IFDEF, and #ENDIF statements, various parts of source code can be left out of the final code. With the setting of one variable, a program can be compiled to support MS-DOS while changing the variable can allow it to support UNIX.

Note that I put quotes around the word “compilation.” Since SSB is really just a filter that converts SSB source code to a SuperBasic ready form, there really is no compilation.

Version 2.5 also supports imbedded print filter directives. I use a couple of “home-grown” print filters for printing out various texts. I have adopted the NROFF and WordStar conventions of using dot (.) commands for imbedding formatting commands into the text. A dot command is something like this:

.boldon

This command tells the print filter to set the bold feature on. SSB version 2.5 allows you to imbed these commands in your SSB code so that you can send the source code through one of these filters and allow you to produce a nice listing. This concept is similar to Web programming. Web, designed by Donald Knuth, believes that the code should be self documenting, and to this end believes that the documentation and source code should be one and the same.

Dot commands must start in the first character of a line.

Version 2.5 supports the / directive of line continuation. In the old days of line editors, if you went past the 80th character in your code, you put in a / to tell the compiler that the rest of the code for that line is on the next line. Since SSB is written using editors based on 80 character screens, it is handy to not have real long code lines, especially when indenting to show nesting and program structure.

To use /, the / character must be the last character of the line. The next line will be read in and appended to the current line. The one caveat is that you may not have two line continuation marks in a row. This means the following:

This will not work:

     IF var = something THEN /
LET some_variable = /
some_other_variable

But this will work:

     IF var = something THEN /
LET some_variable = some_other_variable
IF var = something_else THEN /
LET some_variable = nothing

The big difference is that the continuation line does not have a continuation itself.

** Test file for showing Conditional "Compilation"

#define TEST
##define NOTEST

#ifdef TEST
print "This is test"
print "TEST is defined"
#endif

#ifdef NOTEST
print "This is not a test"
print "NOTEST is defined"
#endif

#ifdef TEST
print "This is a second test"
print "TEST is defined"
#endif

print "This code should appear"
print "This code should also appear

This version of SSB has not been rigorously tested. I’ve tested the conditional “compilation” using the test file above. There might be a case in which this program fails. Since this is a limited life program (before the next upgrade), I’m not too worried about it’s bugs. Consider this to be a beta version of 3.0. If you encounter any problems, bugs, or have comments on SSB or my lack of good programming, please let me know.

One note of thanks to Herb Schaaf who helped me over a stumbling block in my code. He fixed the problem I could not figure out. Sometimes it can hinder you when you are too close to the code. It makes you read what is not there.

## Structured SuperBasic Filter
## Author: Timothy Swenson
## Date Created: 16 Oct 1990
## Date Revised: 5 Sept 1995
## Version: 2.5

## This program takes in SSB code and outputs a file
## that is runnable in SuperBasic

## Init Variables
DIM label$(30,16)
DIM label(30)
DIM defn$(30,16)
label_var = 1
define_var = 1
num_count = 0
file_num = 5

OPEN #3,con_300x200a75x0_32
BORDER #3,2,4
PAPER #3,0 : INK #3,4 : CLS #3

PRINT #3," STRUCTURED SUPERBASIC FILTER"
PRINT #3," Version 2.5"
PRINT #3," by Timothy Swenson"
PRINT #3

PRINT #3,"Enter input file: ( _ssb) "
INPUT #3,in_file$
PRINT #3,"Enter output file: (default ";in_file$;"_bas) "
INPUT #3,out_file$
PRINT #3,"Enter Starting Line Number: (default 100) "
INPUT #3,line_num$
PRINT #3,"Enter Increment for Line Numbers: (default 10) "
INPUT #3,line_delta$

## Default for the output file is the input file with
## a _bas extension.
IF out_file$ = "" THEN out_file$=in_file$&"_bas"

in_file$ = in_file$&"_ssb"

## Default for the starting line number is 100.
IF line_num$ = "" THEN
line_num_d = 100
ELSE
line_num_d = line_num$
END IF

## Default for line number increment is 10.
IF line_delta$ = "" THEN
line_delta = 10
ELSE
line_delta = line_delta$
END IF

line_num = line_num_d
PRINT #3," PASS 1"

pass_one in_file$, file_num

line_num = line_num_d
PRINT #3
PRINT #3," PASS 2"

num_count = 0
file_num = 5

DELETE out_file$
OPEN_NEW #4,out_file$

pass_two in_file$, file_num

CLOSE #4
PRINT #3
PRINT #3,"Program Done"
CLOSE #3
STOP

## Pass_one is strictly designed to count line numbers
## and to find all labels. This allows goto labels to
## refer to code that the filter has not yet seen
## (as compared to a single pass filter).

DEFine PROCedure pass_one (in_file$, file_num)

OPEN_IN #file_num,in_file$
REPeat pass_1
num_count = num_count + 1
IF (num_count MOD 10) = 0 THEN PRINT #3,CHR$(1);
IF EOF(#file_num) THEN EXIT pass_1
INPUT #file_num,in$
## Get first non-space character
temp=first_char(in$)
## Check for Blank Lines
IF temp=0 THEN NEXT pass_1
## If the ** comment line then don't count as a line
IF in$(temp TO temp+1)="**" THEN NEXT pass_1
## Ignore dot commands for print filters
IF in$(temp)="." THEN NEXT pass_1
## A \ is at the end of a line meaning to add the next line
IF in$(LEN(in$))="\" THEN
IF EOF(#file_num) THEN abort_out(1)
INPUT #file_num,in2$
temp = first_char(in2$)
in$ = in$( TO LEN(in$))&in2$(temp TO)
END IF
## If the AT symbol is found, then it's a label
IF in$(1)=CHR$(64) THEN
label$(label_var) = in$
label(label_var) = line_num
label_var = label_var + 1
ELSE
## If it's the include statement then call pass_one again
IF upper$(in$(1 TO 8))="#INCLUDE" THEN
pass_one in$(10 to ), file_num+1
ELSE
IF upper$(in$(1 TO 7))="#DEFINE" THEN
defn$(define_var) = upper$(in$( 9 TO))
define_var = define_var+1
ELSE
IF upper$(in$(1 TO 6))="#IFDEF" THEN
temp1 = 0
temp$ = upper$(in$(8 TO))
FOR x = 1 TO define_var
IF temp$ = defn$(x) THEN temp1 = 1
NEXT X
IF temp1 = 0 THEN
REPEAT loop
IF EOF(#file_num) THEN abort_out(1)
INPUT #file_num,in2$
IF upper$(in2$(1 TO 6))="#ENDIF" THEN EXIT loop
END REPeat loop
END IF
ELSE
line_num = line_num + line_delta
END IF
END IF
END IF
END IF
END REPeat pass_1

CLOSE #file_num
END DEFine pass_one

## Pass_two does the main work of the filter.
## It adds the line numbers and the goto references.

DEFine PROCedure pass_two (in_file$, file_num)

OPEN_IN #file_num,in_file$
REPeat pass_2
num_count = num_count + 1
IF (num_count MOD 10) = 0 THEN PRINT #3,CHR$(1);
IF EOF(#file_num) THEN EXIT pass_2
INPUT #file_num,in$
temp=first_char(in$)
## Ignore blank Lines
IF temp=0 THEN NEXT pass_2
## Ignore Labels
IF in$(1)=CHR$(64) THEN NEXT pass_2
## Ignore ** comments
IF in$(temp TO temp+1)="**" THEN NEXT pass_2
## Ignore dot commands
IF in$(temp)="." THEN NEXT pass_2
## Ignore #DEFINE commands since DEFINE table is already established
IF upper$(in$(1 TO 7))="#DEFINE" THEN NEXT pass_2
## A \ is at the end of a line meaning to add the next line
IF in$(LEN(in$))="\" THEN
IF EOF(#file_num) THEN abort_out(1)
INPUT #file_num,in2$
temp = first_char(in2$)
in$ = in$( TO LEN(in$))&in2$(temp TO)
END IF
IF in$(temp TO temp+1)="##" THEN
PRINT #4,line_num;" remark ";in$(1 TO temp-1);in$(temp+2 TO )
line_num = line_num + line_delta
ELSE
temp = CHR$(64) INSTR in$
IF temp<>0 THEN
a$ = in$(temp TO )
temp2 = 0
@label1
temp2 = temp2 + 1
IF temp2 > 30 THEN
PRINT #3,"Warning - Label ";a$;" Not Found"
END REPeat pass_2
END IF
IF label$(temp2) <> a$ THEN GO TO @label1
PRINT #4,line_num;" ";in$(1 TO temp-1);label(temp2)
line_num = line_num + line_delta
ELSE
IF upper$(in$(1 to 8))="#INCLUDE" THEN
pass_two in$(10 to), file_num+1
ELSE
IF upper$(in$(1 TO 6))="#IFDEF" THEN
temp1 = 0
temp$ = upper$(in$(8 TO))
FOR x = 1 TO define_var
IF temp$ = defn$((x),1 TO LEN(temp$)) THEN temp1 = x
NEXT X
IF temp1 = 0 THEN
REPEAT loop
IF EOF(#file_num) THEN abort_out(1)
INPUT #file_num,in2$
IF upper$(in2$(1 TO 6))="#ENDIF" THEN EXIT loop
END REPeat loop
END IF
ELSE
IF upper$(in$(1 TO6))<>"#ENDIF" THEN
PRINT #4,line_num;" ";in$
line_num = line_num + line_delta
END IF
END IF
END IF
END IF
END IF
END REPeat pass_2
CLOSE #file_num
END DEFine pass_two


## Function first_char
## returns the location of the first non-white
## space character.
DEFine FuNction first_char (a$)
LOCal count
count=0
@label2
count=count+1
IF count > LEN(a$) THEN RETurn 0
IF a$(count)=" " THEN GO TO @label2
RETurn count
END DEFine first_char

## Function upper$
## Takes in input string and returns the
## same string in all upper case letters.
DEF FuNction upper$(up$)
LOCal x, temp

FOR x = 1 TO LEN(up$)
temp = CODE(up$(x))
IF temp > 96 AND temp < 123 THEN up$(x)=CHR$(temp-32)
NEXT x
RETURN up$
END DEFine

## Procedure abort_out
## A separate procedure to neatly close all
## of the files and exit the program.
## Usually reserved for fatal errors.
DEF PROCedure abort_out(err_code)

## error = 1 End of File while doing an #IFDEF

IF err_code = 1 THEN
PRINT #3,"FATAL ERROR - #ENDIF not found before end of file"
IF file_num = 5 THEN
CLOSE #5
ELSE
FOR x = 5 TO file_num
CLOSE #x
NEXT X
END IF
CLOSE #4
CLOSE #5
CLOSE #3
STOP
END IF

END DEFine

Products

 

Downloadable Media

 

Image Gallery

Scroll to Top