SBhtm

In the May 2015 issue of QUANTA, the magazine, I published a program called SBldr. It takes a S*BASIC source code file and EXecutes it, as if it were a normal machine code job. No big deal, it is true. However, the X-factor here is that if the source code doesnt contain line numbers (in which case it cant be EXecuted) SBldr adds them on the fly, as it were, allowing the program to EXecute even so.

The example below takes it to the next level. One of the points of this example utility is to demonstrate invoking an instance of the SBASIC Thing (which, in theory can be done from any programming language) and harnessing its capabilities, in this case to tokenise a S*BASIC source file. The point of the program featured is to convert S*BASIC source code seamlessly to HTML, using my sb2htm program. As such, it may be of special interest to creaking SMSQ/E users (like me) who write S*BASIC programs using an editor. Some of the techniques employed may be of interest to anyone interested in S*BASIC, but most will only work under SMSQ/E and SBASIC (although something similar might be attempted in Minerva).

If converting S*BASIC source code to HTML doesnt appeal to you, let me just quickly mention that a small modification to the program presented and explained below, enables you to compile an S*BASIC program directly from within QD (and probably other text editors) or from any FileInfo2-capable file manager, or indeed from the command line, without having to QSAVE the source file first or even to add line numbers. This may seriously speed up program development, testing and debugging.

Ill explain the program first, then the programming.

The problem:

Although screens are getting bigger and better, the QL founts havent changed; if anything, they seem to be getting smaller and harder on the eye than before! While text editors like QD are better than EDIT for writing all but the simplest of programs, they still only sport black on grey or some such combination, and most have no understanding of the code that is being edited.

The solution (part 1):

For me a partially useful solution was my program sb2htm, (available here). It takes a (tokenised) S*BASIC program and converts it to syntax-highlighted, navigable HTML. Colours can be changed to suit, and the browser can display founts as large and clear as you like. (Navigable here means being able to follow the flow of the program via the linked references to PROCedure and FuNction definitions, and then clicking <-Back to return to where you were). The browser's local search box, and the host OS'es fast file searching facilities, spanning multiple file names and contents, can be very useful at times, too.

The downside:

So far, the downside has mainly been the number of steps taken to produce HTML ouptut of a line-numberless file in an editor such as QD:

  1. Add back the line numbers
  2. Save the file
  3. LOAD it into the interpreter to tokenise it
  4. QSAVE it again
  5. Convert it to HTML
  6. Switch to the host OS and open in browser
  7. To continue editing: Switch back and
  8. remove line numbers

Since I couldnt be bothered, this meant that I would be referencing an out of date version of the code most of the time.

The solution (part 2):

SBhtm. This little program accomplishes a lot of work very simply and very quickly. If you add it to a hotkey, all you have to do is:

  1. Save your program, with or without line numbers, in QD
  2. Press the hotkey
  3. Open the resulting file in your browser (or Refresh if already open)
  4. Switch back and continue editing
(I should mention that on saving a file in QD, it puts the current path and filename into the Stufferbuffer)

When I need to, I can use two monitors attached to my computer. I then extend the Windoze desktop to cover both. QPC2 runs in full screen mode on one monitor, while the browser is open in the second. The few steps described above make the whole thing more or less seamless, allowing me to edit the program on one screen and have a clear, easy-to-read, navigable reference in another. Particularly handy for large or complex projects. It works well for me, so I thought it would be nice to share..The result might look something like the listing below (depending on the publisher of this article).

The Program

