home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
DRI-archive
/
roche
/
FILTER.TXT
< prev
next >
Wrap
Internet Message Format
|
2009-12-11
|
10KB
From: "Salle Arobase" <salle.arob...@ville-rochefort.fr>
Newsgroups: comp.os.cpm
Subject: General-Purpose Filter Program in BASIC
Date: Tue, 5 Aug 2003 14:20:59 +0200
Organization: Ville de Rochefort
Lines: 241
Message-ID: <bgo70q$avg$1@news-reader5.wanadoo.fr>
Reply-To: "Salle Arobase" <salle.arob...@ville-rochefort.fr>
NNTP-Posting-Host: apoitiers-106-2-3-3.w81-248.abo.wanadoo.fr
X-Trace: news-reader5.wanadoo.fr 1060085594 11248 81.248.43.3 (5 Aug 2003 12:13:14 GMT)
X-Complaints-To: abuse@wanadoo.fr
NNTP-Posting-Date: 5 Aug 2003 12:13:14 GMT
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
FILTER.TXT by Emmanuel ROCHE
----------
This week, on the comp.os.cpm Newsgroup, there were talks about
the need of a WordStar 4.0 to HTML converter program.
I remarked that I had not yet written a general purpose filter
program. In the case of tabulations, you only look for 09h
bytes, then replace them with the appropriate number of spaces.
You couldn't care less for the remaining 255 values.
Worse, I had not the slightest idea about the internals of WS4
files. That meant that I would be obliged to prepare a
subroutine for all the 256 values of a byte...
Since no macro-assembler (and SEQIO.LIB) is available under
CP/M-86 Plus, the choice of language to use was obvious: BASIC,
so the program would be portable to CP/M Plus, CP/M-86 Plus, and
MeSsy-DOS.
Back home, I started by creating a BASIC program creating a file
holding the 256 values of a byte (until then, I had always
entered manually those values with SID before saving a file).
Here it is:
10 REM MAKEASCF.BAS by Emmanuel ROCHE
20 :
30 PRINT
40 INPUT "Make ASCII File: Enter ASC File Name: " ; file$
50 PRINT
60 file$ = file$ + ".ASC"
70 OPEN "O", #1, file$
80 FOR i = 0 TO &HFF
90 PRINT #1, CHR$ (i) ;
100 NEXT i
110 END
Ok
(At first sight, it seems to be less than the 512 keystrokes
needed when doing it manually.)
Now that we have such a program at our disposal, we ask it to
make a file, say "ASCII", holding all the values of an 8-bit
byte. (Note that the program mentions ASCII, which is a 7-bit
standard, but that's life.)
run"makeascf
Make ASCII File: Enter ASC File Name: ? ascii
Ok
We now have a file on our disk containing all the 256 values of
a byte. I was wondering how the converter program could
demonstrate that it was managing correctly all those 256 values?
After a while, I decided to let it display on screen all those
byte values in hex, surrounded by "square brackets" ("[" and
"]"). (This way, only a PRINT statement was enough, and the
output was 16*4 on each line, so 64 columns.) Examine the
following display:
run"filter
FILTER: Enter ASC File Name: ? ascii
[00][01][02][03][04][05][06][07][08][09][0A][0B][0C][0D][0E][0F]
[10][11][12][13][14][15][16][17][18][19][1A][1B][1C][1D][1E][1F]
[20][21][22][23][24][25][26][27][28][29][2A][2B][2C][2D][2E][2F]
[30][31][32][33][34][35][36][37][38][39][3A][3B][3C][3D][3E][3F]
[40][41][42][43][44][45][46][47][48][49][4A][4B][4C][4D][4E][4F]
[50][51][52][53][54][55][56][57][58][59][5A][5B][5C][5D][5E][5F]
[60][61][62][63][64][65][66][67][68][69][6A][6B][6C][6D][6E][6F]
[70][71][72][73][74][75][76][77][78][79][7A][7B][7C][7D][7E][7F]
[80][81][82][83][84][85][86][87][88][89][8A][8B][8C][8D][8E][8F]
[90][91][92][93][94][95][96][97][98][99][9A][9B][9C][9D][9E][9F]
[A0][A1][A2][A3][A4][A5][A9][A7][A8][A9][AA][AB][AC][AD][AE][AF]
[B0][B1][B2][B3][B4][B5][B6][B7][B8][B9][BA][BB][BC][BD][BE][BF]
[C0][C1][C2][C3][C4][C5][C6][C7][C8][C9][CA][CB][CC][CD][CE][CF]
[D0][D1][D2][D3][D4][D5][D6][D7][D8][D9][DA][DB][DC][DD][DE][DF]
[E0][E1][E2][E3][E4][E5][E6][E7][E8][E9][EA][EB][EC][ED][EE][EF]
[F0][F1][F2][F3][F4][F5][F6][F7][F8][F9][FA][FB][FC][FD][FE][FF]
Ok
Well... As far as I can see, the program seems to be able to
deal with all 256 cases... Let us now see a little bit of this
program.
list
10 REM FILTER.BAS by Emmanuel ROCHE
20 :
30 PRINT
40 INPUT "FILTER: Enter ASC File Name: " ; file$
50 PRINT
60 file$ = file$ + ".ASC"
70 nofile$ = FIND$ (file$)
80 IF nofile$ = "" THEN PRINT CHR$ (7) "File not found." : PRINT : END
90 OPEN "R", 1, file$, 1
100 FIELD #1, 1 AS byte$
110 :
120 GET #1
130 IF EOF (1) THEN PRINT : END
140 byte = ASC (byte$)
150 hini = INT (byte / 16)
160 loni = byte - hini * 16
170 GOSUB 200
180 GOTO 120 ' Main Loop
190 :
200 ' High Nibble: 0 1 2 3 4 5 6 7
210 ON hini+1 GOSUB 290, 370, 450, 530, 610, 690, 770, 850
220 IF hini > 7 THEN hini2 = hini - 7 ELSE RETURN
230 ' High Nibble: 8 9 A B C D E F
240 ON hini2 GOSUB 930, 1010, 1090, 1170, 1250, 1330, 1410, 1490
250 RETURN
260 '
270 ' High Nibble: 0
280 ' Low Nibble: 0 1 2 3 4 5 6 7
290 ON loni+1 GOSUB 1560, 1600, 1640, 1680, 1720, 1760, 1800, 1840
300 IF loni > 7 THEN loni2 = loni - 7 ELSE RETURN
310 ' Low Nibble: 8 9 A B C D E F
320 ON loni2 GOSUB 1880, 1920, 1960, 2000, 2040, 2080, 2120, 2160
330 RETURN
340 '
As, I hope, can be seen, the beginning of the program deals with
the filename, then gets a byte from the file. This byte is
divided into its high and low nibbles. Then, 16 subroutines of
16 ON GOSUB branches to the appropriate 256 subroutines. Of
course, the program needs to be able to deal with all the 16
possible nibble values. They are omitted for conciceness.
1470 ' High Nibble: F
1480 ' Low Nibble: 0 1 2 3 4 5 6 7
1490 ON loni+1 GOSUB 11310, 11350, 11390, 11430, 11470, 11510, 11550, 11590
1500 IF loni > 7 THEN loni2 = loni - 7 ELSE RETURN
1510 ' Low Nibble: 8 9 A B C D E F
1520 ON loni2 GOSUB 11630, 11670, 11710, 11750, 11790, 11830, 11870, 11910
1530 RETURN
Now, the variant part of the program, which will be changed
according to the characteristics of the input file processed. As
explained previously, I chose to only display the particular hex
value of a given byte between square brackets, using a PRINT
statement, each subroutine being started by a comment reminding
of its hex value, and ending, of course, with a RETURN.
1540 '
1550 ' 00
1560 PRINT "[00]" ;
1570 RETURN
11890 '
11900 ' FF
11910 PRINT "[FF]" ;
11920 PRINT
11930 RETURN
Ok
Since this list of 256 subroutines was so long, I decided to
write a BASIC program to generate them (programmers are lazy).
You just redirect the screen output under CP/M-86 Plus, renum
all the lines, and merge with the main BASIC program.
(Curiously, I had not thought of making a program to generate
the 16 nibble subroutines. In fact, I first started by
displaying the hex values of the first 16 bytes, then added each
high nibble... (This way, I could detect a bug as soon as it
appeared. I am not a believer in writing big programs first,
then debugging them. I prefer "bottom-up".) I had a problem with
the border of nibble 7, as I wanted the program to fit inside 64
columns (that, for some unknown reasons, several readers of the
comp.os.cpm Newsgroup insist be used... Apparently, I was the
only one who learned to type on a 80-columns typewriter.), with
an above reminder of the CASE number. After a while, I ended
with the program structure shown above, but done manually, since
I was testing at the same time that the program was generating
the correct values on screen. So, no program generating this
section... Wouldn't it be a nice little programming exercice for
you, tonight?)
10 REM FILTMAKE.BAS by Emmanuel ROCHE
20 :
30 PRINT
40 INPUT "Make Filter File: Enter ASC File Name: " ; file$
50 PRINT
60 file$ = file$ + ".ASC"
70 OPEN "O", #1, file$
80 ln = 1000
90 FOR i = 0 TO &HFF
100 PRINT #1, USING "####" ; ln + 1 ;
110 PRINT #1 " '"
120 hexa$ = RIGHT$ ("0" + HEX$ (i), 2)
130 PRINT #1, USING "####" ; ln + 3 ;
140 PRINT #1 " ' " hexa$
150 PRINT #1, USING "####" ; ln + 5 ;
160 PRINT #1 " PRINT " CHR$ (34) "[" hexa$ "]" CHR$ (34) " ;"
170 IF i MOD 16 = 15 THEN PRINT #1, USING "####" ; ln + 7 ;
180 IF i MOD 16 = 15 THEN PRINT #1 " PRINT"
190 PRINT #1, USING "####" ; ln + 9 ;
200 PRINT #1 " RETURN"
210 ln = ln + 10
220 NEXT i
230 END
Ok
As we saw above, the program demonstrates that it works
correctly by displaying on the screen the output of its 256
subroutines. Of course, in a real converter, the program will
have to output the value into a file, not on the screen. The
change to achieve this is very simple: change above line 160 as
follows:
160 PRINT #1 " PRINT #2, byte$ ;"
Redirect the screen output into a file, let have BASIC renumber
it (starting at 1540), then merge to an ASCII version of the
BASIC program. Don't forget to add one line dealing with the
output (#2, filetype HTM) file. Finally, remove all the 16
PRINT statements which were ending the lines (at each xF value).
Renumber one last time, and you now have a converter... that
convert nothing, despite using 256 subroutines to output the 256
values of a byte! (I checked with a COMPARE program that the
input WS4 file was exactly the same as the output HTM file.)
Now that we have a general purpose converter program at your
disposal, all we need to do is understand how the internals of
WS4 files work, then replace the appropriate subroutines by the
required code, to convert those WS4 files into HTML files.
system
That's all, folks!
Yours Sincerely,
"French Luser
EOF