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 >
Internet Message Format  |  2009-12-11  |  10KB

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