home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / zip / zdir16b.arc / ZDIR16B.ASM next >
Assembly Source File  |  1989-09-28  |  51KB  |  1,939 lines

  1. ;ZDIR .ZIP directory utility
  2. ;From a disassembly and hack of ADIR.EXE
  3.  
  4. ;v1.6b    Back at Toad Hall ... (28 Sep 89)
  5. ;    - Removed old commented-out code (via v1.5, v1.6, v1.6a changes).
  6. ;    - NICE ideas in v1.6a  .. attaboy, Gisbert!
  7. ;    - No significant changes .. just cleaned up, making a "formal"
  8. ;      release from Toad Hall.
  9. ;    - Suppose we oughtta put in yet ANOTHER cmdline switch (-c or
  10. ;      something) for those who actually wanna pipe names (paths'n'all)
  11. ;      to StdOut.  (The -c means omit ZIP comments.)
  12.  
  13. ;v1.6a  GWS (yeah, hacking away in West Germany's capital village) strikes again
  14. ;    - Cleaning up verbose display:
  15. ;      Some columns were one off. Also, change name alignment slightly.
  16. ;    - Added /m ('monosyllabic') command line switch:
  17. ;      This will show full names, paths'n'all, as stored in the Zip,
  18. ;      one per line, and nothing else. May be nice for piping into
  19. ;      other programmes. - Beware of the header lines, though.
  20.  
  21. ;v1.6    - v1.4a Changes:
  22. ;      Gisbert Selke (all the way from Germany, I think) tweaked the earlier
  23. ;      v1.4 (see v1.4a comments).
  24. ;      I kept his changes (that I hadn't already added in v1.5 myself),
  25. ;      incorporating them into the v1.5 code.  (Of course, just HAD to tweak
  26. ;      his changes as well!)
  27. ;    - Member filenames:
  28. ;      Still considering shifting filenames to the right hand side of
  29. ;      the screen output.  That would permit long (path) filenames to be
  30. ;      displayed/output (with screen wraparound handling the weird,
  31. ;      extra-long ones).  I believe that's why the PKZIP (Katz) author
  32. ;      formatted his display that way.  But the member names on the right
  33. ;      is NOT convenient to me!  Leaving it the original way (member file
  34. ;      names on the left).
  35.  
  36. ;v1.5    Updating for PKZIP v1.01
  37. ;    - Added "implode" to file compression style table
  38. ;      (plus other tests to insure we catch illegal values).
  39. ;    - Adding an "E" before the compression style
  40. ;      (to indicate if file is encrypted) (verbose only).
  41. ;    - Found bug in testing for ZIP member filename paths:
  42. ;      PKZIP uses the "/" char for subdir separator instead of "\".
  43. ;      Fixed.
  44. ;    - Tightened up code for path-testing,
  45. ;      extended the "+" path flag display for verbose as well as
  46. ;      nonverbose displays.
  47. ;      No, we aren't displaying paths yet.
  48. ;    - If using wildcard member option (in verbose mode),
  49. ;      we don't display verbose header until we find a qualifying
  50. ;      file.
  51. ;    - Total and total total displays:  More than one qualifying member
  52. ;      file must be found before the figures are displayed.  (This is
  53. ;      for verbose mode only.)
  54. ;      - Totals (qualifying member files, each ZIP)
  55. ;      - Total totals (qualifying member files, ALL qualifying ZIPs)
  56. ;    - WildCard searches:
  57. ;      Considered not displaying a target .ZIP file's name at ALL
  58. ;      if it has no "eligible" member wildcard contents (to shorten
  59. ;      output to just those .ZIP files (and members) found in a wildcard
  60. ;      search.  However, decided a non-find is valuable information.
  61. ;      At least the .ZIP file name will be output.
  62. ;
  63. ;    - Removed earlier v1.n flags from code
  64. ;
  65. ;    Considering processing file names (vname) to handle "long" names
  66. ;    (e.g., those with paths).
  67. ;    Paths would probably only be displayed in verbose mode
  68. ;    (on a separate line, or maybe to screen right, letting screen
  69. ;    display handle "wraparound").
  70.  
  71. ;v1.4a  Gisbert W.Selke (RECK@DBNUAMA1.BITNET for now): allow '/' as
  72. ;    switch char, too (for them die-hard DOS people like myself).
  73. ;    Output rrrrreal 4-byte CRCs. Add text for 'Imploded'.
  74.  
  75. ;v1.4    Keith Petersen (W8SDZ@WSMR-SIMTEL20.ARMY.MIL) informs me ZDIR
  76. ;    is failing on a lot of ZIP files from local BBS's.  Seems the BBS's
  77. ;    are adding huge comments, and ZDIR can't find the central directory.
  78. ;    Increasing ENDOFS (the amount of ZIP file trailer we read in)
  79. ;    to allow for this.
  80. ;    Keith also suggested the verbose mode as default .. but I don't agree!
  81. ;    If I wanted verbose, I would have used PKZIP -v in the first place!
  82. ;    Also programs like Buerg's ZIPV do that just fine.
  83.  
  84. ;v1.3c  Bug:  I'd written code to handle no cmdline parms at all,
  85. ;    but failed to test it!  Turns out system locks up!
  86. ;    Thanks to FAAR RBBS for alerting me.  Sloppy testing procedures.
  87.  
  88. ;v1.3b  Bug:  Forgot the added "-v" verbose switch as the FIRST PSP
  89. ;    cmdline argument would blow away using our PSP FCB's to get
  90. ;    the parsed member filename.
  91. ;    Using _Args (from KEGELUNX unix-like cmdline parsing)
  92. ;    to handle the -v switch anywhere on cmdline.
  93. ;    (Affects Parse_CmdLine only.)
  94.  
  95. ;v1.3a  23 Mar 89
  96. ; -    Adding file comment display to verbose mode.
  97. ; -    Because of the occasional padding (by XMODEM) of garbage to the
  98. ;    end of a file, we're back to reading a full 256 bytes at the
  99. ;    ZIP file end to find that end structure (149 bytes for the largest
  100. ;    likely ENDDIR structure, plus the padding to the next 128 boundary).
  101. ;    If you don't HAVE any of these files, change ENDOFS back to 149.
  102.  
  103. ;v1.3    22 Mar 89
  104. ; -    Adding verbose display (a -v switch).
  105. ;    Cribbing code from QBARCV3.ASM (my improvements on QBARV2.ASM,
  106. ;    a utility for RBBS ARC/PAK displays).
  107. ;    Usage:  ZDIR -v foob    (yep, -v must be first parm)
  108.  
  109. ;v1.2    21 Mar 89
  110. ; -    Missed the obvious .. the very last structure in a ZIP file
  111. ;    (call it ENDDIR) contains a pointer to the central directory.
  112. ;    Since the only variable length fields in that last structure
  113. ;    are fairly short (zip comments, etc.), it should be MUCH smaller.
  114. ;    We won't need that huge 5Kb SWAG for the initial directory read.
  115. ;    Cutting buffer down to 128 bytes, reading in ENDDIR to get that
  116. ;    central directory pointer, and then going right to central directory.
  117. ;    Since the max possible ZIP file comment (in ENDDIR) is 7FH bytes,
  118. ;    the max possible ENDDIR would be 7FH + 22 (normal structure size)
  119. ;    or 149 bytes (ENDOFS).
  120. ; -    Moved initial cmdline parsing down to code end
  121. ;    (just to clean up things)
  122. ; -    Caught a bug .. failed on a single '*' wildcard cmdline parm.
  123.  
  124. ;v1.1    18 Mar 89
  125. ; -    Added full pathing capabilities for target .ZIP files.
  126. ; -    Added ambiguous member screening (e.g., search FOOB.ZIP
  127. ;    for just *.ASM files).
  128. ; -    Cleaned up the kludgey ADIR wildcard finds with all its
  129. ;    multiple DTAs, etc.
  130. ; -    Still no way to test for member filename paths.
  131.  
  132. ;Original ADIR.EXE fixes:
  133. ; - Fixed bug that never closed any files!
  134. ; - Changed to .COM format, tightened, etc.
  135.  
  136. ;ZIP functional changes:  MANY!  I consider this almost a total rewrite
  137. ;(except for the kludge with wildcard finds from the original ADIR.EXE).
  138.  
  139. ; - Since the filename length is variable (and may include paths),
  140. ;   the handling, formatting and display is significantly different
  141. ;   than in ADIR.
  142. ; - Have to put back the ambiguous member parsing.
  143.  
  144. ;David Kirschbaum
  145. ;Toad Hall
  146.  
  147. FALSE    equ    0
  148. TRUE    equ    NOT FALSE
  149. PLAIN    equ    0            ;            v1.6a
  150. VERBO    equ    0FFh            ;            v1.6a
  151. MONOSYL equ    1            ;            v1.6a
  152. CR    equ    0DH
  153. LF    equ    0AH
  154. STDOUT  equ    1
  155. STDERR  equ    2
  156. ENDOFS  equ    4096        ;enough for largest possible
  157.                 ;ZIP end directory structure.
  158.                 ;(to include XMODEM padding)
  159.                 ;(and hormongous comments!)
  160.                 ;(was 256 in v1.3)
  161.  
  162. Print    macro    name            ; display a field
  163.     mov    dx,offset name
  164.     call    PrintS
  165.     endm
  166.  
  167. ;PKZIP central directory structure:
  168.  
  169. zdirEntry    STRUC
  170. zsig1    db    50H,4BH,01H,02H ;central file header signature  4 bytes
  171.                 ;(0x02014b50)
  172. zVerMade    dw    ?    ;version made by        2 bytes
  173. zVerExt        dw    ?    ;version needed to extract    2 bytes
  174. zBitflag    dw    ?    ;general purpose bit flag    2 bytes
  175. zCmpMeth    dw    ?    ;compression method        2 bytes
  176. zModTime    dw    ?    ;last mod file time        2 bytes
  177. zModDate    dw    ?    ;last mod file date        2 bytes
  178. zCrc32        dw    ?,?    ;crc-32                4 bytes
  179. zCmpSiz        dw    ?,?    ;compressed size        4 bytes
  180. zUncmpSiz    dw    ?,?    ;uncompressed size        4 bytes
  181. zNameLen    dw    ?    ;filename length        2 bytes
  182. zExtraLen    dw    ?    ;extra field length        2 bytes
  183. zFilCmtLen    dw    ?    ;file comment length        2 bytes
  184. zDskNrPtr    dw    ?    ;disk number start        2 bytes
  185. zIntAttr    dw    ?    ;internal file attributes    2 bytes
  186. zExtAttr    dw    ?,?    ;external file attributes    4 bytes
  187. zHdrOfs        dw    ?,?    ;relative offset of local header 4 bytes
  188. zFilename    db    ?    ;filename (variable size)
  189.                 ;extra field (variable size)
  190.                 ;file comment (variable size)
  191. zdirEntry    ENDS
  192.  
  193. ;      End of central dir record:
  194.  
  195. zdirEnd STRUC
  196. zEndSig db    50H,4BH,05H,06H ;end of central dir signature    4 bytes
  197.                 ;(0x06054b50)
  198. zDskNr  dw    ?        ;number of this disk        2 bytes
  199. zDirDsk dw    ?        ;number of the disk with the
  200.                 ;start of the central directory 2 bytes
  201. zDskNrEntry dw  ?        ;total number of entries in
  202.                 ;the central dir on this disk    2 bytes
  203. zDirNrEntry dw  ?        ;total number of entries in
  204.                 ;the central dir        2 bytes
  205. zDirSiz dw    ?,?        ;size of the central directory   4 bytes
  206. zDirOfs dw    ?,?        ;offset of start of central
  207.                 ;directory with respect to
  208.                 ;the starting disk number    4 bytes
  209. zCmtLen dw    ?        ;zipfile comment length        2 bytes
  210. zCmt    db    ?        ;zipfile comment (variable size)
  211. zdirEnd ENDS
  212.  
  213.  
  214. CSEG    segment para public
  215.     assume  CS:CSEG,DS:CSEG
  216.  
  217.     org    5CH        ;FCB #1
  218.     db    ?        ;drive val
  219. fcb1    db    10H dup(?)    ;5DH, FCB #1 first char
  220. fcb2    db    10H dup(?)    ;6DH, FCB #2 first char
  221.     org    80H
  222. nchar    db    ?
  223. params  db    ?
  224.  
  225. ;program entry point
  226.     org    100H
  227.  
  228. Zdir    proc    near
  229.     jmp    Start        ;skip over runtime data
  230.  
  231.  
  232. usage    db    CR,LF,9,9, 'ZDIR version 1.6b, 890928',CR,LF    ; v1.6a
  233.     db    9,9,'David Kirschbaum, Toad Hall/mod GWS',CR,LF    ; v1.6a
  234.     db    9,9, 'USAGE: ',9,'ZDIR zipname[.zip] [afn] [-v|-m]',CR,LF ;v1.6a
  235.     db    9,9,9,'zipname may be ambiguous (wildcarded)',CR,LF
  236.     db    9,9,9,'afn = ambiguous member file name', CR,LF
  237.     db    9,9,9,'-v  = verbose display',CR,LF
  238.     db    9,9,9,'-m  = monosyllabic display',CR,LF    ; v1.6a
  239. USAGELEN equ    $ - usage
  240.  
  241. ziptyp  db    '.ZIP'
  242. ZIPTYPLEN    equ    $ - ziptyp
  243.  
  244. msg1    db    CR,LF, 9, 9, 9, ' ZIP file: '
  245. MSG1LEN equ    $ - msg1
  246. msg2    db    'ZIP file not found',CR,LF
  247. MSG2LEN equ    $ - msg2
  248. msg3    db    'Central directory not found',CR,LF
  249. MSG3LEN equ    $ - msg3
  250. msg4    db    'ZIP is out of alignment or it''s not a ZIP'
  251. crlf    db    CR,LF
  252. MSG4LEN equ    $ - msg4
  253. CRLFLEN equ    $ - crlf
  254.  
  255. ;Keith Petersen suggested this oughtta go .. Sigh ...
  256. ;rivvvt db    'Rivvvvt',CR,LF
  257. ;RVTLEN equ    $ - rivvvt
  258.  
  259.  
  260. handle  dw    0
  261. flag1    db    LOW(TRUE)        ;Find First flag
  262. verbose db    PLAIN            ;verbose display switch        v1.6a
  263.                     ;PLAIN, VERBO, or MONOSYLLABIC  v1.6a
  264. znameptr dw    0            ;point past ZIP target file path
  265. mnameptr dw    0            ;remember .zFilename start
  266. dirNrEntry dw    0            ;central directory file count
  267. dirctr  dw    0            ;for counting down members
  268. pathflag db     ' '            ;is set to '+' if member
  269.                     ; filename includes a path
  270.  
  271. vhdrflag db    FALSE            ;set true when first member
  272.                     ;file is found
  273.  
  274. Comment        ~  Looks like:
  275. +filename.typ 000K / 000K  +filename.typ 000K / 000K  +filename.typ 000K / 000K
  276. Comment ends    ~
  277. blankline db    '         .       K /    K           .       K /    K  '
  278.       db    '         .       K /    K',CR,LF
  279. LINELEN equ    $ - blankline
  280.  
  281. ;    Verbose display data
  282. ;    display lines for verbose
  283. ;v1.5    Adding a "E" (just before Stowage style) if encrypted
  284.  
  285. vhdr    db    CR,LF
  286.  db ' Name            Length E  Stowage     SF  Size now       Date   Time  CRC'  ; v1.6a
  287.  db CR,LF
  288.  db ' ============  ======== = ========   ====  ========  ========= ======  ========' ; v1.6a
  289.  db CR,LF
  290. VHDRLEN equ    $ - vhdr
  291.  
  292. vline    label    byte            ;db    CR,LF
  293. vname    db    15 dup (' ')        ;                v1.6a
  294. vlength db     9 dup (' ')        ; length in archive        v1.6a
  295. vencflag db     3 dup (' ')        ;"E" if encrypted, else blank
  296. vstyle  db    10 dup (' ')        ; compression method (text)
  297. vfactor db    ' xx%  '        ; compression factor (percentage)
  298. vsize    db    10 dup (' ')        ; actual file bytes
  299. vdate    db    'dd '            ; creation date
  300.  vmonth db    'mmm '
  301.  vyear  db    'yy  '
  302.  vtime  db    'hh:mm  '        ; creation time
  303.  vcrc    db    'xxxxxxxx'        ; 32-bit crc in hex        v1.4a
  304.     db    CR,LF
  305. VLINELEN    equ    $ - vline
  306.  
  307.  
  308. ;    final totals line
  309.  
  310. vthdr    db    '*Total    '
  311. vtmbrs    db    5 dup (' ')        ;                v1.6a
  312. vtlen    db    8 dup (' '),'  '
  313.     db    12 dup (' ')
  314.  vtsf    db    '   %  '
  315.  vtsize db    8 dup (' ')
  316.     db    CR,LF            ; for tom
  317. VTHDRLEN    equ    $ - vthdr
  318.  
  319. ;Totals for each ZIP file's members:
  320.  
  321. totcmp  dw    0,0            ; total of file lengths
  322. totuncmp dw    0,0            ; total of file sizes
  323. totmbrs dw    0            ; total number of files
  324. TOTLEN  equ    $ - totcmp
  325.  
  326. ;Totals for ALL ZIP files displayed:
  327.  
  328. ttotcmp dw    0,0            ;total compressed file size
  329. ttotuncmp dw    0,0            ;total uncompressed file size
  330. ttotmbrs dw    0            ;total nr member files
  331.  
  332.  
  333. ;    ZIP compression types:
  334.  
  335. zstyles label    byte
  336.     db    '  Stored'    ;0 - The file is stored (no compression)
  337.     db    '  Shrunk'    ;1 - The file is Shrunk
  338.     db    'Reduced1'    ;2 - Reduced with compression factor 1
  339.     db    'Reduced2'    ;3 - Reduced with       "    "    2
  340.     db    'Reduced3'    ;4 - Reduced with       "    "    3
  341.     db    'Reduced4'    ;5 - Reduced with       "    "    4
  342.     db    'Imploded'    ;6 - The file is imploded
  343.     db    ' Unknown'    ;illegal or unknown value
  344.  
  345. months  db    'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
  346.  
  347.  
  348. Zdir    endp
  349.  
  350. Start    proc    near
  351.  
  352.     call    Parse_CmdLine            ;parse cmdline for
  353.                         ;target filenames
  354.     jb    Jmp_Msg_Term            ;failed
  355.  
  356. ;Let's get to work
  357.  
  358.     call    Find_Zip
  359.     jnc    ZipLup_73            ;found the first one
  360.      mov    dx,offset msg2            ;'Zipfile not found'
  361.      mov    cx,MSG2LEN
  362. Jmp_Msg_Term:
  363.      jmp    Msg_Term            ;display, terminate
  364.  
  365. ZipLup_73:
  366.     call    Read_CentralDir            ;try to read in file trailer
  367.     jnb    Got_Dir                ;found it, DS:BX -> directory
  368.  
  369.      mov    dx,offset msg3            ;'No central directory'
  370.      mov    cx,MSG3LEN
  371.      jmp    short Next1            ;right to next ZIP file
  372.  
  373. Got_Dir:
  374. ;v1.5    We'll only show our verbose header line
  375. ;    when and if we find our first member file.
  376. ;    (Down in Show_FileData)
  377.  
  378.     cmp    verbose,MONOSYL            ;mode switch        v1.6a
  379.     ja    MemberLup            ;verbose, no init    v1.6a
  380.     jb    GD_InitLine            ;plain, use standard    v1.6a
  381.  
  382.     mov    di,offset blankline        ;if monosyllabic, blank    v1.6a
  383.     mov    al,' '                ; that blankline for    v1.6a
  384.     mov    cx,LINELEN-2            ; good            v1.6a
  385.     rep    stosb                ;            v1.6a
  386.  
  387. GD_InitLine:                    ;            v1.6a
  388.      call    Refresh_LineBuff        ;Init formatted display line
  389.  
  390. MemberLup:
  391.     cmp    word ptr [bx],4B50H        ;signature?
  392.     jnz    Bad_Dir                ;nope, bogus
  393.     cmp    word ptr 2[bx],0201H        ;normal entry?
  394.     jnz    Bad_Dir                ;nope, bogus
  395.  
  396. ;Normal directory entry.  Display it.
  397.  
  398.     call    Show_FileData            ;display entry info
  399.     dec    dirctr                ;decr nr entries
  400.     jz    Next_Zip            ;last entry
  401.      jmp    MemberLup            ;next member
  402.  
  403.  
  404. Bad_Dir:
  405.     mov    dx,offset msg4            ;'ZIP is out of alignment'
  406.     mov    cx,MSG4LEN            ; or not a .ZIP file'
  407.     call    Pr_StdOut            ;display msg
  408.  
  409. Next_Zip:
  410.     mov    dx,offset crlf            ;need a new line
  411.     mov    cx,CRLFLEN            ;length
  412.     cmp    verbose,VERBO            ;verbose mode?        v1.6a
  413.     jz    Show_Verbose_Totals        ;yep, maybe display totals
  414.  
  415.     mov    ax,offset LINEBUFF        ;formatted line start
  416.     cmp    di,ax                ;got any file entries?
  417.     jz    Next1                ;nope
  418.      dec    di                ;back up over the two spaces
  419.      dec    di                ; from the last file size
  420.      mov    dx,ax                ;DX'll need it for display
  421.      mov    cx,ax                ;CX will be nr chars
  422.      mov    ax,0A0DH            ;CR/LF
  423.      stosw                    ;stuff
  424.      stosw                    ;2 CR/LFs
  425.      xchg    cx,di                ;CX = end, DI = start
  426.      sub    cx,di                ;end - start = length
  427.      jmp    short Next1
  428.  
  429.  
  430. ;Verbose mode
  431.  
  432. Show_Verbose_Totals:
  433.     cmp    totmbrs,0            ;any totals?
  434.     jz    Next1                ;nope
  435.      call    Format_Totals            ;yep, format
  436.                         ;CX,DX prepared for ...
  437. ;v1.5    If just 1 member, there won't BE a total display!
  438. ;    BP returns from Format_Totals with 0 (1 file) or 1 (more than
  439. ;    1 file)
  440.     or    bp,bp                ;just 1 file?
  441.     jz    Next2                ;yep, no totals
  442.  
  443. Next1:
  444.     call    Pr_StdOut            ;display line seg or CR/LF
  445. Next2:
  446.     call    Find_Zip            ;next .ZIP file
  447.     jnc    ZipLup_73            ;found it, loop
  448.  
  449.     xor    ax,ax                ;handy 0/FALSE
  450.     cmp    al,verbose            ;nonverbose mode?    v1.6a
  451. ;;;;;;; jnc    NoMsg_Term    ;*TEST**TEST*    ;nonverbose, terminate    v1.6a
  452.     jle    NoMsg_Term    ;*TEST**TEST*    ;nonverbose, terminate    v1.6a
  453.                         ;(errorlevel 0)
  454.  
  455. ;    We've been accumulating overall totals.
  456. ;    Now display them.  Gotta move the total totals
  457. ;    into the totals (where Format_Totals expects them).
  458.  
  459. ;v1.5    If we never displayed our verbose header line,
  460. ;    we never found a qualifying member file!
  461. ;    Ergo .. no totals ..
  462.  
  463.     cmp    vhdrflag,al    ;FALSE        ;no header line?
  464.     jz    NoMsg_Term            ;no hdr, so no totals
  465.  
  466.     mov    ax,ttotmbrs            ;accumulated total mbrs
  467.     cmp    ax,dirNrEntry            ;just the one ZIP?
  468.     jz    No_More                ;yep, forget total totals
  469.     cmp    ax,1                ;<= 1?
  470.     jbe    No_More                ;yep, forget the total totals
  471.  
  472.     mov    si,offset ttotcmp        ;move total totals
  473.     mov    di,offset totcmp        ;into totals
  474.     mov    cx,TOTLEN SHR 1            ;nr words
  475.     rep    movsw
  476.  
  477.     call    Pr_CrLf                ;down extra line
  478.     call    Format_Totals            ;format overall totals
  479.     call    Pr_StdOut            ;display them
  480.  
  481. No_More:
  482. ;    Keith Petersen suggested this oughtta go .. Sigh ..
  483. ;    mov    dx,offset rivvvt
  484. ;    mov    cx,RVTLEN            ;fall thru to...
  485.     xor    ax,ax                ;ERRORLEVEL 0
  486.     jmp    short NoMsg_Term
  487.  
  488. Msg_Term:
  489.     push    ax                ;save errorlevel
  490.     call    Pr_StdOut            ;display error msg
  491.     pop    ax
  492. NoMsg_Term:
  493.     mov    ah,4Ch                ;terminate, AL = ERRORLEVEL
  494.     int    21h
  495.  
  496. Start    endp
  497.  
  498.  
  499. ;SUBROUTINE
  500.  
  501. Find_Zip    proc    near
  502.  
  503. ;We reset our DTA to the default PSP DTA each time through.
  504. ;The actual ZIP file open uses another one.
  505.  
  506.     mov    dx,80H                ;use PSP DTA
  507.     mov    ah,1AH                ;set DTA
  508.     int    21h
  509.  
  510.     cmp    flag1,0FFh            ;first time thru?
  511.     jne    FindNext_162            ;nope
  512.  
  513. ;First time through
  514.     not    flag1                ;set to NOT first time thru
  515.  
  516.     mov    dx,offset ziptarget        ;DS:DX -> zip target name
  517.     xor    cx,cx                ;read-only
  518.     mov    ah,4Eh                ;find first
  519.     int    21h
  520.     jmp    short Find_Done
  521.  
  522. FindNext_162:
  523.     mov    ah,4Fh                ;find next
  524.     int    21h
  525. Find_Done:
  526.     jb    FindZ_X                ;failed, return CF set
  527.     call    Move_FileName            ;move name in after path
  528.                         ;to create full name for open
  529.  
  530. ;Found target file.  Announce, set new DTA, open it.
  531.  
  532.     mov    dx,offset msg1            ;'Zip file: '
  533.     mov    cx,MSG1LEN
  534.     call    Pr_StdOut
  535.     Print    ziptarget            ;'filename.zip'
  536.     call    Pr_CrLf                ;new line
  537.  
  538. ;We need a new DTA for the file open/read so we don't blow away
  539. ;the find first/find next stuff in the PSP DTA.
  540.  
  541.     mov    dx,offset dta1BA        ;DS:DX -> new DTA
  542.     mov    ah,1Ah                ;set DTA
  543.     int    21h
  544.  
  545.     mov    dx,offset ziptarget        ;DS:dx -> filename buffer
  546.     mov    ax,3D00H            ;open file, read only
  547.     int    21h
  548.     mov    handle,ax            ;save handle
  549. FindZ_X:
  550.     ret
  551. Find_Zip    endp
  552.  
  553.  
  554. Move_FileName    proc    near
  555.  
  556.     mov    si,9EH                ;FCB #1 +1
  557.     mov    di,znameptr            ;pointer to after path
  558.     mov    cx,13                ;include AsciiZ 0
  559.     rep    movsb
  560.     ret
  561.  
  562. Move_FileName    endp
  563.  
  564.  
  565. ;Reads in file tailer.
  566. ;Then scans for the unique central directory signature.
  567. ;On success:
  568. ;    DS:BX -> central directory structure
  569. ;    readlen = nr bytes actually read
  570. ;    CF clear
  571. ;Else CF set for failure
  572.  
  573. Read_CentralDir proc    near
  574.  
  575.     xor    cx,cx                ;CX:DX = offset from end
  576.     xor    dx,dx                ;to very end
  577.     mov    bx,handle            ;file handle
  578.     mov    ax,4202H            ;move file pointer to end
  579.     int    21H                ;gets file size in DX:AX
  580.     jb    RCD_Close            ;seek failed
  581.  
  582. ;    Increased ENDOFS to read in more of the ZIP file's tail.
  583. ;    Original value wasn't enough to allow for huge comments.
  584.  
  585.     sub    ax,ENDOFS            ;back up psn.lo
  586.     jnb    Read1                ;ok, no problem
  587.      sub    dx,1                ;got a borrow, decr psn.hi
  588.      jnb    Read1                ;no problem
  589.       xor    ax,ax                ;sigh .. small file ..
  590.       xor    dx,dx                ; .. back to very start
  591. Read1:
  592.     mov    cx,dx                ;psn.hi
  593.     mov    dx,ax                ;psn.lo
  594.     mov    ax,4200H            ;now move from start
  595.     int    21H                ;CX:DX point to offset from end
  596.                         ;(big) or to start (small)
  597.     jb    RCD_Close            ;failed, close up
  598.  
  599.     mov    cx,ENDOFS            ;try to read this much
  600.     mov    dx,offset DIRBUFF        ;into our directory buffer
  601.     mov    di,dx                ;DI'll need it in a second
  602.     mov    ah,3FH                ;read from file/device
  603.     int    21H                ;AX=bytes read
  604.     jb    RCD_Close            ;failed, close up
  605.  
  606. ;First scan the end structure to locate the central directory.
  607.  
  608.     call    Sig_Scan            ;find the structure start
  609.                         ;(using bytes read in AX)
  610.     jb    RCD_InvalidDir            ;failed, close and exit
  611.  
  612. ;ES:DI -> end structure start (the signature)
  613. ;While we have the end structure, let's pick up and display
  614. ;any ZIP file comment.
  615.  
  616.     mov    cx,[di].zCmtLen            ;comment length
  617.     jcxz    RCD_NoComment            ;nope, forget it
  618.  
  619.      lea    dx,[di].zCmt            ;DS:DX -> comment
  620.      call    Pr_StdOut            ;display it.
  621.      call    Pr_CrLf                ;and a new line
  622.  
  623. RCD_NoComment:
  624.  
  625. ; Pick up the central directory file pointer (long integer):
  626. ; It's a pointer directly to the central directory start.
  627. ; This will only work for single-disk ZIP files.
  628.  
  629.     mov    si,[di].zDirSiz            ;save central directory size
  630.  
  631.     mov    ax,[di].zDirNrEntry        ;nr central dir entries
  632.     mov    dirNrEntry,ax            ;save it for later
  633.     mov    dirctr,ax            ;two places
  634.  
  635.     mov    dx,[di].zDirOfs            ;central directory offset.lo
  636.     mov    cx,[di].zDirOfs[2]        ;offset.hi
  637.     mov    ax,4200H            ;move file ptrs from start
  638.     int    21H
  639.     jb    RCD_Close            ;seek failed, close and exit
  640.  
  641.     mov    cx,si                ;read central dir size bytes
  642.     mov    dx,offset dirbuff        ;into our directory buffer
  643.     mov    ah,3FH                ;read from file/device
  644.     int    21H
  645.     jb    RCD_Close            ;failed, forget it
  646.  
  647.     mov    di,dx                ;DI -> dir start
  648.     xor    ax,ax                ;return AX=0 for ok
  649.     cmp    word ptr [di],4B50H        ;is it a signature?
  650.     jnz    RCD_InvalidDir            ;nope
  651.      cmp    word ptr 2[di],0201H        ;is it a file entry sig?
  652.      jz    RCD_Close            ;yep, good to go, CF clear
  653.  
  654. RCD_InvalidDir:
  655.     mov    al,11                ;Invalid format
  656.     stc                    ;insure CF set, AL=error
  657. RCD_Close:
  658.     mov    dx,ax                ;save error value (if any)
  659.     pushf                    ;save flags
  660.     mov    ah,3EH                ;close file
  661.     int    21H                ;(BX = file handle)
  662.     popf                    ;restore orig flags
  663.     mov    ax,dx                ;and any error value
  664.     mov    bx,di                ;if it went well,
  665.                         ;DS:BX -> central dir struc
  666.     ret
  667.  
  668.  
  669. ;    Subroutine for Read_CentralDir
  670. ;    Scans backwards through buffer for a directory end signature.
  671. ;    Enter with:
  672. ;    SI = second two signature bytes
  673. ;    DX -> buffer start
  674. ;    AX = bytes read
  675.  
  676. ;We must scan at the byte level (since a member or directory entry
  677. ;can be ANY length).
  678.  
  679. Sig_Scan:
  680.     mov    di,dx                ;ES:DI -> DIRBUFF
  681.                         ;(now a ZIP end dir structure)
  682.     add    di,ax                ;+ bytes read = -> buff end
  683.     mov    cx,ax                ;bytes read for the scan
  684.     inc    cx                ;debug for MAX size
  685.     inc    cx
  686.     mov    ax,4B50H            ;scan for first signature char
  687.                         ;(same for all structures)
  688.     mov    si,0605H            ;2d 2 chars of a directory
  689.                         ;end structure signature
  690.     std                    ;scan from end to start
  691.  
  692. SS_Lup:
  693.     repne    scasb                ;ES:DI -> read buffer
  694.     jnz    No_Sig                ;not found
  695.     jcxz    No_Sig                ;scanned it all
  696.  
  697. ;ES:DI -> the byte BEFORE the 50H signature
  698.  
  699.     cmp    2[di],ah            ;2d signature byte?
  700.     jnz    SS_Lup                ;nope, keep searching
  701.     cmp    3[di],si            ;last 2 signature bytes?
  702.     jnz    SS_Lup                ;nope, keep searching
  703.  
  704.     inc    di                ;bump from that last scasb
  705.                         ;DS:DI -> dir structure
  706.     cld                    ;forwards again to be neat
  707.     clc                    ;CF clear for success
  708.     ret
  709.  
  710. No_Sig:    cld                    ;forward again to be neat
  711.     stc                    ;return CF set for failure
  712.     ret
  713.  
  714. Read_CentralDir endp
  715.  
  716.  
  717. ;SUBROUTINE
  718. ;1 call
  719. Show_FileData    proc    near
  720. ;Added tests for cmdline member name testing
  721.  
  722.     call    Member_Test            ;see if file is eligible
  723.     jb    SF_NextRec            ;nope, forget it
  724.  
  725.     push    bx
  726.  
  727.     xor    ax,ax                ;FALSE
  728.     cmp    al,verbose            ;not verbose?        v1.6a
  729.     jle    SFD_NonVerbose            ;not verbose        v1.6a
  730.  
  731. ;Verbose mode
  732.      cmp    vhdrflag,al    ;FALSE        ;verbose hdr displayed? 
  733.      jnz    SFD_HdrDone            ;yep
  734.  
  735.      not    vhdrflag            ;set to TRUE
  736.      mov    dx,offset vhdr            ;display verbose header 
  737.      mov    cx,VHDRLEN
  738.      call    Pr_StdOut
  739.  
  740. SFD_HdrDone:
  741.      call    Show_Verbose            ;show verbose member display
  742.      jmp    short SFD_BumpPtrs        ;skip nonverbose stuff
  743.  
  744.  
  745. ;Nonverbose mode
  746.  
  747. SFD_NonVerbose:
  748.     call    Stuff_FileName            ;parse, pad at ES:DI
  749.  
  750.     cmp    verbose,MONOSYL            ;monosyllabic output?    v1.6a
  751.     je    SFD_FlushLine            ;shove it out        v1.6a
  752.  
  753.     lea    si,[bx].zCmpSiz            ;compressed size (long int)
  754.     call    Stuff_FileSize            ;to ES:DI
  755.  
  756.     lea    si,[bx].zUncmpSiz        ;uncompressed size
  757.     inc    di                ;adjust line ptr
  758.     call    Stuff_FileSize            ;stuff uncompressed size
  759.                         ; to ES:DI
  760.     cmp    di,offset LINEBUFF + LINELEN    ;hit end?
  761.     jb    SFD_BumpPtrs            ;nope
  762.  
  763. SFD_FlushLine:                    ;            v1.6a
  764.      mov    dx,offset LINEBUFF        ;display the line
  765.      mov    cx,LINELEN            ;length
  766.      call    Pr_StdOut            ;display it
  767.      call    Refresh_LineBuff        ;refresh dynamic variable
  768.  
  769. SFD_BumpPtrs:
  770.     pop    bx
  771.  
  772. SF_NextRec:
  773. ;Now bump our BX pointer to the next entry
  774.     lea    ax,[bx].zFilename        ;from filename start
  775.     add    ax,[bx].zNameLen        ;add in name field length
  776.     add    ax,[bx].zExtraLen        ;and extra field length
  777.     add    ax,[bx].zFilCmtLen        ;and file comment field length
  778.     mov    bx,ax                ;should be next record
  779.     ret
  780.  
  781. Show_FileData    endp
  782.  
  783. ;Tests to see if THIS file is eligible (e.g., meets the ambiguous
  784. ;filename entered on cmdline at startup).
  785. ;  If no such parm, accept it (return CF clear).
  786. ;  If it matches, return CF clear.
  787. ;  If no match, return CF set.
  788.  
  789. ;While we're here, let's Asciify that stupid ZIP directory file name
  790. ;for later tests.
  791.  
  792. Member_Test    proc    near
  793.  
  794.     mov    cx,[bx].zNameLen        ;name length
  795.     jcxz    MT_StepStone            ;zero .. flunk it!    v1.6a
  796.  
  797.     push    di                ;save formatted line pointer
  798.  
  799.     lea    si,[bx].zFilename        ;dirEntry filename
  800.     mov    di,si                ;start
  801.     dec    di                ;back it up one
  802.     mov    ax,di                ;remember new start
  803.     mov    dx,cx                ;save length
  804.  
  805.     rep    movsb                ;move it left 1 char
  806.                         ;(make room for AsciiZ 0)
  807.     mov    byte ptr [di],0            ;AsciiZ the name
  808.  
  809.     mov    cx,dx                ;restore count/length
  810.     mov    si,ax                ;new start (1 char to left)
  811.     mov    dx,ax                ;remember in DX
  812.  
  813.     mov    mnameptr,ax            ;assume no paths    v1.6a
  814.  
  815.     cmp    byte ptr 1[si],':'        ;a drive separator?
  816.     jnz    MT_NoDrive            ;nope
  817.      mov    ax,2
  818.      add    si,ax                ;bump past d:
  819.      sub    cx,ax                ;adjust length counter
  820.      jbe    MT_Fail                ;zeroed out, flunk it!
  821.  
  822. MT_NoDrive:
  823.  
  824. ;Check for directory slashes
  825.     mov    di,si                ;starting point
  826. ;PKZIP uses the '/' character for paths!
  827. ;v1.6b    Wonder why GWS is loading the entire AX?
  828. ;    We're only doing a SCASB for the slash!
  829. ;    Aha!  Because of that je MT01 below .. tricky, tricky...
  830.     mov    ax,' /'                ;scan for PKZIP        v1.6a
  831.                         ; directory slashes
  832. MT_SlashScan:
  833.     repne    scasb
  834.     jnz    MT_NoSlash            ;none
  835.      jcxz    MT_Fail                ;zeroed out, flunk it!
  836.      mov    si,di                ;new starting point
  837.      mov    byte ptr [di-1], '\'        ;old habits never die    v1.6a
  838.      jmp    MT_SlashScan            ;and try again until all gone
  839.  
  840. MT_StepStone:                    ;a stepping stone    v1.6a
  841.      jmp short MT_Fail1            ;Johnny hates kludges    v1.6a
  842.  
  843. MT_NoSlash:
  844.  
  845. ;SI now points at first filename char.
  846.  
  847.     cmp    verbose,MONOSYL            ;are we monosyllabic?    v1.6a
  848.     je    MT_01                ;yes,remember full path    v1.6a
  849.  
  850.     mov    mnameptr,si            ;remember the new address
  851.  
  852. ;v1.5    We'll set a global flag if there was a path.
  853. ;    Simpler than testing if mnameptr = filename start
  854. ;    in both verbose and nonverbose display modes.
  855. ;    DX -> shifted .zFilename
  856. ;    SI -> filename first char
  857.  
  858.     mov    ax,'+ '                ;assume yes (no paths)  
  859.                         ;(AL=' ',AH='+')
  860.     cmp    dx,si                ;name^ = zFileName^?
  861.     jz    MT_1                ;yep, no path
  862. MT_01:                        ;if monosyl, use ' '!    v1.6a
  863.      mov    al,ah    ;'+'            ;set the path flag
  864. MT_1:
  865.     mov    pathflag,al            ;post path flag
  866.  
  867.     cmp    byte ptr pname1,20H        ;empty 2d cmdline parm?
  868.     jz    MT_Done                ;empty, forget the compares
  869.  
  870.     mov    di,offset fcb3            ;ES:DI -> dynamic working FCB
  871.     mov    dx,di                ;save a sec
  872.     xor    ax,ax                ;fill with 0's
  873.     mov    cx,word ptr 6            ;clear old 12-byte filename
  874.     rep    stosw
  875.     mov    di,dx                ;ES:DI -> dynamic working FCB
  876.     mov    ax,2900H + 00001101b        ;parse filename
  877.                         ;(strip leading spaces,
  878.                         ; don't set drive spec,
  879.                         ; change only if valid)
  880.     int    21H
  881.     cmp    al,0FFH                ;failed?
  882.     jz    MT_Fail                ;yep
  883.  
  884. ;We can now compare two expanded file names .. the 2d cmdline parm
  885. ;and the ZIP file member.
  886.  
  887.     inc    di                ;skip leading 0 in filename
  888.     mov    si,offset pname1        ;possible 2d cmdline parm
  889.  
  890. MT_CmpLup:
  891.     lodsb                    ;arg1 char
  892.     or    al,al                ;hit end?
  893.     jz    MT_Done                ;yep, done with a match
  894.     mov    ah,[di]                ;snarf expanded name char
  895.     inc    di                ;bump expanded filename pointer
  896.     cmp    al,'?'                ;wildcard? (no test)
  897.     jz    MT_CmpLup            ;yep, no test
  898.     cmp    al,ah                ;match?
  899.     jz    MT_CmpLup            ;yep, continue
  900.  
  901. MT_Fail:                    ;no match
  902.     pop    di                ;restore formatted line ptr
  903.  
  904. MT_Fail1:
  905.     stc                    ;return CF set
  906. MT_X:    ret
  907.  
  908. MT_Done:
  909.     pop    di
  910.     clc                    ;return CF clear for success
  911.     ret
  912.  
  913. Member_Test    endp
  914.  
  915.  
  916. ;ES:DI -> next position on formatted line
  917. ;zFilename is now AsciiZed
  918. ;mnameptr contains ptr to original or real zFilename start
  919. ;(paths stripped)
  920.  
  921. Stuff_FileName  proc    near
  922.  
  923.     push    di                ;save formatted line ptr
  924.  
  925. ;v1.5    Now using pathflag if target filename has a path
  926.  
  927.     mov    al,pathflag            ;' ' if no paths,
  928.                         ;'+' if paths
  929.     mov    si,mnameptr            ;ptr to filename start  
  930.  
  931.     stosb                    ;stuff space or '+'
  932.     mov    dx,di                ;name start
  933.     add    dx,8                ;bump to the dot
  934.  
  935. SN_Lup:    lodsb
  936.     or    al,al                ;hit AsciiZ 0 yet?
  937.     jz    SN_Done                ;yep
  938.     cmp    verbose,MONOSYL            ;monosyllabic?        v1.6a
  939.     je    SN_NoDot            ;ay,don't mess with '.'    v1.6a
  940.     cmp    al,'.'                ;.typ separator?
  941.     jnz    SN_NoDot            ;nope
  942.      cmp    di,dx                ;where the dot should go?
  943.      jz    SN_NoDot            ;yep, put it there
  944.      mov    di,dx                ; bump to the dot psn
  945. SN_NoDot:
  946.     stosb                    ;stuff in formatted line
  947.     jmp    SN_Lup
  948.  
  949. SN_Done:
  950.     pop    di                ;orig ptr
  951.     add    di,14                ;bump to size psn
  952.     ret
  953.  
  954. Stuff_FileName  endp
  955.  
  956.  
  957. ;SUBROUTINE
  958. ;2 calls
  959.  
  960. Stuff_FileSize  proc    near
  961.     push    bx                ;Preserve BX! (dta ptr)
  962.  
  963.     add    di,3                ;move to number string end
  964.     push    di                ;save it (ptr to last digit)
  965.  
  966.     mov    ax,[si]
  967.     mov    dx,[si+2]
  968.     add    ax,3FFh                ;div 1024 to get Kb
  969.     adc    dx,0
  970.     mov    cl,0Ah
  971.     shr    ax,cl
  972.     mov    cl,6
  973.     shl    dx,cl
  974.     add    ax,dx
  975.  
  976.     mov    si,0Ah
  977. SFS_Lup:
  978.     xor    dx,dx
  979.     div    si
  980.     add    dl,30H                ;asciify
  981.     dec    di                ;back up the digit pointer
  982.     mov    [di],dl                ;stuff digit in buffer
  983.     or    ax,ax                ;number done?
  984.     jnz    SFS_Lup                ;nope
  985.  
  986.     pop    di                ;restore line buffer ptr
  987.     add    di,3                ;bump past ' / ' or ' | '
  988.     pop    bx
  989.     ret
  990.  
  991. Stuff_FileSize  endp
  992.  
  993.  
  994. ;Verbose display functions
  995. ;Format, display single line for each member
  996. ;On success, return:
  997. ; CF clear
  998. ; AL = 0
  999. ;On error, return:
  1000. ; CF set (because of output write fail)
  1001. ; AL = error code
  1002. ;Preserve BX (buffer ptr)
  1003. ;v1.5    Right before the compression style:
  1004. ;       "E" if encrypted
  1005. ;    Else blank
  1006. ;v1.5    Forgot to show our possible "extended" filename with path
  1007. ;    (via a "+" preceding the stripped filename).
  1008. ;    Worked fine for nonverbose mode, now adding for verbose mode.
  1009.  
  1010. sign    db    ' '                ;local variable
  1011. hundred dw    100                ; for computing percentages
  1012.  
  1013.  
  1014. Show_Verbose    proc    near
  1015.  
  1016.     mov    si,mnameptr            ;move real member name
  1017.                         ;(no paths)
  1018.     mov    di,offset vname            ;into formatted line
  1019.     mov    cx,word ptr 14            ;14 spaces in field
  1020.                         ;(added 1 for '+')
  1021.  
  1022.     mov    al,pathflag            ;' ' if no paths,
  1023.                         ;'+' if paths
  1024. ;v1.6a cleaned this up .. nice!
  1025.     stosb                    ;stuff '+'
  1026.     dec    cx                ;adjust pad counter
  1027.                         ;for the stuffed '+'
  1028.  
  1029. SV_Lup:
  1030.     lodsb                    ;snarf char
  1031.     or    al,al                ;AsciiZ ending?
  1032.     jz    SV_5                ;yep
  1033.     stosb
  1034.     loop    SV_Lup
  1035.  
  1036. SV_5:
  1037.     mov    al,ah    ;' '
  1038.     rep    stosb                ;pad with spaces
  1039.  
  1040. ; reduce the size/length to word values
  1041.  
  1042.     mov    si,[bx].zUncmpSiz        ; get uncompressed file size
  1043.     mov    ax,[bx].zUncmpSiz[2]
  1044.  
  1045.     mov    cx,[bx].zCmpSiz            ;compressed size
  1046.     mov    dx,[bx].zCmpSiz[2]
  1047.  
  1048. SVL_51:    or    ax,ax                ; big number?
  1049.     jz    SV_52                ; nope, can use it
  1050.      shr    ax,1                ; yup, divide by two
  1051.      rcr    si,1
  1052.      shr    dx,1
  1053.      rcr    cx,1
  1054.      jmp    SVL_51                ;loop
  1055.  
  1056. SV_52:
  1057.     mov    ax,si                ; low word of actual size
  1058.     mov    sign,' '
  1059.     cmp    ax,cx                ; arc member is larger?
  1060.     jb    SV_520
  1061.      sub    ax,cx                ; amount saved
  1062.      jmp    short SV_521
  1063.  
  1064. SV_520:
  1065.     sub    ax,cx
  1066.     neg    ax
  1067.     mov    sign,'-'
  1068.  
  1069. SV_521:
  1070.     mul    hundred                ; to percentage
  1071.     add    ax,50
  1072.  
  1073. ;v1.5    I'm thinking PK isn't doing this rounding ..
  1074. ;    our percentage figures are sometimes 1% off the PKZIP -v display.
  1075. ;    Close enough for govt work...
  1076.  
  1077.     adc    dx,0                ; round up percent
  1078.     or    si,si                ; empty file?
  1079.     jnz    SV_53
  1080.      mov    ax,100
  1081.      jmp    short SV_54
  1082.  
  1083. SV_53:    div    si
  1084. SV_54:    cmp    ax,100                ; archive fouled?
  1085.     jbe    SV_55
  1086.      sub    ax,ax
  1087. SV_55:
  1088.     mov    di,offset vfactor-2        ;format stowage factor
  1089.     call    Asciify                ;display AX
  1090.  
  1091.     mov    al,sign
  1092.     mov    vfactor,al
  1093.  
  1094. ;v1.5 If encrypted, stuff an 'E', else a blank
  1095.     mov    di,offset vEncFlag        ;space for "E", space
  1096.     mov    ax,' E'                ;assume unencrypted
  1097.                         ;(AL='E',AH=' ')
  1098.     test    byte ptr [bx].zBitFlag,1    ;If 0 bit is set,
  1099.     jnz    SV_56                ;it's encrypted         
  1100.      mov    al,ah    ;' '            ;blank (not encrypted)  
  1101. SV_56:
  1102.     stosw                    ;stuff 'E' or space,
  1103.                         ;trailing space
  1104.                         ;DI -> vstyle field
  1105.  
  1106. ;v1.5    Adding test to insure compression method (0..6) is in legal range
  1107. ;    (e.g., doesn't overrun our compression style table)
  1108.  
  1109.     mov    si,offset zstyles        ;style table start
  1110.     xor    ax,ax                ;clear msb
  1111.     or    ax,[bx].zCmpMeth        ;bring in method
  1112.                         ; of compression
  1113.     jz    SV_58                ;0 -> use table base
  1114.  
  1115.     cmp    al,6                ;max legal
  1116.     jbe    SV_57                ;it's legal             
  1117.      mov    al,7                ;' Unknown'
  1118. SV_57:
  1119.     mov    cl,3                ; eight bytes each entry
  1120.     shl    ax,cl
  1121.  
  1122. SV_58:
  1123.     add    si,ax                ;table base + offset
  1124.                         ;DI already points to vstyle
  1125.  
  1126.     mov    cx,word ptr 4            ;move as words (8 bytes)
  1127.     rep    movsw
  1128.  
  1129.     mov    dx,[bx].zCmpSiz[2]        ;compressed size.hi
  1130.     mov    ax,[bx].zCmpSiz            ;compressed size
  1131.     add    totuncmp,ax            ;accumulate
  1132.     adc    totuncmp[2],dx
  1133.     mov    di,offset vsize            ;format file size
  1134.     call    Asciify_Long
  1135.  
  1136.     mov    dx,[bx].zUncmpSiz[2]        ;uncompressed size.hi
  1137.     mov    ax,[bx].zUncmpSiz        ;uncompressed size.lo
  1138.     add    totcmp,ax            ;accumulate
  1139.     adc    totcmp[2],dx
  1140.     mov    di,offset vlength        ;format file length
  1141.     call    Asciify_Long
  1142.  
  1143.     mov    ax,[bx].zModDate        ; format file date
  1144.     call    GetDate
  1145.  
  1146.     mov    ax,[bx].zModTime        ; format file time
  1147.     call    GetTime
  1148.  
  1149. ;v1.4a  mov    ax,[bx].zCrc32            ; format crc in hex
  1150. ;v1.4a  mov    di,offset vcrc            ;(just low word for now)
  1151. ;v1.4a  call    Cvh
  1152.  
  1153.     mov    ax,[bx].zCrc32            ; format crc.lo in hex
  1154.     mov    di,offset vcrc + 4        ;            v1.4a
  1155.     call    Cvh                ;            v1.4a
  1156.     mov    ax,[bx].zCrc32[2]        ; format crc.hi in hex  v1.4a
  1157.     mov    di,offset vcrc
  1158.     call    Cvh
  1159.  
  1160.     inc    totmbrs                ;bump total file count
  1161.  
  1162.     mov    dx,offset vline            ;display formatted info
  1163.     mov    cx,VLINELEN
  1164.     call    Pr_StdOut
  1165.     ret
  1166.  
  1167. Show_Verbose    endp
  1168.  
  1169.  
  1170. ;Formats, displays verbose totals
  1171.  
  1172. Format_Totals    proc    near
  1173.  
  1174.     mov    ax,totmbrs            ;total members
  1175.     add    ttotmbrs,ax            ;accumulate
  1176.  
  1177. ;v1.5    Don't display totals for this ZIP file's members
  1178. ;    unless there's more than 1.
  1179.  
  1180.     xor    bp,bp                ;use BP for a flag
  1181.                         ;(undisturbed by Asciify)
  1182.                         ;(0 = only 1 file)
  1183.  
  1184.     cmp    ax,1                ;just one?
  1185.     jbe    FT_1                ;yep, no Asciify
  1186.      inc    bp                ;flag more than 1 file  
  1187.      mov    di,offset vtmbrs-2        ;format total members
  1188.      call    Asciify
  1189.  
  1190. FT_1:    mov    dx,totcmp[2]            ;total compressed file size
  1191.     mov    ax,totcmp
  1192.     add    ttotcmp,ax            ;accumulate total totals
  1193.     adc    ttotcmp[2],dx
  1194.  
  1195.     or    bp,bp                ;just 1 file?
  1196.     jz    FT_2                ;yep, no Asciify
  1197.      mov    di,offset vtlen            ;format total compressed file
  1198.                         ;size
  1199.      call    Asciify_Long
  1200. FT_2:
  1201.     mov    dx,totuncmp[2]            ; total uncompressed file size
  1202.     mov    ax,totuncmp
  1203.     add    ttotuncmp,ax            ;accumulate total totals
  1204.     adc    ttotuncmp[2],dx
  1205.     or    bp,bp                ;just 1 file?
  1206.     jz    FT_9                ;yep, no Asciify
  1207.                         ;no fancy computations  
  1208.  
  1209.     mov    di,offset vtsize        ;format total uncompressed
  1210.                         ;file size
  1211.     call    Asciify_Long
  1212.  
  1213. ; reduce the total size/length to word values
  1214.  
  1215.     mov    si,totcmp            ; get compressed file size
  1216.     mov    ax,totcmp[2]
  1217.     mov    cx,totuncmp            ; uncompressed file size
  1218.     mov    dx,totuncmp[2]
  1219.  
  1220. FTDiv:    or    ax,ax                ; big number?
  1221.     jz    FT_4                ; nope, can use it
  1222.      shr    ax,1                ; yup, divide by two
  1223.      rcr    si,1
  1224.      shr    dx,1
  1225.      rcr    cx,1
  1226.      jmp    short FTDiv
  1227.  
  1228. FT_4:
  1229.     mov    ax,si
  1230.     mov    sign,' '            ;whata kludge
  1231.     cmp    ax,cx                ;compressed > uncompressed?
  1232.     jb    FT_5                ;yep
  1233.      sub    ax,cx                ;amount saved
  1234.      jmp    short FT_6
  1235.  
  1236. FT_5:    sub    ax,cx
  1237.     neg    ax
  1238.     mov    sign,'-'
  1239.  
  1240. FT_6:    mul    hundred                ; to percentage
  1241.     add    ax,50
  1242.     adc    dx,0                ; round up percent
  1243.     or    si,si                ; empty file?
  1244.     jnz    FT_7
  1245.      mov    ax,100
  1246.      jmp    short FT_8
  1247.  
  1248. FT_7:    div    si
  1249. FT_8:    mov    di,offset vtsf-2        ;format stowage factor
  1250.     call    Asciify                ;AX
  1251.  
  1252.     mov    al,sign
  1253.     mov    vtsf,al
  1254.  
  1255. FT_9:
  1256.     mov    di,offset totcmp        ;starting at totcmp
  1257.     mov    cx,TOTLEN/2            ;length of totals to clear
  1258.                         ; (words)
  1259.     xor    ax,ax                ;handy 0
  1260.     rep    stosw
  1261.  
  1262.     or    bp,bp                ;just 1 file?
  1263.     jz    FT_X                ;yep, exit
  1264.  
  1265.      mov    dx,offset vthdr            ;prepare to display totals
  1266.      mov    cx,VTHDRLEN            ;msg length
  1267. FT_X:
  1268.     ret                    ;to display
  1269.  
  1270. Format_Totals    endp
  1271.  
  1272.  
  1273. ;    format the time (in AX)
  1274.  
  1275. time    record  hour:5,min:6,sec:5        ;packed time
  1276.  
  1277. GetTime proc    near                ;format the date
  1278.     mov    di,offset vtime
  1279.     or    ax,ax                ;it is zero?
  1280.     jz    GotTime
  1281.  
  1282.     push    ax                ;save date
  1283.     and    ax,mask hour            ;get hour part
  1284.     mov    cl,hour                ;bits to shift
  1285.     shr    ax,cl
  1286.     call    Cnvrt1
  1287.     stosw
  1288.     mov    al,':'
  1289.     stosb
  1290.  
  1291. GT3:    pop    ax                ;get the time back
  1292.     and    ax,mask min            ;get min part
  1293.     mov    cl,min                ;bits to shift
  1294.     call    Cnvrt
  1295.     stosw
  1296. GotTime:ret
  1297.  
  1298. GetTime endp
  1299.  
  1300.  
  1301. Cnvrt2  proc    near                ;convert to ascii
  1302.  
  1303.     call    Cnvrt
  1304.     cmp    al,'0'                ;suppress leading zero
  1305.     jne    Cnvrtd
  1306.      mov    al,' '
  1307.      ret
  1308.  
  1309. Cnvrt:    shr    ax,cl
  1310. Cnvrt1:    aam                    ;make al into bcd
  1311.     or    ax,'00'                ; and to ascii
  1312.     xchg    al,ah
  1313. Cnvrtd:    ret
  1314. Cnvrt2  endp
  1315.  
  1316.     page
  1317.  
  1318. ;    format the date (in AX)
  1319.  
  1320. date    record  yr:7,mo:4,dy:5            ;packed date
  1321.  
  1322. GetDate proc    near                ;format the date
  1323.     or    ax,ax                ;is it zero?
  1324.     jz    GotDate
  1325.  
  1326.     push    bx                ;preserve BX (buff ptr)
  1327.  
  1328.     push    ax                ;save date
  1329.     and    ax,mask yr            ;get year part
  1330.     mov    cl,yr                ;bits to shift
  1331.     call    Cnvrt
  1332.     mov    di,offset vyear
  1333.     or    al,'8'                ;adjust for base year
  1334.     stosw
  1335.  
  1336.     pop    bx                ;get the date back
  1337.     push    bx                ;save it
  1338.     and    bx,mask mo            ;get month part
  1339.     mov    cl,mo                ;bits to shift
  1340.     shr    bx,cl
  1341.     add    bx,bx                ; form month table index
  1342.     add    bx,bx
  1343.     lea    si,word ptr months-4[bx]
  1344.     mov    cx,word ptr 3
  1345.     mov    di,offset vmonth
  1346.     rep    movsb
  1347.  
  1348.     pop    ax                ;get the date back
  1349.     and    ax,mask dy            ;get day part
  1350.     mov    cl,dy                ;bits to shift
  1351.     call    Cnvrt
  1352.     mov    di,offset vdate
  1353.     stosw
  1354.  
  1355.     pop    bx                ;restore buff ptr
  1356. GotDate:ret
  1357.  
  1358. GetDate endp
  1359.  
  1360.  
  1361. ;A severely hacked single/double precision number conversion function.
  1362. ;Originally from JMODEM, but severely hacked by Toad Hall.
  1363. ;ES:DI -> string
  1364. ;Destroys everything almost.
  1365.  
  1366. ;Enter here if integer in AX
  1367. Asciify proc    near
  1368.  
  1369.     push    bx                ;save buff ptr
  1370.  
  1371.     xor    dx,dx                ; clear fake long.hi
  1372.     mov    si,ax                ;move integer into SI
  1373.     xor    ah,ah                ;clear msb (flag)
  1374.     jmp    short Ascii_Ax            ;jump into the code
  1375.  
  1376. ;Enter here if long integer in DX:AX.
  1377. Asciify_Long:
  1378.  
  1379.     push    bx                ;save buff ptr
  1380.  
  1381.     mov    si,ax                ;move long.lo into SI
  1382.     xor    ah,ah                ;clear msb (flag)
  1383.  
  1384. Comment        ~
  1385. Taking out the extremely high numbers to reduce column width.
  1386.  
  1387.     MOV    CX,3B9AH            ; Get billions
  1388.     MOV    BX,0CA00H
  1389.     CALL    Subtr                ; Subtract them out
  1390.  
  1391.     MOV    CX,05F5H            ; Get hundred-millions
  1392.     MOV    BX,0E100H
  1393.     CALL    Subtr                ; Subtract them out
  1394. Comment ends    ~
  1395.  
  1396.     and    dx,4FFH                ;seems likely
  1397.     MOV    CX,word ptr 0098H        ; Get ten-millions
  1398.     MOV    BX,9680H
  1399.     CALL    Subtr                ; Subtract them out
  1400.  
  1401.     MOV    CX,word ptr 000FH        ; Get millions
  1402.     MOV    BX,4240H
  1403.     CALL    Subtr                ; Subtract them out
  1404.  
  1405.     MOV    CX,word ptr 1            ; Get hundred-thousands
  1406.     MOV    BX,86A0H
  1407.     CALL    Subtr                ; Subtract them out
  1408.  
  1409. Ascii_Ax:
  1410.     xor    cx,cx                ; Get ten-thousands
  1411.     MOV    BX,2710H
  1412.     CALL    Subtr                ; Subtract them out
  1413.     MOV    BX,03E8H
  1414.     CALL    Subtr                ; Subtract them out
  1415.  
  1416.     MOV    BX,word ptr 0064H
  1417.     CALL    Subtr                ; Subtract them out
  1418.     MOV    BX,word ptr 10
  1419.     CALL    Subtr                ; Subtract them out
  1420.     mov    ax,si                ;residual in SI
  1421.     add    AL,'0'                ; Add bias to residual
  1422.     stosb                    ; Put in the string
  1423.  
  1424.     pop    bx                ;restore buff ptr
  1425.     RET
  1426.  
  1427. ;Common subroutine for Asciify
  1428.  
  1429. Subtr:    mov    al,'0'-1
  1430.  
  1431. Subtr1:    INC    al                ; Bump the digit character
  1432.     SUB    si,BX                ; Dword subtraction
  1433.     SBB    DX,CX
  1434.     JNB    Subtr1                ; Continue until a carry
  1435.  
  1436.     ADD    si,BX                ; One too many, add back
  1437.     ADC    DX,CX                ;   and the remainder
  1438.  
  1439.     cmp    al,'0'
  1440.     jnz    Subtr2                ;nope, turn off leading flag,
  1441.                         ; stuff
  1442.      or    ah,ah                ;no more leading spaces?
  1443.      jnz    Sub_Stuff            ;right, stuff the '0'
  1444.       mov    al,' '                ;make it neat
  1445.                         ; with leading spaces
  1446. Sub_Stuff:
  1447.     stosb                    ;stuff the char
  1448.     RET
  1449.  
  1450. Subtr2:    inc    ah                ;turn off leading space flag
  1451.     stosb
  1452.     ret
  1453.  
  1454. Asciify ENDP
  1455.  
  1456.  
  1457. ;Convert 16-bit binary word in AX
  1458. ;to hex ASCII string at ES:DI
  1459. ;(Protect BX, directory array pointer)
  1460.  
  1461. hexchar db    '0123456789ABCDEF'
  1462.  
  1463. Cvh    proc    near
  1464.  
  1465.     push    bx                ;save buff ptr
  1466.  
  1467.     mov    si,offset hexchar        ;for faster access
  1468.     mov    dx,ax                ; save 16-bits
  1469.  
  1470.     mov    bl,dh                ; third nibble
  1471.     xor    bh,bh                ;clear msb
  1472.     mov    cx,0F04H            ;CL=4 for shifting,
  1473.                         ;CH=0FH for masking
  1474.     shr    bl,cl
  1475.     mov    al,[si][bx]            ;snarf hex char
  1476.     stosb
  1477.  
  1478.     mov    bl,dh                ; last nibble
  1479.     and    bl,ch    ;0fh
  1480.     mov    al,[si][bx]            ;snarf hex char
  1481.     stosb
  1482.  
  1483.     mov    bl,dl                ; first nibble
  1484.     shr    bl,cl                ; isolate (CL still 4)
  1485.     mov    al,[si][bx]            ;snarf hex char
  1486.     stosb
  1487.  
  1488.     mov    bl,dl                ; second nibble
  1489.     and    bl,ch    ;0fh            ; isolate
  1490.     mov    al,[si][bx]            ;snarf hex char
  1491.     stosb
  1492.  
  1493.     pop    bx                ;restore buff ptr
  1494.     ret
  1495.  
  1496. Cvh    endp
  1497.  
  1498.  
  1499. ;SUBROUTINE
  1500.  
  1501. Pr_CrLf proc    near
  1502.     mov    dx,offset crlf
  1503.     mov    cx,CRLFLEN            ;fall through to ...
  1504.  
  1505. Pr_CrLf endp
  1506.  
  1507. Pr_StdOut    proc    near
  1508.  
  1509.     push    bx                ;preserve bx
  1510.     mov    bx,STDOUT
  1511.     mov    ah,40H                ;write
  1512.     int    21H
  1513.     pop    bx
  1514.     ret
  1515.  
  1516. Pr_StdOut    endp
  1517.  
  1518.  
  1519. ;Print null-terminated (AsciiZ) string like int 21h function 9
  1520. ;Enter with DS:DX -> AsciiZ string
  1521. ;Destroys AX
  1522. ;On success, return:
  1523. ; CF clear
  1524. ; AL = 0
  1525. ;On failure (StdOut write fail), return:
  1526. ; CF set
  1527. ; AL = error
  1528.  
  1529. PrintS  proc    near
  1530.  
  1531.     mov    cx,0FFFFH            ;max scan
  1532.     xor    al,al                ;handy 0
  1533.     mov    di,dx                ;string start
  1534.     repne    scasb                ;find the terminator
  1535.     inc    cx                ;adjust
  1536.     not    cx                ;CX=length
  1537.  
  1538.     call    Pr_StdOut            ;display to StdOut
  1539.  
  1540.     ret
  1541.  
  1542. PrintS  endp
  1543.  
  1544.  
  1545. ;Reinit our nonverbose formatted display line
  1546. ;Returne ES:DI -> formatted line start
  1547. Refresh_LineBuff    proc    near
  1548.  
  1549.     mov    si,offset blankline        ;formatted display line
  1550.     mov    ax,offset LINEBUFF        ;dynamic data area
  1551.     mov    di,ax                ;move to ...
  1552.     mov    cx,LINELEN            ;length
  1553.     rep    movsb
  1554.     mov    di,ax                ;ES:DI -> formatted line start
  1555.     ret
  1556.  
  1557. Refresh_LineBuff    endp
  1558.  
  1559.  
  1560. ;Parses cmdline for target files.
  1561. ;If failure:
  1562. ;  Returns CF set,
  1563. ;  AL = ERRORLEVEL,
  1564. ;  DX -> error msg
  1565. ;Adding command line switch ('-v') parsing.
  1566. ;And '-m', too. Also accept '/' as switch char.                v1.6a
  1567. ;And fixing the bug.
  1568.  
  1569. Parse_CmdLine    proc    near
  1570.  
  1571.     call    _Args                ;parse cmdline
  1572.                         ;returns AX = argc
  1573.     or    ax,ax                ;any argc?
  1574.     jnz    Got_Parm            ;yep
  1575.  
  1576. Cmd_Err:
  1577.      mov    dx,offset usage            ;intro, usage
  1578.      mov    cx,USAGELEN            ;total length
  1579.      mov    al,1                ;errorlevel 1
  1580.      stc                    ;CF set
  1581.      ret                    ;for a jmp to Msg_Term
  1582.  
  1583. Got_Parm:
  1584.     mov    cx,ax                ;argc
  1585.  
  1586. ;See if any of the argv's are our '-v' verbose switch.
  1587. ;Or '-m'. Or '/v'. Or '/m'. Or. Or. Or.                    v1.6a
  1588. ;If so, turn switch on, clear that argv.
  1589.  
  1590.     cmp    cx,word ptr 1            ;just 1 arg?        v1.6b
  1591.     jz    Chk_ZipName            ;yep, can't be any switches
  1592.  
  1593.     mov    bx,offset argv[2]        ;start with ^argv(1)
  1594.  
  1595. Chk_VSwitch:
  1596.     mov    si,[bx]                ;argv^(1)
  1597.     cmp    byte ptr 2[si],0        ;arg longer than 2 chars?v1.6a
  1598.     jnz    Chk_VRelup            ;yes, can't be switch   v1.6a
  1599.     mov    ax,[si]                ;snarf possible -V parm 
  1600.     cmp    al,'-'                ;is first(!) char '-'?  v1.6a
  1601.     je    Found_Some_Switch        ;yes, check which    v1.6a
  1602.     cmp    al,'/'                ;is first(!) char '/'?  v1.6a
  1603.     jne    Chk_VRelup            ;no, cant' be switch    v1.6a
  1604.  
  1605. Found_Some_Switch:                ;            v1.6a
  1606.     or    ah,32                ;force to lowercase
  1607.     mov    al,VERBO            ;assume it's 'v'        v1.6a
  1608.     cmp    ah,'v'                ;'v'?            v1.6a
  1609.     jz    Found_Switch            ;yep            v1.6a
  1610.     cmp    ah,'m'                ;'m'?            v1.6a
  1611.     jnz    Chk_VRelup            ;nope
  1612.     mov    al,MONOSYL            ;hah-it's monosyllabic  v1.6a
  1613.  
  1614. Found_Switch:                    ;            v1.6a
  1615.      cmp    byte ptr 2[si],0        ;Just the '-v'?
  1616.      jnz    Chk_VRelup            ;nope, must be a name
  1617.       mov    verbose,al            ;got switch,set verbose    v1.6a
  1618.       mov    byte ptr [si],0            ;clear this argv
  1619.       cmp    cx,argc                ;first argc?
  1620.       jnz    Chk_V_NoShift            ;nope
  1621.        inc  argc                ; .. sigh .. readjust
  1622.        call _Shift                ;yep, move other args down one
  1623.                         ;(will decr argc again)
  1624. Chk_V_NoShift:
  1625.        dec  argc                ;final decr to eliminate it
  1626.        jmp  short Chk_ZipName        ;done
  1627.  
  1628. Chk_VRelup:
  1629.       add    bx,2                ;next argv^
  1630.       loop  Chk_VSwitch            ;check all args
  1631.  
  1632. ;If argv(1) was the '-v' switch,
  1633. ;or that other one,                            v1.6a
  1634. ;that argv has been cleared via the _Shift call.
  1635. ;The target zip file name HAS to be argv(1)!
  1636.  
  1637. Chk_ZipName:
  1638.  
  1639.     mov    cx,argc                ;argc arg counter
  1640.     jcxz    Cmd_Err                ;he only had a switch!
  1641.  
  1642.     mov    bx,offset argv[2]        ;^argv(1)
  1643.     mov    si,[bx]                ;argv^(argc)
  1644.     call    Parse_MoveZipName        ;handle the zip name
  1645.     call    _Shift                ;move argv's down one
  1646.  
  1647. ;Check for member testing (2d or 3d argv).
  1648. ;We make the call even if argc = 0 (to clear a buffer)
  1649.  
  1650. Chk_MbrName:
  1651.     call    Parse_MoveMbrName        ;handle the member name
  1652.  
  1653. Parse_Done:
  1654.     clc
  1655.     ret
  1656.  
  1657. Parse_CmdLine    endp
  1658.  
  1659. ;Cmdline parsing subroutine
  1660. ;Moves argv into our targetfile buffer,
  1661. ;picks up a pointer to past the paths (if any)
  1662. ;SI -> argv
  1663.  
  1664. Parse_MoveZipName    proc    near
  1665.  
  1666.     push    si                ;save SI
  1667.  
  1668.     mov    bx,offset ziptarget        ;full zip target filename
  1669.  
  1670.     mov    di,bx
  1671.     mov    cx,64                ;clear ziptarget
  1672.     xor    ax,ax
  1673.     rep    stosw
  1674.  
  1675.     mov    di,bx                ;DI -> ziptarget
  1676.  
  1677. Move_ZipName:
  1678.     lodsb                    ;snarf cmdline char
  1679.     or    al,al                ;AsciiZ terminator?
  1680.     jz    Parse_Zip_Type            ;yep
  1681.      stosb                    ;stuff
  1682.      jmp    Move_ZipName
  1683.  
  1684.  
  1685. Parse_Zip_Type:
  1686.  
  1687. ;DI -> last ziptarget's real char +1
  1688.  
  1689.     mov    dx,di                ;end, last char +1
  1690.     sub    dx,bx                ;end - start = length
  1691.  
  1692.     mov    di,bx                ;back to start
  1693.     mov    cx,dx                ;counter for a scan
  1694.     mov    al,'.'
  1695.     repne    scasb                ;find a .TYP separator
  1696.  
  1697. ;DI -> char after '.' or actual filename end
  1698.     jnz    No_Type
  1699.      dec    di                ;back up to the '.'
  1700. No_Type:
  1701.     mov    si,offset ziptyp        ;assume need full '.ZIP'
  1702.     movsw                    ;copy .ZIP in
  1703.     movsw                    ;(4 chars)
  1704.  
  1705.     mov    dx,di                ;end
  1706.     sub    dx,bx                ;end - start = length
  1707.  
  1708.     dec    di                ;adjust from last movsb
  1709.     std                    ;backwards
  1710.  
  1711.     mov    si,di                ;SI -> ziptarget last char
  1712.  
  1713. ;BX = ziptarget start
  1714. ;SI -> ziptarget lastchar
  1715. ;DX = ziptarget length
  1716. ;DI -> ziptarget lastchar
  1717.  
  1718. ;Now find any path separators in ziptarget
  1719.  
  1720.     mov    cx,dx                ;scan length
  1721.     mov    al,'\'                ;subdir dividers
  1722.     repne    scasb                ;scan till we hit one
  1723.     jz    Zip_GotPath            ;DI -> char before the '\'
  1724.  
  1725.     mov    di,si                ;back to last char
  1726.     mov    cx,dx                ;scan length
  1727.     mov    al,':'                ;how about just drive?
  1728.     repne    scasb
  1729.     jnz    Zip_NoPath            ;nope, DI -> ziptarget-1
  1730.                         ;skip the extra inc
  1731. Zip_GotPath:
  1732.     inc    di                ;bump to '\' or ':'
  1733. Zip_NoPath:
  1734.     inc    di                ;and past it to filename's char
  1735.     cld                    ;forward again
  1736.     mov    znameptr,di            ;points to start of
  1737.                         ;true filename (beyond path)
  1738.                         ;for later appending Find Next
  1739.                         ;filenames to path
  1740.     pop    si                ;restore
  1741.     ret
  1742.  
  1743. Parse_MoveZipName    endp
  1744.  
  1745. ;Cmdline parsing subroutine
  1746. ;Has DOS parse the member name (could be wildcards).
  1747. ;Moves that parsed name into runtime buffer.
  1748. ;Enters with SI -> AsciiZ member name.
  1749.  
  1750. Parse_MoveMbrName    proc    near
  1751.  
  1752.     mov    di,offset pname1
  1753.     mov    cx,6                ;12 bytes long
  1754.     mov    ax,2020H
  1755.     rep    stosw                ;clear with spaces
  1756.  
  1757.     mov    cx,argc                ;argc counter
  1758.     jcxz    Parse_MbrDone            ;all done, no member
  1759.  
  1760.     mov    bx,offset argv[2]        ;it's now ^argv(2)
  1761.     mov    si,[bx]                ;argv^(argc)
  1762.  
  1763.     mov    di,offset fcb3
  1764.     mov    ax,2900H + 00001100b        ;parse filename
  1765.                         ;(no leading spaces,
  1766.                         ; don't set drive spec,
  1767.                         ; change only if valid)
  1768.     int    21H
  1769.     cmp    al,0FFH                ;failed?
  1770.     jz    Parse_MbrDone            ;yep
  1771.  
  1772.      mov    si,di                ;0 preceding parsed name
  1773.      inc    si                ;bump past 0
  1774.      mov    di,offset pname1        ;dynamic variable space
  1775.      mov    cx,6                ;11 filename chars + AsciiZ 0
  1776.      rep    movsw
  1777.  
  1778. Parse_MbrDone:
  1779.     ret
  1780.  
  1781. Parse_MoveMbrName    endp
  1782.  
  1783. ;---- args.asm ----------------------------------------------------------
  1784. ;from KEGELUNX.ARC Unix-like utils.
  1785. ;
  1786. ; Args parses the command line into a unix-style parameter array.
  1787. ; CALL _ARGS to have it parse the cmdline.
  1788. ; Argc and Argv are just as in C; argc = # of params on cmd line,
  1789. ; argv is an array of pointers to strings (null terminated, of course).
  1790. ; Because MS-DOS doesn't pass us the name used to invoke the program,
  1791. ; argv[0] always points to a null string.
  1792. ; _Shift updates argc.
  1793. ;
  1794. ;--------------------------------------------------------------------------
  1795.  
  1796. ; Maximum number of parameters
  1797. MAXPARMS    equ    4
  1798.  
  1799. _Args    proc    near
  1800.  
  1801. ; initialize
  1802.     cld                ; clear decrement mode
  1803.     mov    bx, 2            ; argc = 0 (will sub 2 from bx at end)
  1804.     mov    argv[0], offset null    ; prog name unknown; set to null.
  1805.     mov    si,offset PARAMS    ; i = 0
  1806.     mov    cl,nchar        ; cx = # of chars in command line
  1807.     xor    ch,ch
  1808.     jcxz    Args_Done        ; no arg chars -> we're done.
  1809.  
  1810.     mov    di,offset argbuff    ;big arg buffer
  1811.  
  1812. ; Move arguments out of default DTA.
  1813.     push    cx
  1814.     push    di
  1815.     rep    movsb
  1816.     pop    si
  1817.     pop    cx
  1818.  
  1819. ; Big loop- find arguments...
  1820.     mov    ah,20H            ;handy space
  1821. ParmL:
  1822.  
  1823. ; Little loop #1: strip leading blanks from argument.
  1824. ; while (i<NCHAR && params[i] = ' ') do i++;
  1825. StripL:    lodsb                ; al = [si++]
  1826.     cmp    al,ah            ; space?
  1827.     loopz    StripL            ; if so, keep skipping.
  1828.     jne    Args_GotOne        ; If we found a nonblank,
  1829.                     ; skip zero test.
  1830.     jcxz    Args_Done        ; found no unblank chars -> we're done.
  1831.  
  1832. Args_GotOne:
  1833.     dec    si            ; bump SI back to start of nonblank.
  1834.     inc    cx
  1835.     mov    argv[bx],si        ; save pointer to this string
  1836.  
  1837. ; Little loop #2: skip nonblank chars.
  1838. ; while (i<NCHAR && params[i] <> ' ') do i++;
  1839.  
  1840. SkipL:    lodsb
  1841.     cmp    al,ah
  1842.     loopnz  SkipL
  1843.     jz    Oky
  1844.                     ; Last char of line was not blank.
  1845.      inc    si            ; make next statement put null
  1846.                     ; AFTER arg.
  1847. Oky:
  1848.     mov    byte ptr [si][-1], 0    ; put null at end of arg
  1849.     add    bx,2            ; argc++
  1850.  
  1851.     jcxz    Args_Done        ; if we ran off end of cmdline,
  1852.                     ; no more args.
  1853.  
  1854.     cmp    bx, MAXPARMS*2
  1855.     jb    ParmL            ; loop if argc < MAXPARMS.
  1856.  
  1857. Args_Done:
  1858. ; All done finding parms; now share argc with caller.
  1859.     mov    ax,bx
  1860.     sub    ax, 2
  1861.     shr    ax, 1
  1862.     mov    argc,ax            ;save argc
  1863.     or    ax,ax            ;no args at all?
  1864.     jz    Args_X            ;yep, leave now
  1865.  
  1866. ;While we're here, let's uppercase all the args
  1867.  
  1868.     mov    cx,ax            ;argc loop counter
  1869.     mov    dl,20H            ;handy constant for uppercasing
  1870.     mov    ah,'a'            ;and for testing
  1871.     mov    bx,offset argv[2]    ;^argv(1)
  1872.  
  1873. Args_UpLoop:
  1874.     mov    si,[bx]            ;argv^(argc)
  1875.     dec    si            ;prep for upcoming...
  1876. Argv_UpLoop:
  1877.     inc    si
  1878.     mov    al,[si]            ;snarf char
  1879.     or    al,al            ;argv^(argc) end?
  1880.     jz    Args_Relup        ;yep, bump argc
  1881.     cmp    al,ah    ;'a'        ;lowercase?
  1882.     jb    Argv_UpLoop        ;nope
  1883.      sub    [si],dl            ;uppercase
  1884.      jmp    Argv_UpLoop        ;next char
  1885.  
  1886. Args_Relup:
  1887.     add    bx,2            ;next argv^
  1888.     loop    Args_UpLoop
  1889.  
  1890.     mov    ax,argc            ;return argc
  1891. Args_X:
  1892.     ret
  1893.  
  1894. _Args    endp
  1895.  
  1896. ;---- _Shift: --------------------------------------------
  1897. ; Shifts %2 to %1, %3 to %2, etc.  Leaves %0 alone.
  1898. ; Works by shuffling argv[*].
  1899.  
  1900. _Shift  proc    near
  1901.     cld
  1902.     mov    si, offset argv[4]
  1903.     mov    di, offset argv[2]
  1904.     mov    cx, MAXPARMS
  1905.     rep    movsw
  1906.     dec    argc
  1907.     ret
  1908. _Shift  endp
  1909.  
  1910.  
  1911. ;---- parameter count, array ----------------
  1912. ; Pointers to up to MAXPARMS parameter strings are held here.
  1913.  
  1914. null    dw    0            ; the null string
  1915. argc    dw    ?
  1916. argv    dw    MAXPARMS dup (null)
  1917.  
  1918.  
  1919. ;Dynamic variables start here.
  1920. ;Not REAL big .. we could calculate them and release unneeded memory ..
  1921. ;but who needs it?  This ain't TSR, and the normal 64Kb required for
  1922. ;a .COM program shouldn't stress anyone's system capacity.
  1923.  
  1924. dta1BA        equ    $            ;alternate DTA
  1925. ziptarget    equ    dta1BA + 42        ;up to 128 bytes
  1926. pname1        equ    ziptarget + 128        ;11-byte FCB filename + 0
  1927. fcb3        equ    pname1 + 14        ;full 44-byte FCB
  1928.  
  1929. Comment        ~ Looks like:
  1930. +filename.typ 000K / 000K  +filename.typ 000K / 000K  +filename.typ 000K / 000K
  1931. Comment ends    ~
  1932. argbuff        equ    fcb3 + 44        ;cmdline parsing buff
  1933. linebuff    equ    argbuff            ;82 chars long
  1934. dirbuff        equ    linebuff + 82        ;ENDOFS bytes long
  1935.  
  1936.  
  1937. CSEG    ends
  1938.     end    Zdir
  1939.