home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / assemblr / 03 / red.asm < prev    next >
Assembly Source File  |  1986-02-05  |  10KB  |  259 lines

  1. RED segment para public 'code'
  2.     assume    cs:RED, ds:RED, es:RED, ss:NOTHING
  3.     org    100h        ; .COM format
  4. BEGIN:
  5.     jmp    CODE_START    ; Jump around data declarations
  6. ;
  7. DECLARE:    ; Messages, Storage Areas, Equates
  8.     COPYRIGHT    db    'REDirect (C) 1985, Dickinson Associates Inc.'
  9.             db    13,10,'$'
  10.     PATH_FILE_LEN    equ    77  ;Length = 1, Path = 63, FileName = 12, 0 = 1
  11.     SOURCE_FILE    db    PATH_FILE_LEN dup (0)
  12.     TARGET_PATH    db    PATH_FILE_LEN dup (0)
  13.     SOURCE_END    dw    0
  14.     TARGET_END    dw    0
  15.     PC_DOS_VER    db    0
  16.     VALID_IN    db    'abcdefghijklmnopqrstuvwxyz,;=',9
  17.     VALID_OUT    db    'ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
  18.     VALID_NUM    equ    $ - VALID_OUT + 1
  19.     ERR_FLAG    db    0
  20.     ERR_HEAD    db    10,13,'REDirect Error - $'
  21.     BAD_VERSION    db    'Incorrect PC-DOS Version$'
  22.     NO_PARMS    db    'Correct Syntax is:',13,10,10
  23.     db    'RED [d:][source_path]source_filename[.ext] [d:][target_path]$'
  24.     FILE_NOT_FOUND    db    'File Not Found$'
  25.     PATH_NOT_FOUND    db    'Target Path Not Found$'
  26.     PC_DOS_2_PATCH    db    13,10,'or $'
  27.     DRIVES_CONFLICT db    'Source and Target Disk Drives Conflict$'
  28.     UNDEFINED_ERR    db    'Undefined Error: PC-DOS Function 56H$'
  29.     ERR_TAIL    db    10,10,13,' . . . Aborting',10,13,13,'$'
  30.     GOOD_MSG    db    ' . . REDirected to . . $'
  31.     BAD_MSG1    db    ' . . NOT REDirected . . $'
  32.     BAD_MSG2    db    ' . . already exists$'
  33.     END_LINE    db    10,13,'$'
  34. ;
  35. CODE_START:    ; Parse command line into source & target parameters
  36.     mov    dx,offset COPYRIGHT    ; Display copyright notice
  37.     mov    ah,9h
  38.     int    21h
  39.     mov    ah,30h            ; Get PC-DOS Version
  40.     int    21h
  41.     mov    PC_DOS_VER,al
  42.     mov    si,80h            ; PSP parameter byte count pointer
  43.     mov    cl,[si]         ; Move byte count to CL
  44.     xor    ch,ch            ; Zero CH
  45.     jcxz    NO_PARMS_PASSED     ; If CX is zero, there are no parameters
  46.     mov    dx,cx            ; Save byte count in dx
  47.     inc    si            ; Point to parameter area
  48.     mov    di,si            ; Copy SI to DI for cleanup routine
  49.     cld                ; Set direction flag to forward
  50. CLEAN_PARMS:    ; Change valid delimiters to blanks, lower to upper case
  51.     lodsb                ; Load each character to AL
  52.     push    di            ; Save DI on stack
  53.     mov    di,offset VALID_IN    ; Point to table of valid inputs
  54.     push    cx            ; Save CX on stack
  55.     mov    cx,VALID_NUM        ; Set CX to number of inputs to look for
  56. repne    scasb                ; See if any are in AL
  57.     jcxz    CLEAN_END        ; If not, change nothing
  58.     mov    bx,VALID_NUM        ; Set up BX to point to valid output
  59.     sub    bx,cx            ; This will leave BX one off
  60.     mov    al,VALID_OUT [bx - 1]    ; Load the valid output to AL
  61. CLEAN_END:
  62.     pop    cx            ; Restore CX
  63.     pop    di            ; Restore DI
  64.     stosb                ; Store modified AL back to PSP
  65. loop    CLEAN_PARMS            ; Loop until CX is zero
  66. ;
  67.     mov    cx,dx            ; Restore number of bytes in PSP to CX
  68.     mov    dx,2            ; Set DX to look for up to 2 parameters
  69.     mov    bx,offset SOURCE_FILE    ; Set BX to address of 1st parameter
  70.     mov    al,' '                  ; Set up to scan for first non-blank
  71.     mov    di,81h            ; Set DI to PC-DOS parameter pointer
  72. FIND_PARMS:    ; Start looking for parameters, load to program storage
  73. repe    scasb                ; Scan while blanks
  74.     mov    si,di            ; Set SI to second non-blank byte
  75.     dec    si            ; Adjust it to first non-blank byte
  76.     inc    cx            ; Adjust CX to compensate
  77.     jcxz    PARMS_LOADED        ; If CX is zero, no parameters left
  78.     mov    di,bx            ; Set DI to parameter hold area
  79.     mov    ax,cx            ; Store CX to first byte of hold area
  80.     stosb                ; DI is adjusted to second byte here
  81. STORE:    lodsb                ; Load each byte to AL
  82.     cmp    al,' '                  ; Is it a blank?
  83.     jz    END_STORE        ; Yes, end of this parameter
  84.     stosb                ; No, store the byte to hold area
  85. END_STORE:
  86.     loopnz    STORE            ; Keep looking
  87.     sub    [bx],cx         ; Store number of bytes in each
  88.     jcxz    PARMS_LOADED        ; If CX is zero, no more parameters
  89.     dec    byte ptr [bx]        ; parameter to first byte of hold area
  90.     mov    di,si            ; Set up to scan for next non-blank
  91.     dec    di            ; Adjust DI to point to the blank
  92.     inc    cx            ; Adjust CX to compensate
  93.     dec    dx            ; Decrement DX counter
  94.     cmp    dx,0            ; Is DX zero?
  95.     jz    PARMS_LOADED        ; Yes, all expected parameters loaded
  96.     add    bx,PATH_FILE_LEN    ; No, point to next part of hold area
  97.     jmp    FIND_PARMS        ; Go back and look for more
  98. PARMS_LOADED:                ; All parameters are loaded
  99.     cmp    SOURCE_FILE[0],0    ; If there are no bytes in the
  100.     ja    FIX_UP            ; SOURCE_FILE, no parameters present
  101. NO_PARMS_PASSED:            ; Exit with an error if there
  102.     mov    dx,offset NO_PARMS    ; are no parameters passed
  103.     jmp    ERROR_EXIT
  104. FIX_UP:                 ; Fix SOURCE_FILE and TARGET_PATH
  105.     mov    si,offset SOURCE_FILE    ; For Search and Rename calls
  106.     lodsb                ; Get Number of bytes
  107.     xor    ah,ah            ; Zero high byte of AX
  108.     mov    di,si            ; Move SI to DI for scan
  109.     add    di,ax            ; Start scan at end of parameter
  110.     dec    di
  111.     mov    cx,ax            ; Set CX to number of bytes
  112.     mov    al,'\'                  ; Scan for the last '\'
  113.     std                ; Set direction flag to reverse
  114. repnz    scasb                ; Scan while not '\'
  115.     jnz    NO_SOURCE_DIR        ; If Zero Flag not set, '\' not found
  116.     add    di,2            ; Add 2 to DI to point to file name
  117.     jmp    SOURCE_FIXED        ; position
  118. NO_SOURCE_DIR:                ; No source directory was specified
  119.     add    di,1            ; Adjust DI
  120.     cmp    SOURCE_FILE[2],':'      ; Check for specified disk drive
  121.     jne    SOURCE_FIXED        ; None present, we're done
  122.     mov    di,offset SOURCE_FILE[3]; Yes, set DI to point to first byte
  123. SOURCE_FIXED:                ; after ':'
  124.     mov    SOURCE_END,di        ; Move DI to SOURCE_END pointer
  125. ;
  126.     cld                ; Set direction flag to forward
  127.     mov    si,offset TARGET_PATH    ; Set up to look for '\' present
  128.     lodsb                ; Get number of bytes
  129.     cmp    al,0            ; If it's zero, no target specified
  130.     je    NO_TARGET
  131.     xor    ah,ah            ; Zero high byte of AX
  132.     add    si,ax            ; Add it to SI to point to end
  133.     dec    si            ; Decrement SI to adjust
  134.     lodsb                ; Look at last byte
  135.     mov    di,si            ; Copy SI to DI
  136.     cmp    al,'\'                  ; Is last byte a '\'?
  137.     je    TARGET_FIXED        ; Yes, everything's fine
  138.     cmp    TARGET_PATH[0],2    ; If TARGET_PATH is 2 bytes long and
  139.     jne    STORE_SLASH        ; is a disk drive specification,
  140.     cmp    TARGET_PATH[2],':'      ; let it default to the current
  141.     je    TARGET_FIXED        ; directory.
  142. STORE_SLASH:                ; Place a '\' at the end of
  143.     mov    al,'\'                  ; TARGET_PATH if user did
  144.     stosb                ; not
  145. TARGET_FIXED:
  146.     mov    TARGET_END,di        ; Move DI to TARGET_END pointer
  147.     jmp    FIND_FILE
  148. NO_TARGET:                ; Set up to allow target path default
  149.     mov    TARGET_END,offset TARGET_PATH + 1    ; to current path
  150. FIND_FILE:
  151.     mov    dx,offset SOURCE_FILE + 1    ; DX points to SOURCE_FILE
  152.     mov    ah,4eh            ; Request function 4EH (find 1st file)
  153.     mov    cx,0            ; Set CX to zero for normal files only
  154.     int    21h            ; Call PC-DOS
  155.     jnc    FOUND_FILE        ; If no error, first file found
  156.     mov    dx,offset FILE_NOT_FOUND    ; If no files found, exit
  157.     jmp    ERROR_EXIT            ; program with error message
  158. FOUND_FILE:
  159.     mov    di,SOURCE_END        ; DI points to end of source path
  160.     mov    si,9eh            ; SI points to default DTA in PSP
  161.     mov    cx,13            ; DTA will have 13 bytes
  162. rep    movsb                ; Move bytes to SOURCE_FILE
  163.     mov    di,TARGET_END        ; DI points to end of target path
  164.     mov    si,9eh            ; SI points to default DTA in PSP
  165.     mov    cx,13            ; DTA will have 13 bytes
  166. rep    movsb                ; Move bytes to TARGET_PATH
  167. ;
  168.     mov    dx,offset SOURCE_FILE + 1    ; DX points to old file name
  169.     mov    di,offset TARGET_PATH + 1    ; DI points to new file name
  170.     mov    ah,56h            ; Request function 56H (rename file)
  171.     int    21h            ; Call PC-DOS
  172.     jnc    GOOD_RED        ; If no error, call was successful
  173.     cmp    ax,3            ; Check for error 3 (path not found)
  174.     jne    ERR_5
  175.     mov    dx,offset PATH_NOT_FOUND
  176.     jmp    ERROR_EXIT        ; Exit program with error message
  177. ERR_5:    cmp    ax,5            ; Check for error 5 (file inaccessible)
  178.     jne    ERR_17
  179.     mov    ERR_FLAG,1        ; Soft error -
  180.     call    RED_MSG         ; Issue message with subroutine
  181.     jmp    NEXT_FILE        ; and keep going
  182. ERR_17: cmp    ax,17            ; Check for error 17 (drive conflict)
  183.     jne    UNDEF
  184.     mov    dx,offset DRIVES_CONFLICT
  185.     jmp    ERROR_EXIT        ; Exit program with error message
  186. UNDEF:    mov    dx,offset UNDEFINED_ERR ; Undefined error from function 56H
  187.     jmp    ERROR_EXIT        ; Exit program with error message
  188. GOOD_RED:
  189.     mov    ERR_FLAG,0        ; Set error flag off and
  190.     call    RED_MSG         ; issue message with subroutine
  191. NEXT_FILE:                ; Look for next file
  192.     mov    ah,4fh            ; Request function 4FH (find next file)
  193.     mov    cx,0
  194.     int    21h
  195.     jnc    FOUND_ANOTHER        ; No error, another file was found
  196.     jmp    END_OK            ; Error, we're done finding files
  197. FOUND_ANOTHER:
  198.     jmp    FOUND_FILE        ; Go process next file
  199. END_OK: int    20h            ; Exit to PC-DOS
  200.  
  201. ERROR_EXIT:                ; Print Error Message and Exit
  202.     push    dx            ; Save error message pointer on stack
  203.     mov    ah,9            ; Display error header
  204.     mov    dx,offset ERR_HEAD
  205.     int    21h
  206.     mov    ah,9            ; Display error message
  207.     pop    dx
  208.     int    21h
  209.     mov    ah,9            ; Display error tail
  210.     mov    dx,offset ERR_TAIL
  211.     int    21h
  212.     int    20h            ; Exit to PC-DOS
  213. ;
  214. RED_MSG proc    near    ; Display message for each file
  215.     mov    cx,2            ; 2 fields - source & target file
  216.     mov    bx,offset SOURCE_FILE + 1    ; Point to source file
  217. START1: mov    si,bx            ; Copy BX to SI
  218. START2: lodsb                ; Load each byte to AL
  219.     cmp    al,0            ; If ASCII 0, end of field
  220.     je    BETWEEN
  221.     mov    dl,al            ; Copy byte to DL for funciton 2H
  222.     mov    ah,2h            ; Request function 2H
  223.     int    21h            ; Call PC-DOS
  224.     jmp    START2            ; Get next character
  225. BETWEEN:cmp    cx,2            ; Is it first or second field?
  226.     jne    CR_LF            ; If second, display end of message
  227.     cmp    ERR_FLAG,0        ; Is this a success message?
  228.     jz    OK1            ; Yes, go use GOOD_MSG
  229.     mov    dx, offset BAD_MSG1    ; No, display first part of BAD_MSG
  230.     mov    ah,9h            ; Request function 9H
  231.     int    21h            ; Call PC-DOS
  232.     jmp    NEXT            ; Go process next field
  233. OK1:    mov    dx,offset GOOD_MSG    ; Display GOOD_MSG
  234.     mov    ah,9h            ; Request function 9H
  235.     int    21h            ; Call PC-DOS
  236.     jmp    NEXT            ; Go process next field
  237. CR_LF:    cmp    ERR_FLAG,0        ; Is this a success message?
  238.     jz    OK2            ; Yes, go terminate message
  239.     mov    dx,offset BAD_MSG2    ; No, display second part of BAD_MSG
  240.     mov    ah,9h            ; Request function 9H
  241.     int    21h            ; Call PC-DOS
  242. PC_DOS_2:                ; Patch for incorrect error
  243.     cmp    PC_DOS_VER,3        ; return in PC-DOS 2.0 and 2.1
  244.     jae    OK2
  245.     mov    dx,offset PC_DOS_2_PATCH
  246.     mov    ah,9h
  247.     int    21h
  248.     mov    dx,offset PATH_NOT_FOUND
  249.     int    21h
  250. OK2:    mov    dx,offset END_LINE    ; Terminate display line
  251.     mov    ah,9h            ; Request function 9H
  252.     int    21h            ; Call PC-DOS
  253. NEXT:    add    bx,PATH_FILE_LEN    ; Move BX to point to next field
  254.     loop    START1            ; Loop for second field
  255.     ret                ; Or end and return to callint point
  256. RED_MSG     endp
  257. RED    ends
  258.     end    BEGIN
  259.