home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / nfd104.arc / NFD.ASM next >
Encoding:
Assembly Source File  |  1987-11-25  |  29.1 KB  |  667 lines

  1.         TITLE   NFD - New File Date Utility 1.03 28 Oct 87
  2.     page    62,132
  3.  
  4. ;*************************************************************************
  5. ; This program is NOT copyrighted in any way and may be used in whole or
  6. ; in part in any manner.  The author, as is usual, makes no claims about
  7. ; the suitability of this program for any purpose whatsoever and disclaims
  8. ; liability for any damages, actual or consequential, that may arise from
  9. ; use of this program.
  10. ;
  11. ;     Don A. Williams
  12. ;     7 Mar 86
  13. ;*************************************************************************
  14.  
  15. ;*************************************************************************
  16. ; The source for NFD, NFD.ASM, as issued is intended for use with
  17. ; SpeedWare's excellent assembler, Turbo Editasm.  For use with Micrsoft's
  18. ; MASM, SEGMENT, ASSUME, and ENDS statements will have to be added.
  19. ;*************************************************************************
  20.  
  21. ;*************************************************************************
  22. ; Source modified on 28 Oct 87 for use with MASM and added a conditional
  23. ; to GetArgs in order to allow the "Usage: . . ." output when no arguments
  24. ; are supplied.  (Aside:  the differences in the generated machine code,
  25. ; MASM vs. Turbo Editasm, are interesting to say the least.  CISC cause
  26. ; no doubt.) -- Will Jordan
  27. ; Source modified again 25 Nov 87 -- flipped condition (jnz, was jz) 2
  28. ; lines before "GotDir:"; corrected "Could not find file" message when
  29. ; the filename is explicitly entered.
  30. ;*************************************************************************
  31.  
  32. CODESEG  segment para public 'code'
  33.          assume cs:CODESEG,ds:CODESEG,es:CODESEG,ss:CODESEG
  34.  
  35. LF      EQU     0AH
  36. CR      EQU     0DH
  37.  
  38. DTA    EQU    80H            ; define (default) DTA of PSP
  39. FATTRD  EQU    byte ptr DTA[21]    ; defining all parm's, even not used
  40. FTIMED    EQU    word ptr DTA[22]
  41. FDATED    EQU    word ptr DTA[24]
  42. FSIZLD    EQU    word ptr DTA[26]
  43. FSIZHD    EQU    word ptr DTA[28]
  44. FNAMED    EQU    byte ptr DTA[30]
  45.  
  46. ARDONLY    EQU    01H            ; define file attribute (FATTR) bits
  47. AHIDDEN    EQU    02H
  48. ASYSTEM    EQU    04H
  49. AVOLLAB    EQU    08H
  50. ASUBDIR    EQU    10H
  51. AARCHIV    EQU    20H
  52.  
  53.         ORG     0100H
  54.  
  55. Start:  jmp     Begin
  56.  
  57. DateSw  dw      0
  58. TimeSw  dw      0
  59.  
  60. NFDate  dw      0                       ; New Date for file
  61. NFTime  dw      0                       ; New Time for file
  62.  
  63. FDate   dw      0                       ; File Date From/To Function 57H
  64. FTime   dw      0                       ; File Time From/To Function 57H
  65.  
  66. Hour    dw      0
  67. Minute  dw      0
  68. Second  dw      0
  69.  
  70. Day     dw      0
  71. Month   dw      0
  72. Year    dw      0
  73.  
  74. ArgSep  db      0
  75.  
  76. TmpCnt  dw      0
  77. PtrOfs  dw      0
  78.  
  79. UseMsg  db      'Usage is: NFD <filename> [mm/dd/yy] [hh:mm:ss]',CR,LF
  80.     db    '  /s for silent operation (no STDOUT)',CR,LF
  81.     db    '  /n for no query',CR,LF,'$'
  82.  
  83. NFMsg   db      'Could not find file',CR,LF,'$'
  84.  
  85. BDMsg   db      'Incorrect date',2CH,' format is mm/dd/yy or mm-dd-yy',CR,LF,'$'
  86.  
  87. BTMsg   db      'Incorrect time',2CH,' format is hh:mm:ss',CR,LF,'$'
  88.  
  89. IntMsg  db      'Internal error during file access',CR,LF,'$'
  90.  
  91. SignOn    db    'NFD Version: 1.04  -  25 Nov 87',CR,LF,LF,0
  92.  
  93. From    db      CR,LF,'    From: ',0
  94.  
  95. To      db      '   To: ',0
  96.  
  97. CrLfMs  db      CR,LF,0
  98.  
  99. Query   db      '   Change? ',0
  100.  
  101. Begin:  mov    SI,offset SignOn    ; Display logon message
  102.     call    PrtStr            ; ...
  103.     call    GetArgs                 ; Parse Command Line arguments
  104.         cmp     word ptr ARGC,0         ; Check for no arguments
  105.         jz      Usage                   ; ... Xfr - no arguments
  106.         cmp     word ptr ARGC,4         ; Check for more than 4 arguments
  107.         ja      Usage                   ; ... Xfr - more than 4
  108.         call    GetPath                 ; Extract Path from File Path Name
  109.     call    DateTime
  110.     cmp    word ptr DateSw,0    ; Check for Date argument
  111.     jne    CheckTime        ; ... Xfr - Date on Command Line
  112.         mov     AH,2AH                  ; MS-DOS 'Get Date'
  113.         int     21H                     ; ... DOS Entry Interrupt
  114.         sub     CX,1900                 ; Make Year 1900 relative
  115.         mov     Year,CX                 ; ... and save it
  116.         mov     CL,DH                   ; Move Month to CX as 16-bit value
  117.         mov     CH,0                    ; ...
  118.         mov     Month,CX                ; ... and save it
  119.         mov     CL,DL                   ; Move Day to CX as 16-bit value
  120.         mov     Day,CX                  ; ... and save it
  121. CheckTime:
  122.     cmp    word ptr TimeSw,0    ; Check for Time on Command Line
  123.     jne    Here            ; ... Xfr - Time on Command Line
  124.         mov     AH,2CH                  ; MS-DOS 'Get Time'
  125.         int     21H                     ; ... DOS Entry Interrupt
  126.         mov     AX,0                    ; Move Hour to AX as 16-bit value
  127.         mov     AL,CH                   ; ...
  128.         mov     Hour,AX                 ; ... and save it
  129.         mov     AL,CL                   ; Move Minute to AX as 16-bit value
  130.         mov     Minute,AX               ; ... and save it
  131.         mov     AL,DH                   ; Move Second to AX as 16-bit value
  132.         mov     Second,AX               ; ... and save it
  133.     mov    word ptr DateSw,0FFH
  134.     mov    word ptr TimeSw,0FFH
  135. Here:   jmp     Format
  136.  
  137. Usage:  mov     DX,offset UseMsg        ; Display 'Usage' message
  138.         mov     AH,9                    ; ... MS-DOS 'Print String'
  139.         int     21H                     ; ... DOS Entry Interrupt
  140.         mov     AL,1                    ; Set error code
  141.         jmp     Term                    ; ... and terminate
  142.  
  143. DateTime:
  144.         mov     AX,ARGC                 ; Initialize loop counter to ARGC
  145.         mov     TmpCnt,AX               ; ...
  146.         mov     word ptr PtrOfs,0       ; Initialize Arg ptr offset to 0
  147.  
  148. ArgLoop:
  149.         add     word ptr PtrOfs,2       ; Incr Arg ptr offset
  150.         dec     word ptr TmpCnt         ; ... and decr loop count
  151.         jnz     DoArg                   ; ... Xfr - loop count not exhausted
  152.     ret
  153.  
  154. DoArg:
  155.         mov     BX,PtrOfs               ; Get Arg ptr offset
  156.         mov     SI,[BX+ARGV]            ; ... and Arg ptr
  157.         mov     AL,byte ptr [SI]        ; Check for switch arg
  158.         cmp     AL,'/'                  ; ... primary switch char
  159.         je      Switch                  ; ... Xfr - got switch
  160.         cmp     AL,'-'                  ; ... secondary switch char
  161.         je      Switch                  ; ... Xfr - got switch
  162.         call    GetNumber               ; Convert 1st arg field to binary
  163.         cmp     AL,'/'                  ; Check for Date field separator
  164.         jz      GotMonth                ; ... Xfr - got separator
  165.         cmp     AL,'-'                  ; Check for Date field separator
  166.         jz      GotMonth                ; ... Xfr - got separator
  167.         cmp     AL,':'                  ; Check for Time field spearator
  168.         jnz     Usage                   ; ... Xfr - bad format
  169.         jmp     GotHour                 ; Xfr - got separator
  170.  
  171. Switch:
  172.         inc     SI                      ; Skip switch char
  173.  
  174. SWLoop: lodsb                           ; Get byte
  175.         cmp     AL,0                    ; Check for NULL terminator
  176.         je      ESW                     ; ... Xfr - NULL - end of Arg
  177.         and     AL,0DFH                 ; Force upper case
  178.         cmp     AL,'N'                  ; Check for 'No Query'
  179.         je      NQ                      ; ... Xfr - 'No Query
  180.         cmp     AL,'S'                  ; Check for 'Silent'
  181.         je      Silent                  ; ... Xfr - 'Silent'
  182.         jmp     Usage                   ; Xfr - invalid switch
  183.  
  184. NQ:     mov     byte ptr QSwt,0FFH      ; Turn on No Query Switch
  185.         jmp     short SWLoop            ; Go try for another switch
  186.  
  187. Silent: mov     byte ptr SSwt,0FFH      ; Turn on Silent Switch
  188.         jmp     short SWLoop            ; Go try for another switch
  189.  
  190. ESW:    jmp    ArgLoop         ; Go try for another argument
  191.  
  192.  
  193. ErExit: mov     AH,9                    ; MS-DOS 'Print String'
  194.         int     21H                     ; ... DOS Entry Interrupt
  195.         mov     AL,2
  196.         jmp     Term
  197.  
  198. GotMonth:
  199.         cmp     word ptr DateSw,0       ; Check Date Arg Switch
  200.         jz      DoDate                  ; ... Xfr - OFF - okay
  201.         jmp     short Usage             ; Go display Usage msg and term
  202.  
  203. DoDate: mov     word ptr DateSw,1       ; Set Date Arg Switch ON
  204.         cmp     CX,0                    ; Check for zero field
  205.         jbe     BadDate                 ; ... Xfr - bad Date field
  206.         cmp     CX,12                   ; Check Month upper limit
  207.         ja      BadDate                 ; ... Xfr - Month too high
  208.         mov     Month,CX                ; Save binary month
  209.         mov     ArgSep,AL               ; Save field separator
  210.         inc     SI                      ; Incr to next field of Date
  211.         call    GetNumber               ; ... and convert to binary
  212.         cmp     AL,0                    ; Check for NULL terminator
  213.         jz      EndDate                 ; ... Xfr - end of parameters
  214.         cmp     AL,ArgSep               ; Was it the same as for Month?
  215.         jnz     BadDate                 ; ... Xfr - no - bad date format
  216. EndDate:
  217.         cmp     CX,0                    ; Check field value for zero
  218.         jbe     BadDate                 ; ... Xfr - Day <= 0 - bad
  219.         cmp     CX,31                   ; Check Day upper limit
  220.         ja      BadDate                 ; ... Xfr - too high - bad
  221.         mov     Day,CX                  ; Save binary Day
  222.         cmp     AL,0                    ; Check for NULL terminator
  223.         jnz     DoYear                  ; ... Xfr - not end of parameters
  224.         jmp     ArgLoop                 ; Xfr - end of parameters
  225.  
  226. DoYear: inc     SI                      ; Incr to next Date field [Year]
  227.         call    GetNumber               ; Convert to binary
  228.         cmp     AL,0                    ; Check for NULL terminator
  229.         jnz     BadDate                 ; ... Xfr - not end - bad format
  230.         cmp     CX,80                   ; Check lower limit of Year
  231.         jb      BadDate                 ; ... Xfr - < lower limit - bad
  232.         cmp     CX,99                   ; Check upper limit of Year
  233.         ja      BadDate                 ; ... Xfr - > upper limit - bad
  234.         mov     Year,CX                 ; Save binary Year
  235.         jmp     ArgLoop
  236.  
  237. BadDate:
  238.         mov     DX,offset BDMsg         ; Display 'Bad Date' message
  239.         jmp     short ErExit            ; ... and terminate
  240.  
  241. GotHour:
  242.         cmp     word ptr TimeSw,0       ; Check Time Arg switch
  243.         jz      DoTime                  ; ... Xfr - OFF - okay
  244.         jmp     Usage                   ; Display 'Usage' msg and term
  245.  
  246. DoTime: mov     word ptr TimeSw,1       ; Turn ON Time Arg switch
  247.         cmp     CX,24                   ; Check upper limit on Hour
  248.         ja      BadTime                 ; ... Xfr - too high - error
  249.         mov     Hour,CX                 ; Save binary Hour
  250.         mov     ArgSep,AL               ; Save field separator
  251.         inc     SI                      ; incr ptr past separator
  252.         call    GetNumber               ; Get Minute in binary
  253.         cmp     AL,0                    ; Check for NULL terminator
  254.         jz      EndTime                 ; ... Xfr - NULL terminator
  255.         cmp     AL,' '                  ; Check for blank terminator
  256.         jz      EndTime                 ; ... Xfr - Blank terminator
  257.         cmp     AL,ArgSep               ; Compare separator to prior
  258.         jnz     BadTime                 ; ... Xfr - not same - error
  259. EndTime:
  260.         cmp     CX,59                   ; Check upper limit on Minute
  261.         ja      BadTime                 ; ... Xfr - too high - error
  262.         mov     Minute,CX               ; Save binary minute
  263.         cmp     AL,0                    ; Check for NULL terminator
  264.         jz      NoSec                   ; ... Xfr - NULL - no seconds
  265.         cmp     AL,' '                  ; Check for Blank terminator
  266.         jnz     DoSec                   ; ... Xfr - not Blank - get secs
  267. NoSec:  mov     word ptr Second,0       ; Zero-set binary Second
  268.         jmp     ArgLoop                 ; Go try for another argument
  269.  
  270. DoSec:  inc     SI                      ; Incr ptr past separator
  271.         call    GetNumber               ; Get Seconds in binary
  272.         cmp     AL,0                    ; Check for NULL terminator
  273.         jnz     BadTime                 ; ... Xfr - not NULL - error
  274.         cmp     CX,59                   ; Check upper limit on Seconds
  275.         ja      BadTime                 ; ... Xfr - too high - error
  276.         mov     Second,CX               ; Save binary Seconds
  277.         jmp     ArgLoop                 ; Go try for another argument
  278.  
  279. BadTime:
  280.         mov     DX,offset BTMsg         ; Display 'Bad Time' message
  281.         jmp     ErExit                  ; ... and terminate
  282.  
  283. Format: mov     AX,Year                 ; Format today's date for Directory
  284.         sub     AX,80                   ; ... entry Date format
  285.         mov     CX,4                    ; ...
  286.         shl     AX,CL                   ; ...
  287.         or      AX,Month                ; ...
  288.         mov     CX,5                    ; ...
  289.         shl     AX,CL                   ; ...
  290.         or      AX,Day                  ; ...
  291.         mov     NFDate,AX               ; Save formated New File Date
  292.         mov     AX,Hour                 ; Format current time for Directory
  293.         mov     CX,6                    ; ... entry format
  294.         shl     AX,CL                   ; ...
  295.         or      AX,Minute               ; ...
  296.         mov     CX,5                    ; ...
  297.         shl     AX,CL                   ; ...
  298.         mov     BX,Second               ; ...
  299.         shr     BX,1                    ; ...
  300.         or      AX,BX                   ; ...
  301.         mov     NFTime,AX               ; Save formated New File Time
  302.         
  303.         mov     DX,offset Path
  304.         mov     CX,(AHIDDEN+AARCHIV)    ; ... find ALL files
  305.         mov     AH,4EH                  ; ... MS-DOS 'Find First Match'
  306.         int     21H                     ; ... DOS Entry Interrupt
  307.         jnc     DoFile                  ; ... Xfr - match
  308.     jmp    NoFile            ; Xfr - no match
  309.  
  310. DoFile: mov     DI,FName                ; Get ptr to File Name in Path
  311.         mov     SI,FNAMED               ; ... and ptr to File Name in DTA
  312.         mov     CX,15                   ; ... set CX for max length
  313.  
  314. DFLoop: lodsb                           ; Move File Name from DTA to
  315.         stosb                           ; ... Path
  316.         cmp     AL,0                    ; Check for NULL terminator
  317.         je      DFEnd                   ; ... Xfr - NULL - end of name
  318.         loop    DFLoop
  319.  
  320. DFend:  mov     DX,Offset PATH          ; Get file Path name ptr for open
  321.         mov     AL,2                    ; ... set access to Read/Write
  322.         mov     AH,3DH                  ; ... MS-DOS 'Open File Handle'
  323.         int     21H                     ; ... DOS Entry Interrupt
  324.     jnc    OpenOK            ; ... Xfr - no Open Error
  325.         jmp     NoFile                  ; ... Xfr - Open Error
  326. OpenOK:
  327.         push    AX
  328.         cmp     byte ptr SSwt,0         ; Check Silent switch
  329.         jne     Sil1                    ; ... Xfr - Silent
  330.         mov     SI,offset Path          ; Display file name
  331.         call    PrtStr                  ; ...
  332.         mov     SI,offset From          ; Display 'From' message
  333.         call    PrtStr                  ; ...
  334. Sil1:   pop     AX
  335.         mov     BX,AX                   ; Move File Handle to BX
  336.         mov     AH,57H                  ; MS-DOS 'Get/Set File Date/Time'
  337.         mov     AL,0                    ; ... make it Get
  338.         int     21H                     ; ... DOS Entry Interrupt
  339.     jnc    GetOK            ; ... Xfr - no error
  340.         jmp     IntErr                  ; ... Xfr - error - bad trouble
  341. GetOK:
  342.         mov     FDate,DX                ; Save File Date
  343.         mov     FTime,CX                ; Save File Time
  344.         cmp     byte ptr SSwt,0         ; Check Silent switch
  345.         jne     NewTime                 ; ... Xfr - Silent
  346.         call    PrtDate                 ; Display Old Date
  347.         call    PrtTime                 ; Display Old Time
  348. NewTime:
  349.         cmp     word ptr TimeSw,0       ; Was a Time argument supplied?
  350.         jz      NewDate                 ; ... Xfr - no
  351.         mov     AX,NFTime               ; Move New Time to File Time
  352.         mov     FTime,AX                ; ...
  353. NewDate:
  354.         cmp     word ptr DateSw,0       ; Was a Date argument supplied?
  355.         jz      SetFile                 ; ... Xfr - no
  356.         mov     AX,NFDate               ; Move New Date to File Date
  357.         mov     FDate,AX                ; ...
  358. SetFile:
  359.         mov     DX,FDate                ; ... get Date
  360.         mov     CX,FTime                ; ... get Time
  361.         cmp     byte ptr SSwt,0         ; Check for Silent
  362.         jne     Change                  ; ... Xfr - Silent
  363.         mov     SI,offset To            ; Display 'To' message
  364.         call    PrtStr                  ; ...
  365.         push    CX
  366.         push    DX
  367.         call    PrtDate                 ; Display New Date
  368.         call    PrtTime                 ; Display New Time
  369.         cmp     byte ptr QSwt,0         ; Check No Query switch
  370.         jne     Change                  ; ... Xfr - No Query switch ON
  371.         mov     SI,offset Query         ; Display Query message
  372.         call    PrtStr                  ; ...
  373.         mov     AH,1                    ; Get user's response
  374.         int     21H                     ; ... DOS Entry Interrupt
  375.         and     AL,0DFH                 ; Force upper case
  376.         cmp     AL,'Y'                  ; Check for YES
  377.         pop     DX
  378.         pop     CX
  379.         je      Change                  ; ... Xfr - YES - Change it
  380.         jmp     short NoChange          ; ... Assume NO - No Change
  381. Change:
  382.         mov     AH,57H                  ; MS-DOS 'Get/Set File Date/Time'
  383.         mov     AL,1                    ; ... make it Set
  384.         int     21H                     ; ... DOS Entry Interrupt
  385.         jb      IntErr                  ; ... Xfr - error - bad trouble
  386. NoChange:
  387.         cmp     byte ptr SSwt,0         ; Check for Silent
  388.         jne     Sil2                    ; ... Xfr - Silent
  389.         call    NewLine                 ; Advance display to new line
  390. Sil2:   mov     AH,3EH                  ; MS-DOS 'Close File Handle'
  391.         int     21H                     ; ... DOS Entry Interrupt
  392.         jb      IntErr                  ; ... Xfr - error - bad trouble
  393.         mov     AH,4FH                  ; MS-DOS 'Find Next Match'
  394.         int     21H                     ; ... DOS Entry Interrupt
  395.         jb      NormTerm                ; Xfr - no more files - terminate
  396.         jmp     DoFile
  397.  
  398. NormTerm:
  399.         mov     AL,0                    ; Set return code for Good return
  400. Term:   mov     AH,4CH                  ; MS-DOS 'Terminate Process'
  401.         int     21H                     ; ... DOS Entry Interrupt
  402.         ret
  403.  
  404. NoFile: mov     DX,offset NFMsg         ; Display 'Not Found' message
  405.         jmp     ErExit                  ; ... and terminate
  406.  
  407. IntErr: mov     DX,offset IntMsg        ; Display 'Internal Error' message
  408.         jmp     ErExit                  ; ... and terminate
  409.  
  410.  
  411. GetArgs:
  412.         cld                             ; Clear Direction Flag [forward]
  413.         mov     SI,DTA                  ; Get ptr to Command Tail length
  414.         mov     CL,[SI]                 ; Get length to CX as 16-bit value
  415.         mov     CH,0                    ; ...
  416.         push    CX                      ; Save Command Tail length
  417.         inc     SI                      ; Incr ptr to 1st data byte
  418.         mov     DI,offset COMMND        ; Get ptr to internal Command Tail
  419.         rep     movsb                   ; ... and move it
  420.         mov     byte ptr [DI],0         ; Store NULL terminator
  421.         pop     CX                      ; Restore Command Tail length
  422.         mov     SI,offset COMMND        ; Get ptr to internal Command Tail
  423.         mov     word ptr ARGC,0         ; Initialize Arg Count to 0
  424.         mov     BX,offset ARGV          ; Initialize ARGV to Path
  425.     cmp    CX,0            ; Test for no arguments
  426.     jz    GAExit            ; ... and get out now if none
  427.  
  428. NextArg:
  429.         mov     AL,' '                  ; By pass leading blanks
  430.         xchg    SI,DI                   ; ...
  431.         repz    scasb                   ; ...
  432.         dec     DI                      ; Back up ptr
  433.         inc     CX                      ; ... and count
  434.         xchg    SI,DI                   ; ... and put back in Source Index
  435.         jcxz    GAExit                  ; Xfr - nothing but blanks
  436.         mov     [BX],SI                 ; Save ptr to file Path Name
  437.         add     BX,2                    ; Incr Arg ptr offset to next
  438.         inc     word ptr ARGC           ; Incr Arg Count
  439.         mov     AL,' '                  ; Now scan for blank following path
  440.         xchg    SI,DI                   ; ...
  441.         repnz   scasb                   ; ...
  442.         dec     DI                      ; Back up ptr
  443.         xchg    SI,DI
  444.         jcxz    GAExit                  ; Xfr - end of Tail
  445.         mov     byte ptr [SI],0         ; Store NULL terminator at end of Path
  446.         inc     SI                      ; Incr ptr past NULL
  447.         jmp     short NextArg           ; Go get next arg
  448.  
  449. GAExit: ret
  450.  
  451. GetNumber:
  452.         push    BX                      ; Save BX
  453.         mov     BX,10                   ; ... and set BX to multiplier
  454.         mov     CX,0                    ; Initialize result to 0
  455.  
  456. GNLoop: mov     AL,[SI]                 ; Get byte from argument
  457.         cmp     AL,'0'                  ; Check for numeric
  458.         jb      GNExit                  ; ... Xfr - not numeric - too low
  459.         cmp     AL,'9'                  ; ... no check upper limit
  460.         ja      GNExit                  ; ... Xfr - not numeric - too high
  461.         sub     AL,'0'                  ; Convert digit to binar
  462.         cbw                             ; ... and make 16-bit value
  463.         xchg    CX,AX                   ; Put current digit in CX
  464.         imul    BX                      ; Multiply accum result by 10
  465.         add     AX,CX                   ; ... and add in current digit
  466.         xchg    CX,AX                   ; Move accumulated result to CX
  467.         inc     SI                      ; Incr arg ptr
  468.         jmp     short GNLoop            ; ... and go get next digit
  469.  
  470. GNExit: pop     BX                      ; Restore user's BX
  471.         ret
  472.  
  473. GetPath:
  474.     mov    DI,offset Path          ; Get ptr to Path storage area
  475.     mov    SI,ARGV                 ; ... and ptr to File path name
  476.     mov    CX,0                    ; ... initialize length to zero
  477.  
  478. GPL1:    lodsb                           ; Move 1 byte from File path name
  479.     stosb                           ; ... to Path
  480.     cmp    AL,0                    ; Was it NULL terminator?
  481.     je    EGPL1                   ; ... Xfr - NULL - no more
  482.     inc    CX                      ; Incr length
  483.     jmp    short GPL1              ; Go do another
  484.  
  485. GotWild:
  486.     pop    DI                      ; Restore ptr to end of Path
  487.         xchg    SI,DI                   ; ... back to SI
  488.         cmp     byte ptr [SI],'\'       ; Did Path end in a '\'?
  489.         je      Bump                    ; ... Xfr - Yes - move past
  490.         cmp     byte ptr [SI],'/'       ; Dir it end in a '/'?
  491.         je      Bump                    ; ... Xfr - Yes - move past
  492.         cmp     byte ptr [SI],':'       ; Did it end in a ':'?
  493.         je      Bump                    ; ... Xfr - Yes - move past
  494.     jmp    File                    ; Go process as a File
  495. Bump:   inc     SI                      ; Incr past terminal char
  496.         jmp     File                    ; ... and go process as File
  497.  
  498. EGPL1:    sub    DI,2                    ; Back up DI to last char
  499.     mov    PLen,CX                 ; ... and save length
  500.     mov    SI,DI                   ; Duplicate DI in SI
  501.     std                             ; Set Direction Flag [reverse]
  502.  
  503. GPL2:    lodsb                           ; Scan for last Directory delimitor
  504.     cmp    AL,'\'                  ; ... normal delimitor
  505.     je    EGPL2                   ; ... Xfr - normal delim
  506.     cmp    AL,'\'                  ; ... alternate delimitor
  507.     je    EGPL2                   ; ... Xfr - alternate delimitor
  508.     cmp    AL,':'                  ; ... disk delimitor
  509.     je    EGPL2                   ; ... Xfr - disk delimitor
  510.     loop    GPL2                    ; Loop through entire name
  511.  
  512. EGPL2:  cld                             ; Clear Direction Flag [forward]
  513.     inc    SI                      ; Back up ptr
  514.     cmp    SI,DI                   ; Was the last char of name a delim?
  515.     je    GotDir                  ; ... Xfr - handle as Directory
  516.         xchg    SI,DI                   ; Scan final element for Wild Cards
  517.     push    DI                      ; ... save ptr
  518.         mov     CX,PLen                 ; ... set length to name length
  519.     mov    AL,'*'                  ; ... scan for '*'
  520.     repnz    scasb                   ; ...
  521.     jz    GotWild                 ; ... Xfr - had at least one '*'
  522.         pop     DI                      ; Restore ptr
  523.         push    DI                      ; ... and save again
  524.     mov    CX,PLen                 ; ... set length again
  525.     mov    AL,'?'                  ; ... scan for '?'
  526.     repnz    scasb                   ; ...
  527.     jz    GotWild                 ; ... Xfr - had at least one '?'
  528.     pop    DI                      ; Restore ptr
  529.         xchg    SI,DI                   ; ... back to SI
  530.     mov    DX,offset Path          ; Get ptr to Path for Find 1st
  531.     mov    AH,4EH                  ; ... MS-DOS 'Find First Match'
  532.     mov    CX,ASUBDIR              ; ... check for directories
  533.     int    21H                     ; ... DOS Entry Interrupt
  534.     jb    NotFound                ; ... Xfr - not found
  535.     mov    AL,FATTRD               ; Get directory entry attribute (DTA)
  536.     test    AL,ASUBDIR              ; ... and test for directory
  537.     jnz    File                    ; ... Xfr - not directory
  538.     xchg    SI,DI                   ; Move Path end ptr to SI
  539.  
  540. GotDir:
  541.     inc    SI                      ; Incr to next char in Path
  542.         xchg    SI,DI                   ; ... and move ptr to DI
  543.     mov    AL,byte ptr [DI-1]      ; Is final char a directory delim?
  544.     cmp    AL,'\'                  ; ... normal delimitor
  545.     je    Dont                    ; ... Xfr - Yes - final char delim
  546.     cmp    AL,'/'                  ; ... alternate delimitor
  547.     je    Dont                    ; ... Xfr - Yes - final char delim
  548.     mov    AL,'\'                  ; Store delimitor at end of Path
  549.     stosb                           ; ...
  550.     inc    PLen                    ; ... and incr Path Length
  551. Dont:    push    DI                      ; Save ptr to 1st of element
  552.         mov    SI,offset Wild          ; ... and move '*.*' as element
  553.     mov    CX,4                    ; ... [include terminal NULL]
  554.     rep    movsb                   ; ...
  555.         pop     SI                      ; Restore ptr to element
  556.  
  557. File:    mov     word ptr FName,SI       ; Save ptr to File Name in Path
  558.         ret
  559.  
  560. NotFound:
  561.     jmp    NoFile                  ; Go display message and terminate
  562.  
  563. PrtDate:
  564.         push    AX
  565.         push    CX
  566.         push    DX
  567.         pop     AX
  568.         push    AX
  569.         mov     CL,5
  570.         shr     AX,CL
  571.         and     AX,0FH
  572.         call    PrtDecimal
  573.         mov     DL,'-'
  574.         int     21H
  575.         pop     AX
  576.         push    AX
  577.         and     AX,1FH
  578.         call    PrtDecimal
  579.         mov     DL,'-'
  580.         int     21H
  581.         pop     AX
  582.         push    AX
  583.         xchg    AH,AL
  584.         mov     AH,0
  585.         shr     AX,1
  586.         add     AL,80
  587.         call    PrtDecimal
  588.         mov     DL,' '
  589.         int     21H
  590.         pop     DX
  591.         pop     CX
  592.         pop     AX
  593.         ret
  594.  
  595. PrtTime:
  596.         push    AX
  597.         push    DX
  598.         push    CX
  599.         mov     AL,CH
  600.         mov     AH,0
  601.         mov     CL,3
  602.         shr     AX,CL
  603.         call    PrtDecimal
  604.         mov     DL,':'
  605.         int     21H
  606.         pop     AX
  607.         push    AX
  608.         mov     CL,5
  609.         shr     AX,CL
  610.         and     AX,3FH
  611.         call    PrtDecimal
  612.         mov     DL,' '
  613.         int     21H
  614.         pop     CX
  615.         pop     DX
  616.         pop     AX
  617.         ret
  618.  
  619. PrtDecimal:
  620.         aam
  621.         or      AX,'00'
  622.         push    AX
  623.         mov     DL,AH
  624.         mov     AH,2
  625.         int     21H
  626.         pop     AX
  627.         mov     DL,AL
  628.         mov     AH,2
  629.         int     21H
  630.         ret
  631.  
  632. PrtStr: push    AX
  633.     push    DX
  634.  
  635. PSLoop:    lodsb
  636.         cmp     AL,0
  637.         jz      PSExit
  638.         mov     DL,AL
  639.         mov     AH,2
  640.         int     21H
  641.         jmp     short PSLoop
  642.  
  643. PSExit: pop    DX
  644.     pop    AX
  645.     ret
  646.  
  647. NewLine:
  648.         mov     SI,offset CrLfMs
  649.         call    PrtStr
  650.         ret
  651.  
  652. QSwt    db      0                       ; Query switch - default = OFF
  653. SSwt    db      0                       ; Silent switch - default = OFF
  654.  
  655. FName   dw      0                       ; Ptr to File Name in Path
  656. PLen     dw    0            ; Length of Path
  657.  
  658. Wild     db    '*.*',0         ; Wild Card string
  659.  
  660. PATH    EQU     byte ptr $              ; Storage for Path [64 bytes max]
  661. COMMND  EQU     byte ptr PATH+64        ; Internal Command Line [255(?) bytes]
  662. ARGC    EQU     word ptr COMMND+256     ; Count of Command Line agruments
  663. ARGV    EQU     word ptr ARGC+2         ; Vector of ptrs to Arguments
  664.  
  665. CODESEG  ends
  666.         end     Start
  667.