Dal S*BASIC all’HTML

Nel numero della rivista QUANTA del maggio 2015 avevo pubblicato un programma chiamato SBldr. Questo prende un file S*BASIC e lo esegue (EXegue), come se fosse un job in linguaggio macchina. Niente di straordinario, sicuramente. Comunque l’X-factor del lavoro è che se il codice sorgente non contiene numeri di linea (e in tal caso non è EXeguibile), SBldr li aggiunge al volo, permettendo così l’EXecute del programma.

L’esempio qui sotto è un livello successivo. Uno dei punti di questa utilità di esempio è la dimostrazione di come si invoca un’istanza della Thing SBASIC (cosa che, in teoria, è fattibile da qualsiasi linguaggio di programmazione) utilizzandone le caratteristiche, in questo caso per tokenizzare un sorgente S*BASIC. La peculiarità di questo programma è la capacità di convertire un sorgente S*BASIC in HTML, tramite il mio programma sb2htm. In questo senso potrebbe essere molto interessante per gli utenti SMSQ/E (come me) che scrivono programmi S*BASIC tramite editor. Alcune delle tecniche impiegate potrebbero essere utili agli interessati al S*BASIC, ma molte di queste funzionano solo in SMSQ/E e SBASIC (anche se si può fare qualcosa di simile con Minerva).

Se la conversione S*BASIC in HTML non vi affascina, lasciatemi solo accennare al fatto che una piccola modifica del programma presentato qui sotto permette di compilare un programma S*BASIC direttamente da QD (e probabilmente da altri editor) o da qualsiasi file manager compatibile FileInfo2, o dalla linea di comando, senza dover fare il QSAVE del sorgente né tantomeno aggiungere numeri di linea. In questo modo si potrebbe accelerare di molto lo sviluppo e il debug di programmi.

Prima di tutto spieghiamo il programma.

Il problema è questo:

ancorché gli schermi diventino sempre più grandi, i fount del QL non sono cambiati; anzi, sembrano diventare sempre più piccoli e più difficili da leggere! Editor di testo come QD sono migliori di EDIT per la scrittura di programmi appena appena complessi, ma anche loro hanno solo combinazioni di nero su grigio, e molti di essi non hanno idea di cosa viene scritto.

La soluzione (1a parte):

una soluzione parziale è il mio programma sb2htm, disponibile presso il sito di Dilwyn, sotto Software Download/HTML utilities. Questo prende un programma S*BASIC tokenizzato e lo converte in HTML navigabile e con evidenziazione della sintassi. I colori possono esser cambiati a piacere, e il browser è in grado di mostrare caratteri delle dimensioni che volete. (Navigabile significa che è possibile seguire il flusso del programma grazie al fatto che le definizioni di PROCedure e FuNzioni sono linkate ed è possibile seguirle. Cliccando sul tasto Indietro del browser si può tornare al punto di chiamata). Il box di ricerca locale del browser, e le funzioni di ricerca del SO sottostante, possono anch’esse rivelarsi molto utili.

Problemi:

Finora l’aspetto negativo è soprattutto il numero di passi da fare per produrre un output HTML di un file senza numeri di linea in un editor come QD:

– Aggiungere i numeri di linea
– Salvare il file
– Caricarlo nell’interprete e tokenizzarlo
– QSAVE del file
– Convertirlo in Html
– Passare al SO ospite e leggerlo via browser
– Per continuare a scrivere, tornare al QL e rimuovere i numeri di linea

La soluzione (seconda parte):

SBhtm. Questo programma esegue molta parte del lavoro in maniera veloce e semplice. Assegnandolo a una hotkey, tutto quel che serve fare è:

– Salvare il programma, con o senza numeri di linea, in QD
– Premere la hotkey
– Aprire il file nel browser, o aggiornarlo se già aperto
– Rientrare nel QL e proseguire

(Devo forse ricordare che salvando il file in QD, questi ne mette percorso e nome file nello Stufferbuffer)

In caso di necessità io posso usare due monitor attaccati al computer. A quel punto estendo il desktop di Windows per usarli entrambi. QPC2 gira a pieno schermo su un monitor, e il browser è aperto sull’altro. I passi descritti sopra rendono l’intera procedura più o meno immediata, permettendomi di modificare il programma su uno schermo e avere un riferimento chiaro e facile da leggere e navigare sull’altro. Il risultato potrebbe sembrare simile al listato qui sotto (dipende da chi pubblica l’articolo).

Il programma

