home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler1 / clean.asm < prev    next >
Assembly Source File  |  1985-08-28  |  11KB  |  420 lines

  1.     name    clean
  2.     page    55,132
  3.     title    'CLEAN --- Filter text file'
  4.  
  5. ;
  6. ; CLEAN --- a utility to filter text files.
  7. ; This program removes all control codes except
  8. ; for line feeds, carriage returns, and form
  9. ; feeds, strips off the high bit of all characters,
  10. ; and expands tabs.  Can be used to make a Wordstar
  11. ; file acceptable for other screen or line editors,
  12. ; and vice versa.
  13. ;
  14. ; version 1.1    10 Dec 83  Blocking/deblocking 
  15. ; version 1.0    25 Nov 83
  16. ;
  17. ; Copyright (c) 1983 by Ray Duncan
  18.  
  19. cr    equ    0dh        ;ASCII carriage return
  20. lf    equ    0ah        ;ASCII line feed
  21. ff    equ    0ch        ;ASCII form feed
  22. eof    equ    01ah        ;End of file marker
  23. tab    equ    09h        ;ASCII tab character
  24.  
  25. command    equ    80h        ;buffer for command tail
  26.  
  27. blksize    equ    1024        ;blocking/deblocking size
  28.  
  29.  
  30. cseg    segment    para public 'CODE'
  31.  
  32.     assume    cs:cseg,ds:data,es:data,ss:stack
  33.  
  34.  
  35. clean    proc    far        ;entry point from PC-DOS
  36.  
  37.     push    ds        ;save DS:0000 for final
  38.     xor    ax,ax        ;return to PC-DOS
  39.     push    ax
  40.     mov    ax,data        ;make our data segment
  41.     mov    es,ax        ;addressable via ES register
  42.     call    infile        ;get path and file spec.
  43.                 ;for input file
  44.     mov    ax,es        ;set DS=ES for remainder
  45.     mov    ds,ax        ;of program
  46.     jnc    clean1        ;jump, got acceptable name
  47.     mov    dx,offset msg4    ;missing or illegal filespec,
  48.     jmp    clean9        ;print error message and exit.
  49.  
  50. clean1:    call    outfile        ;set up output file name
  51.     call    open_input    ;now try to open input file
  52.     jnc    clean2        ;jump,opened input ok
  53.     mov    dx,offset msg1    ;open of input file failed,
  54.     jmp    clean9        ;print error msg and exit.
  55.  
  56. clean2:
  57.     call    open_output    ;try to open output file.
  58.     jnc    clean25        ;jump,opened ok
  59.     mov    dx,offset msg2    ;open of output file failed,
  60.     jmp    clean9        ;print error message and exit.
  61.  
  62. clean25:            ;set up buffers
  63.     call    init_buffs
  64.     call    sign_on        ;print ident and file names
  65.  
  66.                 ;files successfully opened,        
  67. clean3:                ;now filter the file.  
  68.     call    get_char    ;read 1 character from input.
  69.     and    al,07fh        ;strip off the high bit
  70.     cmp    al,20h        ;is it a control code?
  71.     jae    clean4        ;no,write it to new file    
  72.                 ;yes it is control code,
  73.     cmp    al,eof        ;is it end of file marker?
  74.     je    clean6        ;yes,jump to close files.
  75.     cmp    al,tab        ;is it a tab command?
  76.     jz    clean5        ;yes,jump to special processing.
  77.     cmp    al,cr        ;if control code other than
  78.     je    clean35        ;tab or end-of-file mark, throw 
  79.     cmp    al,ff        ;it away unless it is a 
  80.     je    clean35        ;form feed, carriage return,
  81.     cmp    al,lf        ;or line feed.
  82.     jne    clean3        
  83. clean35:            ;If it is one of those three,
  84.     mov    column,0    ;incidentally initialize
  85.     jmp    clean45        ;column count for tab processor.
  86.  
  87. clean4:                ;count alphanumeric chars. sent.
  88.     inc    column
  89.  
  90. clean45:            ;write this character to 
  91.     call    put_char    ;output file,
  92.     jnc    clean3        ;if CY not set, write was
  93.                 ;ok so go get next char.
  94. clean47:
  95.     call    close_input    ;if CY set, disk is full
  96.     call    close_output    ;so close files and exit
  97.     mov    dx,offset msg5  ;with error message.
  98.     jmp    clean9
  99.  
  100. clean5:                ;process tab character
  101.     mov    ax,column    ;let DX:AX=column count
  102.     cwd
  103.     mov    cx,8        ;divide it by eight...
  104.     idiv    cx
  105.     sub    cx,dx        ;remainder is in DX.
  106.     add    column,cx    ;update column pointer.
  107. clean55:            ;8 minus the remainder 
  108.     push    cx        ;gives us the number of
  109.     mov    al,20h        ;spaces to send out to
  110.     call    put_char    ;move to the next tab position
  111.     pop    cx        ;restore space count
  112.     jc    clean47        ;jump if disk is full
  113.     loop    clean55
  114.     jmp    short clean3    ;get next character 
  115.  
  116. clean6:                ;end of file detected,
  117.     call    put_char    ;write end-of-file marker,
  118.     jc    clean47        ;jump if disk was full
  119.     call    flush_buffs    ;write remaining data to disk
  120.     jc    clean47        ;if CY set,disk was full
  121.                 ;otherwise file was written ok    
  122.     call    close_input    ;close input and output 
  123.     call    close_output    ;files.
  124.     mov    dx,offset msg3    ;addr of success message,
  125.  
  126. clean9:                ;print message and return
  127.     mov    ah,9        ;control to PC-DOS
  128.     int    21h
  129.     ret
  130.  
  131. clean    endp
  132.  
  133.  
  134. infile    proc    near        ;process name of input file
  135.                 ;DS:SI <- addr command line    
  136.     mov    si,offset command
  137.                 ;ES:DI <- addr filespec buffer
  138.     mov    di,offset input_name
  139.     cld
  140.     lodsb            ;any command line present?
  141.     or    al,al        ;return error status if not.
  142.     jz    infile4
  143. infile1:                 ;scan over leading blanks
  144.     lodsb            ;to file name
  145.     cmp    al,cr        ;if we hit carriage return
  146.     jz    infile4     ;filename is missing.
  147.     cmp    al,20h        ;is this a blank?
  148.     jz    infile1        ;if so keep scanning.
  149.  
  150. infile2:             ;found first char of name,
  151.     stosb            ;move last char. to output
  152.                 ;file name buffer. 
  153.     lodsb            ;check next character, found
  154.     cmp    al,cr        ;carriage return yet?      
  155.     je    infile3        ;yes,exit with success code
  156.     cmp    al,20h        ;is this a blank?
  157.     jne     infile2        ;if not keep moving chars.
  158.  
  159. infile3:             ;exit with carry =0
  160.     clc            ;for success flag
  161.     ret
  162.  
  163. infile4:             ;exit with carry =1
  164.     stc            ;for error flag
  165.     ret
  166. infile  endp 
  167.  
  168. outfile    proc    near        ;set up path and file
  169.     cld            ;name for output file.
  170.     mov    cx,64        ;length to move
  171.     mov    si,offset input_name  ;source addr
  172.     mov    di,offset output_name ;dest addr
  173.     rep movsb        ;transfer the string
  174.     mov    di,offset output_name
  175. outfile1:            ;scan string looking for
  176.     mov    al,[di]     ;"." marking start of extension
  177.     or    al,al        ;or zero byte marking name end.
  178.     jz    outfile2    ;if either is found,jump.
  179.     cmp    al,'.'
  180.     je    outfile2    ;bump string pointer, loop
  181.     inc    di        ;if neither '.' or zero found.
  182.     jmp    outfile1    
  183. outfile2:            ;found zero or '.',force the
  184.                 ;extension of the output file    
  185.                 ;to '.CLN'
  186.     mov    si,offset outfile_ext
  187.     mov    cx,5
  188.     rep movsb
  189.     ret            ;back to caller
  190. outfile endp
  191.  
  192. open_input proc near        ;open input file
  193.                 ;DS:DX=addr filename
  194.     mov    dx,offset input_name
  195.     mov    al,0        ;AL=0 for read only
  196.     mov    ah,3dh        ;function 3dh=open
  197.     int     21h        ;handle returned in AX,
  198.     mov    input_handle,ax ;save it for later.
  199.     ret            ;CY is set if error
  200. open_input endp
  201.  
  202. open_output proc near        ;open output file
  203.                 ;DS:DX=addr filename
  204.     mov    dx,offset output_name
  205.     mov    al,1        ;AL=1 for write    only
  206.     mov    ah,3ch        ;function 3ch=MAKE or
  207.     int    21h        ;truncate existing file
  208.                 ;handle returned in AX
  209.     mov    output_handle,ax;save it for later.
  210.     ret            ;return CY=true if error
  211. open_output endp
  212.  
  213. close_input proc near        ;close input file
  214.     mov    bx,input_handle ;BX=handle
  215.     mov    ah,3eh
  216.     int    21h
  217.     ret
  218. close_input endp
  219.  
  220. close_output proc near        ;close output file
  221.     mov    bx,output_handle;BX=handle
  222.     mov    ah,3eh
  223.     int    21h
  224.     ret
  225. close_output endp
  226.  
  227. get_char proc     near        ;get one character from input buffer
  228.     mov    bx,input_ptr
  229.     cmp    bx,blksize
  230.     jne    get_char1
  231.     call    read_block
  232.     mov    bx,0
  233. get_char1:
  234.     mov    al,[input_buffer+bx]
  235.     inc    bx
  236.     mov    input_ptr,bx
  237.     ret
  238. get_char endp    
  239.  
  240. put_char proc    near        ;put one character into output buffer
  241.     mov    bx,output_ptr
  242.     mov    [output_buffer+bx],al
  243.     inc    bx
  244.     mov    output_ptr,bx
  245.     cmp    bx,blksize    ;buffer full yet?
  246.     jne    put_char1    ;no,jump
  247.     call    write_block    ;yes,write the block
  248.     ret            ;return CY as status code
  249. put_char1:
  250.     clc            ;return CY clear for OK status
  251.     ret
  252. put_char endp
  253.  
  254. read_block proc near
  255.     mov    bx,input_handle ;read first block of input
  256.     mov    cx,blksize
  257.     mov    dx,offset input_buffer
  258.     mov    ah,3fh
  259.     int    21h
  260.     jnc    read_block1    ;jump if no error status
  261.     mov    ax,0        ;simulate a zero length read if error
  262. read_block1:            
  263.     cmp    ax,blksize    ;was full buffer read in?
  264.     je    read_block2    ;yes,jump
  265.     mov    bx,ax        ;no, store End-of-File mark
  266.     mov    byte ptr [input_buffer+bx],eof
  267. read_block2:
  268.     xor    ax,ax        ;initialize input buffer pointer
  269.     mov    input_ptr,ax    
  270.     ret
  271. read_block endp
  272.  
  273. write_block proc near        ;write blocked output (blksize bytes)
  274.     mov    dx,offset output_buffer
  275.     mov    cx,blksize
  276.     mov    bx,output_handle
  277.     mov    ah,40h
  278.     int    21h
  279.     xor    bx,bx        ;initialize pointer to blocking buffer
  280.     mov    output_ptr,bx
  281.     cmp    ax,blksize    ;was correct length written?
  282.     jne    write_block1    ;no,disk must be full
  283.     clc            ;yes,return CY=0 indicating all OK
  284.     ret
  285. write_block1:            ;disk is full, return CY =1
  286.     stc            ;as error code
  287.     ret
  288. write_block endp
  289.  
  290. init_buffs proc near
  291.     call    read_block    ;read 1st block of input
  292.     xor    ax,ax        ;initialize pointer to output
  293.     mov    output_ptr,ax    ;output blocking buffer
  294.     ret
  295. init_buffs endp
  296.  
  297. flush_buffs proc near        ;write any data in output buffer to disk
  298.     mov    cx,output_ptr
  299.     or    cx,cx
  300.     jz    flush_buffs1    ;jump,buffer is empty
  301.     mov    bx,output_handle
  302.     mov    dx,offset output_buffer
  303.     mov    ah,40h
  304.     int    21h
  305.     cmp    ax,output_ptr    ;was write successful?
  306.     jnz    flush_buffs2    ;no,jump
  307. flush_buffs1: 
  308.     clc            ;yes,return CY=0 for
  309.     ret            ;success flag
  310. flush_buffs2:            ;disk was full so write failed,
  311.     stc            ;return CY=1 as error flag
  312.     ret
  313. flush_buffs endp
  314.  
  315. sign_on proc    near        ;print sign-on message
  316.     mov    dx,offset msg6    ;title...
  317.     mov    ah,9
  318.     int    21h
  319.     mov    dx,offset msg7    ;input file:
  320.     mov    ah,9
  321.     int    21h
  322.     mov    dx,offset input_name
  323.     call    pasciiz
  324.     mov    dx,offset msg8    ;output file:
  325.     mov    ah,9
  326.     int    21h
  327.     mov    dx,offset output_name
  328.     call    pasciiz
  329.     mov    dx,offset msg9
  330.     mov    ah,9
  331.     int    21h
  332.     ret
  333. sign_on    endp
  334.  
  335. pasciiz    proc    near        ;call DX=offset of ASCIIZ string
  336.     mov    bx,dx        ;which will be printed on standard output
  337. pasciiz1:
  338.     mov    dl,[bx]
  339.     or    dl,dl
  340.     jz    pasciiz9
  341.     cmp    dl,'A'
  342.     jb    pasciiz2
  343.     cmp    dl,'Z'
  344.     ja    pasciiz2
  345.     or    dl,20h
  346. pasciiz2:
  347.     mov    ah,2
  348.     int    21h
  349.     inc    bx
  350.     jmp    pasciiz1
  351. pasciiz9:
  352.     ret
  353. pasciiz endp
  354.  
  355. cseg    ends
  356.  
  357.  
  358. data    segment    para public 'DATA'
  359.  
  360. input_name    db    64 dup (0)    ;buffer for input filespec
  361. output_name    db    64 dup (0)    ;buffer for output filespec    
  362.  
  363. input_handle    dw    0        ;token returned by PCDOS
  364. output_handle    dw    0        ;token returned by PCDOS
  365.  
  366. input_ptr    dw    0        ;pointer to input blocking buffer
  367. output_ptr    dw    0        ;pointer to output blocking buffer
  368.  
  369. outfile_ext    db     '.CLN',0    ;extension for filtered file
  370.  
  371. column        dw    0        ;column count for tab processing
  372.  
  373. msg1        db    cr,lf
  374.         db    'Cannot find input file.'
  375.         db    cr,lf,'$'
  376.  
  377. msg2        db    cr,lf
  378.         db    'Failed to open output file.'
  379.         db    cr,lf,'$'
  380.  
  381. msg3        db    cr,lf
  382.         db    'File processing completed'
  383.         db    cr,lf,'$'
  384.  
  385. msg4        db    cr,lf
  386.         db    'Missing file name.'
  387.         db    cr,lf,'$'
  388.  
  389. msg5        db    cr,lf
  390.         db    'Disk is full.'
  391.         db    cr,lf,'$'
  392.  
  393. msg6        db    cr,lf
  394.         db    'Clean Word Processing File'
  395.         db    cr,lf
  396.         db    'Copyright (c) 1983 Laboratory Microsystems Inc.'
  397.         db    cr,lf,'$'
  398.  
  399. msg7        db    cr,lf,'Input file:   $'
  400.  
  401. msg8        db    cr,lf,'Output file:  $'
  402.  
  403. msg9        db    cr,lf,'$'
  404.  
  405.  
  406. input_buffer    db    blksize dup (?)    ;buffer for deblocking of data
  407.                     ;from input file
  408.  
  409. output_buffer    db    blksize dup (?)    ;buffer for blocking of data
  410.                     ;sent to output file
  411.  
  412. data     ends    
  413.  
  414.  
  415. stack    segment    para stack 'STACK'
  416.     db    64 dup (?)
  417. stack    ends
  418.  
  419.     end    clean
  420.