home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1986 / 19 / change.asm next >
Assembly Source File  |  1987-12-13  |  13KB  |  251 lines

  1. ;            Change.asm
  2. ; A find and replace utility for text files.
  3. ; Format:  CHANGE filespec findstring replacestring
  4. ; The strings have to be in quotes or decimal ASCII
  5. ; Multiple codes in a string are separated by commas
  6. ; e.g. CHANGE MYFILE 27,"-1" "*"
  7.  
  8.  
  9. CODE SEGMENT                           ;*************************
  10. ASSUME CS:CODE,DS:CODE                 ;*                       *
  11. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *
  12.                                        ;*                       *
  13. START:         JMP    BEGINNING        ;*************************
  14.  
  15.  
  16. ;              DATA AREA
  17. ;              ---------
  18. FILE_START     DW  ?
  19. FIND_CNT       DW  0
  20. REPLACE_CNT    DW  0
  21. CHANGE_FLAG    DB  0
  22.  
  23. SYNTAX_MSG     DB  'Syntax error$'
  24. NOT_FOUND$     DB  'File not found$'
  25. TOO_BIG$       DB  'File too big$'
  26. CHANGE$        DB  'Not Changed$'
  27.                DB  "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
  28.            DB  "Programmed by Michael J. Mefford",1Ah
  29.  
  30. ;              CODE AREA
  31. ;              ---------
  32.  
  33. ;-------------------------------------------------------;
  34. ; First we will parse the filename and the two strings. ;
  35. ;-------------------------------------------------------;
  36.  
  37. BEGINNING:     MOV    SI,80H                 ;Point to parameters.
  38.                MOV    DX,OFFSET SYNTAX_MSG   ;Point to syntax message.
  39.                CLD                           ;Move in forward direction.
  40.                CALL   SPACE                  ;Parse leading spaces.
  41.                MOV    FILE_START,SI          ;We now point to filename.
  42.  
  43. FILE_BYTE:     CMP    BYTE PTR [SI],13       ;Is it a carriage return?
  44.                JZ     EXIT                   ;If yes, exit with syntax error.
  45.                CMP    BYTE PTR [SI],32       ;Is it a space?
  46.                JZ     ASCIIZ                 ;If yes, end of filename
  47.                INC    SI                     ; else, point to next byte
  48.                JMP    SHORT FILE_BYTE        ; and check it.
  49. ASCIIZ:        MOV    BYTE PTR [SI],0        ;Make filename into ASCIIZ.
  50.  
  51.                CALL   SPACE                  ;Parse the spaces.
  52.                XOR    CX,CX                  ;Set string counter to zero.
  53.                MOV    DI,OFFSET FIND$        ;Point to find string storage.
  54. FIND_BYTE:     CALL   STRING                 ;Get string.
  55.                CMP    BYTE PTR [SI],32       ;Are we now pointing to space?
  56.                JZ     REPLACE                ;If yes, done here.
  57.                CMP    BYTE PTR [SI],13       ;Is it a carriage return?
  58.                JZ     EXIT                   ;If yes, it's a syntax error
  59.                INC    SI                     ; else point to next byte
  60.                JMP    SHORT FIND_BYTE        ; and get rest of string.
  61.  
  62. REPLACE:       CALL   SPACE                  ;Parse spaces.
  63.                MOV    FIND_CNT,CX            ;Save count of find string bytes.
  64.                XOR    CX,CX                  ;Reset counter to zero.
  65.                MOV    DI,OFFSET REPLACE$     ;Point to replace string storage.
  66. REPLACE_BYTE:  CALL   STRING                 ;Get string.
  67.                CMP    BYTE PTR [SI],32       ;Are we now pointing to space?
  68.                JZ     OPEN_FILE              ;If yes, we are done here.
  69.                CMP    BYTE PTR [SI],13       ;Are we now pointing to CR?
  70.                JZ     OPEN_FILE              ;If yes, we are done here
  71.                INC    SI                     ; else, point to next byte
  72.                JMP    SHORT REPLACE_BYTE     ; and get rest of string.
  73.  
  74. ;------------------------------------------;
  75. ; The exit is placed in the middle of code ;
  76. ; so it can be reached by short jumps.     ;
  77. ;------------------------------------------;
  78.  
  79. EXIT:          MOV    AH,9                   ;Display message
  80.                INT    21H
  81.                INT    20H                    ; and terminate.
  82.  
  83. ;-----------------------------------------------------------;
  84. ; We are ready to open the file and read it into the buffer ;
  85. ; offset 20,000 bytes from the start. We will then move the ;
  86. ; bytes to the start of buffer, trading any match of find   ;
  87. ; string with replacement string.                           ;
  88. ;-----------------------------------------------------------;
  89.  
  90. OPEN_FILE:     MOV    REPLACE_CNT,CX         ;Save count of replace bytes.
  91.                MOV    DX,FILE_START          ;Point to ASCIIZ filename
  92.                MOV    AX,3D00H               ; and open file for reading.
  93.                INT    21H
  94.                MOV    DX,OFFSET NOT_FOUND$   ;If not found
  95.                JC     EXIT                   ; display message and exit.
  96.  
  97. READ_FILE:     MOV    BX,AX                    ;File handle into BX
  98.                MOV    DX,OFFSET BUFFER+20000   ;Point buffer
  99.                MOV    CX,40000                 ;Attempt to read 40,000 bytes.
  100.                MOV    AH,3FH
  101.                INT    21H
  102.                MOV    DX,OFFSET TOO_BIG$     ;Point to error message.
  103.                CMP    AX,40000               ;Did we read 40,000 bytes?
  104.                JZ     EXIT                   ;If yes, file too big; exit
  105.                PUSH   AX                     ; else, save count of bytes
  106.                MOV    AH,3EH                 ; and close the file.
  107.                INT    21H
  108.  
  109. COMPARE:       POP    DX                     ;Retrieve byte count.
  110.                MOV    AX,FIND_CNT            ;Retrieve find string length.
  111.                CMP    DX,AX                  ;Is find string bigger than file?
  112.                JGE    OK                     ;If no, it's OK
  113.                MOV    DX,OFFSET CHANGE$      ; else exit with no change.
  114.                JMP    SHORT EXIT
  115.  
  116. OK:            MOV    BX,OFFSET BUFFER+20000 ;Point to start of file
  117.                MOV    AX,OFFSET BUFFER       ; and start of storage.
  118. NEXT_COMP:     MOV    SI,OFFSET FIND$        ; point to find string
  119.                MOV    DI,BX                  ; point to match attempt
  120.                MOV    CX,FIND_CNT            ; get find string length
  121.                REP    CMPSB                  ; and compare.
  122.                MOV    DI,AX                  ;Point storage area.
  123.                JZ     MATCH                  ;If match, store replace string
  124.                MOV    SI,BX                  ; else store
  125.                MOVSB                         ; old byte
  126.                INC    AX                     ; point to next storage spot
  127.                INC    BX                     ; start of next byte to compare
  128.                DEC    DX                     ; decrement file byte count
  129.                JMP    SHORT LOOP             ; and check if end of file.
  130.  
  131. MATCH:         OR     CHANGE_FLAG,1          ;Indicate that we found a match.
  132.                MOV    SI,OFFSET REPLACE$     ;Point to replacement string.
  133.                MOV    CX,REPLACE_CNT         ;Get length.
  134.                ADD    AX,CX                  ; point to next storage spot
  135.                ADD    BX,FIND_CNT            ; start of next byte to compare
  136.                SUB    DX,FIND_CNT            ; subtract from file byte count
  137.                REP    MOVSB                  ; and store the string.
  138.  
  139. LOOP:          CMP    DX,FIND_CNT            ;Is find string bigger than
  140.                JGE    NEXT_COMP              ; balance of file? If no, next
  141.                MOV    CX,DX                  ; compare else, transfer the
  142.                ADD    AX,CX                  ; balance of file to write
  143.                MOV    SI,BX                  ; storage area.
  144.                REP    MOVSB
  145.  
  146. ;-----------------------------------------;
  147. ; We are ready to write the file to disk. ;
  148. ;-----------------------------------------;
  149.  
  150. WRITE:         PUSH   AX                     ;Save length of new file.
  151.                MOV    DX,FILE_START          ; point to ASCIIZ filename.
  152.                XOR    CX,CX                  ; normal attribute
  153.                MOV    AH,3CH                 ; and create new file.
  154.                INT    21H
  155.                POP    CX                     ;Retrieve file length
  156.                SUB    CX,OFFSET BUFFER       ;It's in offset form; correct it.
  157.                MOV    BX,AX                  ;File handle into BX
  158.                MOV    DX,OFFSET BUFFER       ; point to storage buffer
  159.                MOV    AH,40H                 ; and write the file.
  160.                INT    21H
  161.                MOV    AH,3EH                 ;Close file.
  162.                INT    21H
  163.                MOV    DX,OFFSET CHANGE$      ;Point to "Not Changed"
  164.                CMP    CHANGE_FLAG,0          ;Did we find a match?
  165.                JZ     NOT_CHANGED            ;If no, display as is
  166.                ADD    DX,4                   ; else bump pointer to "Changed"
  167. NOT_CHANGED:   JMP    EXIT                   ; and we are done.
  168.  
  169. ;---------------------------------------------;
  170. ; This subroutine will get the quoted string  ;
  171. ; or convert the decimal ASCII to hexadecimal ;
  172. ; and store in the appropriate storage area.  ;
  173. ;---------------------------------------------;
  174.  
  175. STRING:        CMP    BYTE PTR [SI],'"'      ;Is it quotes?
  176.                JNZ    NUMBER                 ;If no, must be number
  177.                INC    SI                     ; else, point to first string
  178. NEXT_STRING:   LODSB                         ; byte and retrieve.
  179.                CMP    AL,13                  ;Is it carriage return?
  180.                JZ     ERROR                  ;If yes, syntax error; exit.
  181.                CMP    AL,'"'                 ;Is it quotes?
  182.                JNZ    STORE                  ;If no, store the byte
  183.                CALL   DELIMITER              ; else, see if delimiter
  184.                JNC    STORE                  ; and store the quote if part
  185.                RET                           ; of string else, we are done.
  186.  
  187. STORE:         STOSB                         ;Store the byte
  188.                INC    CX                     ; increment byte count
  189.                JMP    SHORT NEXT_STRING      ; and get next string byte
  190.  
  191. NUMBER:        XOR    BL,BL                  ;Zero into hex counter.
  192. GET_NUMBER:    CALL   DELIMITER              ;Is it a delimiter?
  193.                JNC    LOAD_NUMBER            ;If no, get next decimal number
  194.                MOV    AL,BL                  ; get hex byte
  195.                STOSB                         ; and store
  196.                INC    CX                     ; increment byte count
  197.                RET                           ; and we are done
  198.  
  199. LOAD_NUMBER:   LODSB                         ;Get the decimal number
  200.                CMP    AL,'0'                 ;Is it between 0 and 9?
  201.                JB     ERROR                  ;If no, syntax error
  202.                CMP    AL,'9'
  203.                JA     ERROR
  204.                SUB    AL,30H                 ; else, convert to hex
  205.                MOV    BH,AL                  ; and save
  206.                MOV    AL,10                  ; multiply by ten
  207.                MUL    BL                     ; to shift place left
  208.                MOV    BL,AL
  209.                ADD    BL,BH                  ; add new number
  210.                JMP    SHORT GET_NUMBER       ; and get next decimal number.
  211. ERROR:         JMP    EXIT                   ;In lieu of range of short jump.
  212.  
  213. ;--------------------------------;
  214. ; This subroutine will parse     ;
  215. ; leading and delimiting spaces. ;
  216. ;--------------------------------;
  217.  
  218. SPACE:         INC    SI                     ;Point to next byte
  219.                CMP    BYTE PTR [SI],32       ;Is it space?
  220.                JZ     SPACE                  ;If no, get next byte
  221.                RET                           ; else, return.
  222.  
  223. ;----------------------------;
  224. ; This subroutine will check ;
  225. ; for delimiter characters.  ;
  226. ;----------------------------;
  227.  
  228. DELIMITER:     CLC                           ;Assume not delimiter.
  229.                CMP    BYTE PTR [SI],32       ;Is it space
  230.                JZ     SET_CARRY
  231.                CMP    BYTE PTR [SI],13       ; or carriage return
  232.                JZ     SET_CARRY
  233.                CMP    BYTE PTR [SI],','      ; or comma?
  234.                JNZ    RETURN                 ;If no, return else, indicate
  235. SET_CARRY:     STC                           ; by setting carry flag
  236. RETURN:        RET                           ; and return.
  237.  
  238. ;-------------------------------------------------------------;
  239. ; Storage buffers for findstring, replacestring and file at   ;
  240. ; end of code to make basic data listing appreciably shorter. ;
  241. ;-------------------------------------------------------------;
  242.  
  243. FIND$:
  244. ORG  OFFSET FIND$+128
  245. REPLACE$:
  246. ORG  OFFSET REPLACE$+128
  247. BUFFER:
  248.  
  249. CODE ENDS
  250. END  START
  251.