From: "Salle Arobase" 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: Reply-To: "Salle Arobase" 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