REMark $$chan=4
:
REMark + ---------------------------------------------------- +
REMark |<                   SBASIC to Html                   >|
REMark + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
REMark | Converts SBASIC programs to HTML using sb2htm        |
REMark | Adds line numbers to numberless code via intermed-   |
REMark | iary file in a temporary directory                   |
REMark |                                                      |
REMark | Add to FileInfo2 or use with EX:                     |
REMark |                                                      |
REMark | er = FEW(<SBhtm>;"<program>_bas [;<command_line>]")  |
REMark |                                                      |
REMark | SBhtm passes the optional <command_line> to sb2htm   |
REMark | Use this to supply standard sb2htm cmdl parameters   |
REMark | (see sb2htm manual) except the -i command.           |
REMark |                                                      |
REMark | Version 1.01, pjw, 2oi5, SBASIC only!                |
REMark + ---------------------------------------------------- +
:
REMark       Config:
s2h$ = 'win2_util_s2h_sb2htm_obj': REMark Html conversion program
out$ = 'dos3_': REMark Default HTML output to My D:/temp/
tmp$ = 'ram1_sbhtmxxx': REMark Location and name of temp file
first% = 10: step% = 1: REMark First line and step size
:
REMark       Get input file name
REMark Get it either from cmdl or from Stufferbuffer
l% = LEN(CMD$)
IF l% = 0 THEN
 fnm$ = HOT_GETSTUFF$: l% = LEN(fnm$)
ELSE
 fnm$ = CMD$
END IF
IF l% < 9: Bye -12
:
REMark       Process command line(s)
com$= ''
REMark Embedded command line?
s% = ';' INSTR fnm$
IF s% THEN
 IF s% < l%: com$ = fnm$(s% + 1 TO l%)
 l% = s% - 1: fnm$ = fnm$(1 TO l%)