10 REMark $$chan=4
11 :
12 REMark + ---------------------------------------------------- +
13 REMark |<                   SBasic to Html                   >|
14 REMark + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
15 REMark | Converts SBasic programs to html using sb2htm        |
16 REMark | Adds line numbers to numberless code via intermed-   |
17 REMark | iary file in a temporary directory                   |
18 REMark |                                                      |
19 REMark | Add to FileInfo2, Hotkey, or use with EX:            |
20 REMark |                                                      |
21 REMark | er = FEW(<SBhtm>;"<program>_bas [;<command_line>]")  |
22 REMark |                                                      |
23 REMark | SBhtm passes the optional <command_line> to sb2htm   |
24 REMark | Use this to supply standard sb2htm cmdl parameters   |
25 REMark | (see sb2htm manual) except the -i command.           |
26 REMark |                                                      |
27 REMark | Version 0.02, pjw, 2oi5, SBASIC only!                |
28 REMark + ---------------------------------------------------- +
29 :
30 REMark       Config:
31 s2h$ = HOME_DIR$ & 'sb2htm_obj': REMark Html conversion program
32 out$ = 'dos3_html_':             REMark Default html output to my D:/temp/
33 tmp$ = 'ram1_sbhtmxxx': REMark Location and name of temp file
34 first% = 10: step% = 1: REMark First line and step size
35 :
36 REMark       Get input file name
37 REMark Get it either from cmdl or from Stufferbuffer
38 l% = LEN(CMD$)
39 IF l% = 0 THEN
40  fnm$ = HOT_GETSTUFF$: l% = LEN(fnm$)
41 ELSE
42  fnm$ = CMD$
43 END IF
44 IF l% < 9: Bye -12
45 :
46 REMark       Process command line(s)
47 com$= ''
48 REMark Additional command line?
49 s% = ';' INSTR fnm$
50 IF s% THEN
51  IF s% < l%: com$ = fnm$(s% + 1 TO l%)
52  l% = s% - 1: fnm$ = fnm$(1 TO l%)
53 END IF
54 :
55 REMark       Extract name from file name
56 ci = FOP_DIR(fnm$): IF ci < 0: Bye ci
57 dir$ = FNAME$(#ci): CLOSE#ci
58 ci = FOP_IN(fnm$): IF ci < 0: Bye ci
59 ld% = LEN(dir$)
60 nm$ = fnm$(6 + (ld% > 0) + ld% TO l% - 4)
61 :
62 REMark       Filter by extension
63 IF fnm$(l% - 2 TO l%) == 'sav' THEN
64  REMark _sav files pass straight through
65  bas = 0
66  CLOSE#ci
67 ELSE
68  REMark _bas file w/wo line number
69  IF fnm$(l% - 2 TO l%) == 'bas' THEN
70   bas = 1
71  ELSE
72   REMark Wrong file type
73   Bye -15
74  END IF
75  :
76  REMark Line numbers or not?
77  INPUT#ci; l$
78  IF NOT l$(1) INSTR '123456789' THEN
79   :
80   REMark     Process line numberless file
81   fnm$ = tmp$ & '_bas'
82   co = FOP_OVER(fnm$): IF co < 0: Bye co
83   bas = 2: i% = first%: lno$ = i%
84   BPUT#co; lno$, 32, l$, 10
85   :
86   FOR i% =  first% + step% TO 32767 STEP step%
87    IF EOF(#ci): EXIT i%
88    INPUT#ci; l$: lno$ = i%
89    BPUT#co; lno$, 32, l$, 10
90   END FOR i%
91   CLOSE#co
92  END IF
93  CLOSE#ci
94  :
95  REMark     Process non-sav files
96  REMark Use SBasic daughter to tokenise program
97  pip$ = 'pipe_p' & HEX$(JOBID, 32)
98  co = FOPEN(pip$ & 'o_2048'): IF co < 0: Bye co
99  :
100  REMark Slave will take instructions from here
101  cm$ = 'ci = fop_in(#0; "' & pip$ & 'o")'
102  :
103  REMark Start SBAS with our opening command
104  EXEP 'SBASIC'; cm$
105  :
106  REMark Tell it what we want
107  PRINT#co; 'load "' & fnm$ & '"'
108  PRINT#co; 'qsave_o "' & tmp$ & '"'
109  PRINT#co; 'beep 2,2: beep 2,2': REMark Signal success
110  PRINT#co; 'quit': REMark Job done! Get rid of slave
111  fnm$ = tmp$ & '_sav'
112 END IF
113 :
114 REMark      Create sb2htm command line
115 com$ = '-i!' & fnm$ & ' ' & com$ & ' -o' & out$ & nm$ & '.htm -t' & nm$
116 IF bas = 2: com$ = com$ & ' -noff'
117 :
118 REMark      Convert to tokenised file to html
119 Bye FEW(s2h$; com$)
121 :
122 REMark      Tidy and quit
123 DEFine PROCedure Bye(er)
124 IF er < 0: BEEP 3000,255
125 REMark Remove any temporary files
126 IF bas: DELETE fnm$
127 IF bas = 2: DELETE tmp$ & '_bas'
128 QUIT er
129 END DEFine Bye
130 :
  

What SBhtm does:

SBhtm takes the name of the file to process from its command line. If there is nothing on the command line, it takes the name from the stufferbuffer. If launching the program via EX, a command line should be supplied, containing at least the filespec of the source file to be processed. Any additional parameters you want to pass on to sb2htm must be embedded in the pseudo command line, thus:

	EW <SBhtm>; <filespec> & '; -odos5_'

This means: Execute the SBhtm program (compiled or not) with the file path and name given in <filespec>, ending on _bas or _sav (or .bas or .sav (but also tubas!)). The pseudo command line starts after the second semi colon. It passes through SBhtm to sb2htm to tell it you want the output sent to dos5_ instead of SBhtm's inbuilt default. Any error from (somewhere within) the process is returned in er on completion.

The program can be compiled with QLib and attached to a hotkey, thus:

	ERT HOT_RES1(<key>, <path>SBhtm_obj)

If used from a hotkey, SBhtm uses its own hard-wired defaults, except for the file name, which it gets from the stufferbuffer. There are many possibilities..

To continue what SBhtm does:

Once SBhtm has a file, it checks the extension and tries to open it. Three scenarios are catered for:

bas files
S*BASIC source files
bas files without line numbers
These need to be given line numbers before they can be tokenised. This is done via a temporary file.
bas files with line numbers
These only need to be tokenised via a temporary file before conversion to HTML
sav files
These have already been tokenised. They are passed straight through to sb2htm.

To tokenise the program, an instance of SBASIC is invoked via FEP/EXEP. It is instructed to take its commands from a pipe open to SBhtm. SBhtm tells the slave SBASIC to LOAD <filespec> or the temporary file, as the case may be. Syntax errors are flagged as MISTake. After the code is successfully parsed by the SBASIC slave, it is QSAVEd to a(nother) temporary file.

All that was wanted of the slave was its access to the SBASIC parser, so the slave's job is done and it is removed. sb2htm is invoked with the resultant temporary _sav file to do its stuff, and the result squirted into the default or specified directory.

If a temporary _bas file was created, it is now deleted, ditto for a temporary _sav file, although no original files are deleted.

The Ende

To calm those SuperBASIC bit-twiddlers who are no doubt horrified by my liberal use of blank lines and other puerile eye candy, at run-time SBASIC is not bothered by such trifles. It refines the tokenised program even further than SuperBASIC, which results, among many other advantages, in only effective code being encountered by the interpreter. All code that has no impact on the program's function is ruthlessly stripped away, any ambiguities resolved, and expressions and structures unravelled, leaving a much more efficient code, pretty close to that of QLib-compiled code.

There is more to say about this particular program in relation to sb2htm. It should become clear once you play around with it and sb2htm. I wrote this piece partly to plug sb2htm, which is receiving a quiet make-over back here at the lab, and will be released in due course once the final t's are crossed and i's dotted. Before trying SBhtm out, you should have correctly installed and tested sb2htm to get some idea of how it works.

The thing Id like you to take away from this, is the way SBASIC daughter jobs can be used. It doesnt take a lot of imagination to realise that instead of sending the file to sb2htm, it could be sent to Q_Liberator. So from editing your S*BASIC program in QD, within three steps you could have it compiled and, if desired, executing!

But that is left as an excercise for the fervent tinkerer.

Hint: To turn SBhtm into SBobj (no-frills, mind you) only a few minor changes need to be made, mainly to the command line com$ ;)

A copy of the source code and executable can be downloaded here