--- title: "Structured SuperBasic Version 2.5" type: "article" slug: "structured-superbasic-version-2-5" url: "http://localhost/article/structured-superbasic-version-2-5/" markdown_url: "http://localhost/article/structured-superbasic-version-2-5.md" published_at: "2025-12-18T17:59:33+00:00" modified_at: "2026-06-21T23:20:42+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "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…" category: - name: "QL Hacker's Journal" slug: "ql-hackers-journal" taxonomy: "category" url: "http://localhost/category/periodicals/ql-hackers-journal/" post_tag: - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "QL" slug: "ql" taxonomy: "post_tag" url: "http://localhost/tag/ql/" - name: "Superbasic (programming language)" slug: "superbasic-programming-language" taxonomy: "post_tag" url: "http://localhost/tag/superbasic-programming-language/" model: - name: "Sinclair QL" slug: "sinclair-ql" taxonomy: "model" url: "http://localhost/model/sinclair-ql/" indiv: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" publication_r: id: 33686 title: "QL Hacker’s Journal" type: "periodical" url: "http://localhost/periodical/ql-hackers-journal/" authors_r: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" issue: "22" issues_articles: - id: 61558 title: "QL Hacker’s Journal 22" type: "issue" url: "http://localhost/issue/ql-hackers-journal-22/" pubdate: "October 1995" archive_link: true --- # Structured SuperBasic Version 2.5 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](http://localhost/indiv/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 ```