END IF
:
REMark       Extract name from file name
ci = FOP_DIR(fnm$): IF ci < 0: Bye ci
dir$ = FNAME$(#ci): CLOSE#ci
ci = FOP_IN(fnm$): IF ci < 0: Bye ci
nm$ = fnm$(7 + LEN(dir$) TO LEN(fnm$) - 4)
:
REMark       Filter by extension
IF fnm$(l% - 2 TO l%) == 'sav' THEN
 REMark _sav files pass straight through
 bas = 0
 CLOSE#ci
ELSE
 REMark _bas file w/wo line number
 IF fnm$(l% - 2 TO l%) == 'bas' THEN
  bas = 1
 ELSE
  REMark Wrong file type
  Bye -12
 END IF
 :
 REMark Line numbers or not?
 INPUT#ci; l$
 IF NOT l$(1) INSTR '123456789' THEN
  :
  REMark     Process line numberless file
  fnm$ = tmp$ & '_bas'
  co = FOP_OVER(fnm$): IF co < 0: Bye co
  bas = 2: i% = first%: lno$ = i%
  BPUT#co; lno$, 32, l$, 10
  :
  FOR i% =  first% + step% TO 32767 STEP step%
   IF EOF(#ci): EXIT i%
   INPUT#ci; l$: lno$ = i%
   BPUT#co; lno$, 32, l$, 10
  END FOR i%
  CLOSE#co
 END IF
 CLOSE#ci
 :
 REMark     Process non-sav files
 REMark Use SBASIC slave to tokenise program
 pip$ = 'pipe_p' & HEX$(JOBID,32)
 co = FOPEN(pip$ & 'o_2048'): IF co < 0: Bye co
 :
 REMark Slave will take instructions from here
 cm$ = 'ci = fop_in(#0; "' & pip$ & 'o")'
 :
 REMark Start SBASIC with our opening command
 EXEP 'SBASIC'; cm$
 :
 REMark Tell it what we want
 PRINT#co; 'load "' & fnm$ & '"'
 PRINT#co; 'qsave_o "' & tmp$ & '"'
 PRINT#co; 'beep 2,2: beep 2,2': REMark Signal success
 PRINT#co; 'quit': REMark Job done! Get rid of slave
 fnm$ = tmp$ & '_sav'
END IF
:
REMark      Create sb2htm command line
com$ = '-i!' & fnm$ &' '& com$ & ' -o' & out$ & nm$ & '.htm -t' & nm$
IF bas = 2: com$ = com$ & ' -noff'
:
REMark      Convert tokenised file to HTML
Bye FEW(s2h$; com$)
:
REMark      Tidy and quit
DEFine PROCedure Bye(er)
IF er < 0: BEEP 3000,255
REMark Remove any temporary files
IF bas: DELETE fnm$
IF bas = 2: DELETE tmp$ & '_bas'
QUIT er
END DEFine Bye

Cosa fa SBhtm:

SBhtm prende il nome del file da elaborare dalla riga di comando. Se non è presente un nome di file, prende il nome dallo Stufferbuffer. Lanciando il programma tramite EX, si dovrebbe dare una riga di comando che contenga almeno il filespec del file sorgente da elaborare. Altri parametri che si vogliano passare a sb2htm devono essere scritti nella pseudo linea di comando, per cui

EW <SBhtm>; <filespec> & ‘; -odos5_’

significa: Esegui il programma SBhtm (compilato o meno) con il percorso e il nome di file dato in <filespec>, che termina per _bas o _sav (o .bas or .sav (ma anche tubas!)). La pseudo linea di comando inizia dopo il secondo punto e virgola. Questa passa attraverso SBhtm per andare a sb2htm e dirgli che volete che l’uscita del programma sia ridiretta a dos5_ invece che nella directory predefinita di SBhtm. Tutti gli errori provenienti dal processo vengono riportati in er al completamento.

Il programma può quindi essere compilato con QLib e assegnato a una hotkey:

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

Usato da una hotkey, SBhtm usa valori predefiniti eccezion fatta per il nome file, che recupera dallo Stufferbuffer. Esistono parecchie possibilità…

Per elencare le altre cose che fa SBhtm:

Dato un file, SBhtm ne controlla l’estensione e cerca di aprirlo. Sono possibili tre scenari:

file bas
sorgenti S*BASIC

file bas senza numeri di linea
Viene creato un file temporaneo per dare al file i numeri di linea prima della tokenizzazione.
file bas con numeri di linea
Tramite un file temporaneo si crea la tokenizzazione prima della conversione in HTML

file sav
Sono già tokenizzati e vengono passati direttamente a sb2htm.

Per la tokenizzazione viene evocata un’istanza di SBASIC tramite FEP/EXEP, istruito a prendere i suoi comandi da una pipe aperta verso SBhtm. SBhtm dice al SBASIC slave di caricare <filespec> o il file temporaneo, a seconda del caso. Gli errori di sintassi vengono marcati come MISTake. Dopo che SBASIC ha analizzato il codice, il file viene salvato con QSAVE in un altro file temporaneo.

Lo slave SBASIC non è più necessario e può essere rimosso. sb2htm viene invocato con il file _sav temporaneo per fare le proprie elaborazioni, e il risultato viene salvato nella directory specificata o in quella predefinita.

Se è stato creato un file _bas temporaneo, questo viene cancellato esattamente come per un eventuale file _sav temporaneo: nessuno dei file originali viene cancellato.

Finale

Per calmare i fanatici del SuperBASIC sicuramente orripilati dal mio uso liberale di linee vuote e di altre raffinatezze puerili, chiarirò che a runtime il SBASIC non viene influenzato da queste cose. Esso raffina il programma tokenizzato anche di più del SuperBASIC, terminando – a parte altri vantaggi – con l’interprete che legge solo codice effettivo. Tutto il codice che non ha impatto sul funzionamento del programma viene brutalmente cancellato, le ambiguità vengono risolte, le espressioni e le strutture sviluppate, producendo un codice molto più efficiente e vicino a quello compilato con QLib.

C’è ancora altro da dire su questo programma in relazione a sb2htm. Dovrebbe risultare chiaro una volta che si gioca un po’ con entrambi. Io ho scritto questo pezzo in parte per riprendere sb2htm, che sta ricevendo qui in laboratorio una silenziosa revisione, e verrà rilasciato al momento opportuno dopo aver messo i puntini sulle i e le lineette sulle t. Brima di provare SBhtm, dovreste aver installato e testato sb2htm per avere un’idea di come funziona.

Quello che mi piacerebbe che sviluppaste è il modo in cui si possono usare i job figli SBASIC. Non ci vuole molto a capire che, invece che a sb2htm, il file potrebbe essere mandato a Q_Liberator. In tal modo, dall’editing del programma S*BASIC in QD, in tre passi sarebbe possibile compilarlo e anche eseguirlo!

Ma questo lo lasciamo come esercizio per il fervente pensatore…
Suggerimento: per trasformare SBhtm in SBobj (niente trucchi) sono necessari pochi cambiamenti, soprattutto alla linea di comando com$ 😉

Per J. Witte