home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / extra / nyenhuis3.arc / MSSFIL.ASM < prev    next >
Assembly Source File  |  1990-01-16  |  61KB  |  1,775 lines

  1.     NAME    mssfil
  2. ; File MSSFIL.ASM
  3.     include mssdef.h
  4. ; Edit history:
  5. ; Last edit 15 Jan 1990
  6.  
  7.     public    buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec
  8.     public    encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr
  9.     public    strlen, strcat, strcpy, tfilsz, templp, latin1, charids
  10.     public    L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique
  11.     public    load, cplatin
  12.  
  13. data    segment    public 'data'
  14.     extrn    flags:byte, trans:byte, denyflg:word, dosnum:word
  15.     extrn    oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte
  16.  
  17. ermes4  db    'Unable to make unique name',0
  18. ermes9    db    'Printer not ready',0
  19. erms12    db    'Unable to create file ',0
  20. erms13    db    'Error writing output file',0
  21. infms5  db    'Renaming file to $'
  22. infms6    db    cr,lf,'?Unable to open file$'
  23. asmsg    db    ' as $'
  24. crlf    db    cr,lf,'$'
  25. printer    db    'PRN',0
  26. screen    db    'CON',0
  27. loadhlp    db    'filename$'
  28.                 ; DOS special chars allowed in filenames
  29. spchar2    db    '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh
  30.     db    5fh, 5eh, 7eh, 60h
  31. spc2len    equ    $-spchar2
  32.  
  33. textctl    db    cr,lf,tab,bell,ff,ctlz    ; controls allowed in text files
  34. textctlen equ    $-textctl
  35.     even
  36. filflg    db    0        ; input buffer has data, if non-zero
  37. tmprptq    db    0        ; working copy of repeat prefix
  38. rptval    db    0        ; repeated character
  39. rptct    db    1        ; number of times it's repeated
  40. decoutp    dw    0        ; ptr to proc to dump decode output buffer
  41. encinp    dw    0        ; ptr to proc to refill encode input buffer
  42. dchrcnt dw    0        ; number of chars in the decode file buffer
  43. echrcnt dw    0        ; number of chars in the encode file buffer
  44. dbufpnt dw    0        ; position in file buffer, decoder
  45. ebufpnt dw    0        ; position in file buffer, encoder
  46. decbuf    db    512 dup (0)    ; decoding source buffer
  47.     db    0        ; safety for possible null terminator
  48. encbuf    db    512 dup (0)    ; encoding source buffer
  49.     db    0        ; safety for possible null terminator
  50.  
  51. tfilsz    dw    0,0        ; bytes transferred (double word qty)
  52. nmoflg    db    0        ; have override filename, if non-zero
  53. templp    db    65 dup (?)    ; temp for local path part
  54. templf    db    14 dup (?)    ; temp for local filename part
  55. temprp    db    65 dup (?)    ; temp for remote path part
  56. temprf    db    14 dup (?)    ; temp for remote filename part
  57. auxfile    db    65 dup (?)    ; auxillary filename for general use
  58. diskio    filest    <>        ; ditto, for ordinary file transfers
  59. buff    db    buffsz dup (?)    ; use as our Disk Transfer Area
  60. havdot    db    0        ; dot-found status in verify
  61. unum    dw    0        ; unique filename generation number
  62. temp    dw    0
  63.                 ; charids: table of transfer char-set idents
  64. charids dw    2,chtrans,chlatin1 ; qty, pointers to char set idents
  65. chtrans    db    1,'A'        ; Transparent. char count, ident
  66. chlatin1 db    6,'I2/100'    ; Latin1. char count, ident
  67.                 ; end of charids info
  68. loadtab    db    1        ; LOAD command table
  69.     mkeyw    'Transfer-character-set',0
  70.  
  71. filtab    macro
  72.     cnt = 128
  73.     rept    128            ; 128 idenity entries
  74.     db    cnt            ; initialize table to 128 .. 255
  75.     cnt = cnt + 1
  76.     endm
  77. endm
  78.  
  79. userin    equ    this byte        ; LOAD command
  80.     filtab                ; init table to idenity
  81. namein    db    20 dup (0)        ; name of the character set
  82. userout    equ    this byte
  83.     filtab                ; init table to idenity
  84. nameout db    20 dup (0)        ; name of the character set
  85. tblptr    dw    0            ; LOAD command
  86. xlines    dw    0            ; LOAD command
  87. linecnt    dw    0            ; LOAD command
  88. badvalue db    cr,lf,'?Bad value on line $'
  89.  
  90. ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages
  91. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  92. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  93. ; Each table is 96 translatable bytes followed by the table size (96), the
  94. ; ISO announcer ident ('A' and a null here).
  95.                     ; from ISO 8859-1 Latin-1 to Code Page
  96.                             ; to CP437
  97. L1cp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  98.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  99.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  100.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  101.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  102.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  103.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0feh    ; column 11
  104.     db    2ch,60h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  105.     db    85h,0a0h,83h,83h,  8eh,8fh,92h,80h    ; column 12
  106.     db    8ah,90h,88h,89h,   8dh,0a1h,8ch,8bh
  107.     db    44h,0a5h,95h,0a2h, 93h,94h,94h,58h    ; column 13
  108.     db    0edh,97h,0a3h,96h, 9ah,59h,3fh,0e1h
  109.     db    85h,0a0h,83h,84h,  84h,86h,91h,87h    ; column 14
  110.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  111.     db    3fh,0a4h,95h,0a2h, 93h,94h,94h,0f6h    ; column 15
  112.     db    0edh,97h,0a3h,96h, 81h,98h,9eh,98h
  113.     db    96,'A',0            ; 96 byte set, letter ident
  114.  
  115.                             ; to CP850
  116. L1cp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  117.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  118.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  119.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  120.     db    20h,0adh,0bdh,9ch,  0cfh,0beh,0ddh,15h    ; column 10
  121.     db    0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh
  122.     db    0f8h,0f1h,0fdh,0fch, 0efh,0e6h,14h,0feh    ; column 11
  123.     db    03fh,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h
  124.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  125.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  126.     db    0d1h,0a5h,0e0h,0e3h, 0e2h,0e5h,99h,9eh    ; column 13
  127.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,0e7h,0e1h
  128.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  129.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  130.     db    0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h    ; column 15
  131.     db    9bh,97h,0a3h,96h,   81h,0ech,0e8h,98h
  132.     db    96,'A',0            ; 96 byte set, letter ident
  133.                             ; to CP860
  134. L1cp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  135.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  136.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  137.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  138.     db    20h,0adh,9bh,9ch,  0fh,59h,7ch,15h    ; column 10
  139.     db    22h,3fh,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  140.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0feh    ; column 11
  141.     db    2ch,60h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  142.     db    85h,0a0h,83h,83h,  8eh,8fh,92h,80h    ; column 12
  143.     db    8ah,90h,88h,89h,   8dh,0a1h,8ch,8bh
  144.     db    44h,0a5h,95h,0a2h, 93h,94h,94h,58h    ; column 13
  145.     db    0edh,97h,0a3h,96h, 9ah,59h,3fh,0e1h
  146.     db    85h,0a0h,83h,84h,  84h,86h,91h,87h    ; column 14
  147.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  148.     db    3fh,0a4h,95h,0a2h, 93h,94h,94h,0f6h    ; column 15
  149.     db    0edh,97h,0a3h,96h, 81h,98h,9eh,98h
  150.     db    96,'A',0            ; 96 byte set, letter ident
  151.                             ; to CP863
  152. L1cp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  153.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  154.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  155.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  156.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  157.     db    22h,40h,61h,0aeh, 0aah,0c4h,3fh,2dh
  158.     db    0f8h,0f1h,0fdh,33h, 0a1h,0e6h,86h,0feh    ; column 11
  159.     db    0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh
  160.     db    8eh,41h,84h,41h,   41h,41h,3fh,80h    ; column 12
  161.     db    91h,90h,92h,94h,   49h,49h,88h,95h
  162.     db    44h,4eh,4fh,4fh,   99h,4fh,4fh,58h    ; column 13
  163.     db    0edh,9dh,55h,0aeh, 55h,59h,3fh,0e1h
  164.     db    85h,61h,83h,61h,   61h,61h,3fh,87h    ; column 14
  165.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  166.     db    3fh,6eh,6fh,0a2h,  93h,6fh,6fh,0f6h    ; column 15
  167.     db    0edh,97h,0a3h,96h, 75h,79h,3fh,79h
  168.     db    96,'A',0            ; 96 byte set, letter ident
  169.                             ; to CP865
  170. L1cp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  171.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  172.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  173.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  174.     db    20h,0adh,3fh,9ch,  0afh,3fh,7ch,15h    ; column 10
  175.     db    0a4h,3fh,0a6h,0aeh, 0aah,0c4h,3fh,0c4h
  176.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0feh    ; column 11
  177.     db    2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h
  178.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  179.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  180.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  181.     db    0edh,55h,55h,55h,  9ah,59h,3fh,0e1h
  182.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  183.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  184.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  185.     db    0edh,97h,0a3h,96h, 81h,79h,3fh,98h
  186.     db    96,'A',0            ; 96 byte set, letter ident
  187.  
  188. ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin-1
  189. ; For GRight only (high bit set).
  190.                             ; from Code Page 437
  191. cp437L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  192.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  193.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  194.     db    0ffh,0d6h,0dch,0a2h, 0a3h,0a6h,3fh,3fh
  195.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  196.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  197.     db    16 dup (3fh)                 ; column 11
  198.     db    16 dup (3fh)                 ; column 12
  199.     db    16 dup (3fh)                 ; column 13
  200.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  201.     db    6 dup(3fh),             3fh,3fh
  202.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  203.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  204.                              ; from Code Page 850
  205. cp850L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  206.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  207.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  208.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,0d7h,3fh
  209.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  210.     db    0bfh,0aeh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  211.     db    5 dup (3fh),              0c1h,0c2h,0c0h ; column 11
  212.     db    0a9h, 4 dup (3fh),      0a2h,0a5h,0ach
  213.     db    6 dup (3fh),0e3h,0c3h, 7 dup (3fh),0a4h     ; column 12
  214.     db    0f0h,0d0h,0cah,0cbh, 0c8h,0b9h,0cdh,0ceh ; column 13
  215.     db    0cfh, 4 dup (3fh),       0a6h,0cch,3fh
  216.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0deh ; column 14
  217.     db    0feh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  218.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,0f7h,0b8h ; column 15
  219.     db    0b0h,0a8h,3fh,0b9h,  0b2h,0b3h,0b7h,20h
  220.                              ; from Code Page 860
  221. cp860L1    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  222.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  223.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  224.     db    0cch,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  225.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  226.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  227.     db    16 dup (3fh)                 ; column 11
  228.     db    16 dup (3fh)                 ; column 12
  229.     db    16 dup (3fh)                 ; column 13
  230.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  231.     db    5 dup(3fh),            0f8h,3fh,3fh
  232.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  233.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  234.                              ; from Code Page 863
  235. cp863L1    db    0c7h,0fch,0e9h,0e2h, 0e2h,0e0h,0b6h,0a2h ; column 8
  236.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  237.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0fah ; column 9
  238.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  239.     db    0a6h,0b4h,0f3h,0fah, 0a8h,0a8h,0b3h,0afh ; column 10
  240.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  241.     db    16 dup (3fh)                 ; column 11
  242.     db    16 dup (3fh)                 ; column 12
  243.     db    16 dup (3fh)                 ; column 13
  244.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  245.     db    5 dup(3fh),            0f8h,3fh,3fh
  246.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  247.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  248.                                   ; from Code Page 865
  249. cp865L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  250.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  251.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0fah ; column 9
  252.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  253.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  254.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  255.     db    16 dup (3fh)                 ; column 11
  256.     db    16 dup (3fh)                 ; column 12
  257.     db    16 dup (3fh)                 ; column 13
  258.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  259.     db    5 dup(3fh),            0f8h,3fh,3fh
  260.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  261.     db    0b0h, 4 dup (3fh),       0b2h,0b7h,3fh
  262.  
  263. data    ends
  264.  
  265. code    segment    public 'code'
  266.     extrn    decout:near, isfile:near, newfn:near, comnd:near, atoi:near
  267.     extrn    ermsg:near, clrfln:near, frpos:near, kbpr:near, perpr:near
  268.  
  269.     assume  cs:code, ds:data, es:nothing
  270.  
  271. ; Set register SI to the offset of the ISO Latin-1 table appropriate to the
  272. ; currently active Code Page. Defaults to CP437 if no CP found.
  273. LATIN1    proc    near
  274.     mov    si,offset L1cp437    ; assume CP437
  275.     cmp    flags.chrset,437    ; current Code Page is 437?
  276.     je    latin1x            ; e = yes
  277.     mov    si,offset L1cp850    ; assume CP850
  278.     cmp    flags.chrset,850    ; current Code Page is 850?
  279.     je    latin1x            ; e = yes
  280.     mov    si,offset L1cp860    ; assume CP860
  281.     cmp    flags.chrset,860    ; current Code Page is 860?
  282.     je    latin1x            ; e = yes
  283.     mov    si,offset L1cp863    ; assume CP863
  284.     cmp    flags.chrset,863    ; current Code Page is 863?
  285.     je    latin1x            ; e = yes
  286.     mov    si,offset L1cp865    ; assume CP865
  287.     cmp    flags.chrset,865    ; current Code Page is 865?
  288.     je    latin1x            ; e = yes
  289.     mov    si,offset userin    ; user loadable incoming table
  290.     cmp    flags.chrset,1        ; User-defined table?
  291.     je    latin1x            ; e = yes
  292.     mov    si,offset L1cp437    ; default to CP437
  293. latin1x:ret
  294. LATIN1    endp
  295.  
  296. ; Set reg BX to offset of table for Code Page to ISO 8859-1 Latin-1
  297. cplatin proc    near
  298.     mov    bx,offset cp437L1    ; assume CP437
  299.     cmp    flags.chrset,437    ; current Code Page is 437?
  300.     je    cplatx            ; e = yes
  301.     mov    bx,offset cp850L1    ; assume CP850
  302.     cmp    flags.chrset,850    ; current Code Page is 850?
  303.     je    cplatx            ; e = yes
  304.     mov    bx,offset cp860L1    ; assume CP860
  305.     cmp    flags.chrset,860    ; current Code Page is 860?
  306.     je    cplatx            ; e = yes
  307.     mov    bx,offset cp863L1    ; assume CP863
  308.     cmp    flags.chrset,863    ; current Code Page is 863?
  309.     je    cplatx            ; e = yes
  310.     mov    bx,offset cp865L1    ; assume CP865
  311.     cmp    flags.chrset,865    ; current Code Page is 865?
  312.     je    cplatx            ; e = yes
  313.     mov    bx,offset userout    ; user loadable outgoing table
  314.     cmp    flags.chrset,1        ; User-table?
  315.     je    cplatx            ; e = yes
  316.     mov    bx,offset cp437L1    ; default to CP437
  317. cplatx:ret
  318. cplatin endp
  319.  
  320. ; Output the chars in a packet, called only by receiver code.
  321. ; Enter with SI equal to pktinfo structure pointer.
  322. PTCHR:    mov    decoutp,offset outbuf  ; routine to call when buffer gets full
  323.     jmp    short decode
  324.  
  325.  
  326. ; Dodecoding.
  327. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ???
  328. ; Modifies regs BX, CX.
  329. ; Enter with SI equal to pktinfo structure pointer.
  330. dodec    proc    near
  331.     push    ax            ; save reg
  332.     mov    decoutp,offset dnulr    ; routine to dump buffer (null)
  333.     call    decode
  334.     push    bx
  335.     mov    bx,dbufpnt        ; next char position
  336.     mov    byte ptr [bx],0        ; null terminator
  337.     pop    bx
  338.      pop    ax
  339.     ret
  340. dodec    endp
  341.  
  342. dnulr:    ret                ; dummy buffer emptier
  343.  
  344. ; Enter with [si].datlen = length of data, [si].datadr = address of data,
  345. ; DECOUTP = pointer to routine which writes output buffer
  346. ; Returns DBUFPNT = pointer to output buffer address (offset part)
  347. ; All packets are decoded except I, S, and A types.
  348. ; Flushes output buffer before returning.
  349. ; Returns carry clear if success, otherwise carry set
  350. decode    proc    near
  351.     push    si
  352.     push    di
  353.     push    es
  354.     push    dx
  355.     push    ds
  356.     pop    es            ; set es to data segment
  357.     mov    dchrcnt,length decbuf    ; size of output buffer
  358.     mov    dbufpnt,offset decbuf ; decoded data placed here pending output
  359.     mov    cx,[si].datlen        ; length of source buffer data
  360.     mov    si,[si].datadr        ; source buffer address
  361.     mov    di,dbufpnt        ; destination of data
  362.     mov    bl,trans.squote        ; regular quote char
  363.     xor    dh,dh            ; assume no quote char
  364.     cmp    trans.ebquot,'N'    ; any 8-bit quoting?
  365.     je    decod1            ; e = no quoting
  366.     cmp    trans.ebquot,'Y'    ; or not doing it?
  367.     je    decod1            ; e = no need to quote
  368.     mov    dh,trans.ebquot        ; otherwise use 8-bit quote char
  369.  
  370. decod1:    mov    rptct,1            ; reset repeat count
  371.     cmp    cx,0            ; any more chars in source?
  372.     jg    decod2            ; g = yes
  373.     jmp    decod6            ; else, we're through
  374. decod2:    cld                ; forward direction
  375.     lodsb                ; pick up a char
  376.     dec    cx            ; count number left
  377.     cmp    al,trans.rptq        ; repeat quote char?
  378.     jne    dcod21            ; ne = no, continue processing it
  379.     or    al,al            ; doing repeat quoting? (0 if no)
  380.     jz    dcod21            ; z = no, skip this part
  381.     lodsb                ; get the size
  382.     dec    cx            ; modify buffer count
  383.     sub    al,20H            ; make printable
  384.     mov    rptct,al        ; remember how many repetitions
  385.     lodsb                ; get the char to repeat
  386.     dec    cx            ; modify buffer count
  387.  
  388. dcod21:    xor    ah,ah            ; assume no 8-bit quote char
  389.     cmp    al,dh            ; is this the 8-bit quot char?
  390.     jne    decod3            ; ne = no
  391.     lodsb                ; yes, get the real character
  392.     dec    cx            ; decrement # chars in packet
  393.     mov    ah,80H            ; turn on 8-bit quot char flag
  394. decod3: cmp    al,bl            ; quote char?
  395.     jne    decod4            ; ne = no, proceed
  396.     lodsb                ; get the quoted character
  397.     dec    cx            ; decrement # of chars in packet
  398.     or    ah,al            ; save parity (combine with prefix)
  399.     and    ax,807fh        ; only parity in ah, remove it in al
  400.     cmp    al,bl            ; quote char?
  401.     je    decod4            ; e = yes, just go write it out
  402.     cmp    al,dh            ; 8-bit quote char?
  403.     je    decod4            ; e = yes, just go write it out
  404.     cmp    al,trans.rptq        ; repeat quote character?
  405.     je    decod4            ; e = yes, just write it out
  406.     cmp    al,3fh            ; char less than '?' ?
  407.     jb    decod4            ; b = yes; leave it intact
  408.     cmp    al,5fh            ; char greater than '_' ?
  409.     ja    decod4            ; a = yes; leave it alone
  410.     add    al,40H            ; make it a control char again
  411.     and    al,7FH            ; modulo 128 (includes DEL)
  412. decod4: or    al,ah            ; or in parity
  413.     push    cx
  414. decod5:    xor    ch,ch
  415.     mov    cl,rptct        ; number of chars to be written
  416.     jcxz    decod5c            ; z = none
  417.     cmp    cx,dchrcnt        ; needed vs space available
  418.     jbe    decod5a            ; be = enough space for rptct chars
  419.     mov    cx,dchrcnt        ; insufficient space, do dchrcnt
  420. decod5a:sub    rptct,cl        ; reduce number left to be written
  421.     sub    dchrcnt,cx        ; reduce output free space
  422.     pushf                ; save sub status flags
  423.     shr    cx,1
  424.     jnc    decod5b            ; nc = an even number
  425.     stosb                ; store the odd byte
  426.     jcxz    decod5d            ; z = nothing else to write
  427. decod5b:mov    ah,al            ; make a copy for word writes
  428.     rep    stosw            ; store cx words
  429. decod5d:popf                ; recover flags from sub dchrcnt,cx
  430.     jg    decod5c            ; g = space remaining in output buffer
  431.     push    dx            ; flush output buffer
  432.     push    bx
  433.     push    ax            ; save the char
  434.     call    decoutp            ; output the buffer
  435.     pop    ax            ; recover repeated char
  436.     pop    bx
  437.     pop    dx
  438.     jc    decod7            ; c = error if disk is full
  439.     mov    di,dbufpnt
  440.     jmp    short decod5        ; see if more chars need be written
  441. decod5c:pop    cx            ; recover main loop counter
  442.     jmp    decod1            ; get next source character
  443.     
  444. decod6:    mov    dbufpnt,di        ; flush buffer before exiting decode
  445.     push    cx
  446.     call    decoutp            ; flush output buffer before final ret
  447. decod7:    pop    cx
  448.  
  449.     pop    dx
  450.     pop    es
  451.     pop    di
  452.     pop    si
  453.     ret                ; return successfully if carry clear
  454. decode    endp
  455.                     ; output decbuf, reset bufpnt & chrcnt
  456. outbuf:    mov    cx,length decbuf    ; get full size of buffer
  457.     sub    cx,dchrcnt        ; minus space remaining = # to write
  458.     jg    outbu2            ; g = something to do
  459.     jmp    outbf1
  460. outbu2:    mov    dx,offset decbuf    ; address of buffer
  461.     cmp    trans.xtype,1        ; File Type Binary?
  462.     je    outbu5            ; e = yes, no translation
  463.     cmp    flags.destflg,1        ; disk destination?
  464.     je    outbu5            ; e = yes, DOS will do it
  465.     cmp    flags.eofcz,0        ; end on Control-Z?
  466.     je    outbu5            ; e = no
  467.     push    cx            ; else map Control-Z to space
  468.     push    di
  469.     push    es
  470.     push    ds
  471.     pop    es            ; data to es
  472.     mov    di,dx            ; scan buffer es:di, cx chars worth
  473.     mov    al,ctlz            ; look for Control-Z
  474.     cld
  475. outbu3:    repne    scasb
  476.     jne    outbu4            ; ne = found no Control-Z's
  477.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  478.     jcxz    outbu4            ; z = examined all chars
  479.     jmp    short outbu3        ; until examined everything
  480. outbu4:    pop    es
  481.     pop    di
  482.     pop    cx
  483.                     ; Character set translation section
  484. outbu5:    cmp    trans.xtype,1        ; File Type Binary?
  485.     je    outbu7            ; e = yes, no translation
  486.     cmp    trans.xchset,0        ; Transfer Transparent?
  487.     je    outbu7            ; e = yes, no translation
  488.     push    cx
  489.     push    si
  490.     push    di
  491.     call    latin1            ; set si to Latin-1 to CP table
  492.     mov    bx,si            ; set to bx for xlat
  493.     mov    si,offset decbuf    ; scan this buffer
  494.     mov    di,si
  495.     push    es
  496.     push    ds
  497.     pop    es
  498.     cld
  499. outbu6:    lodsb                ; get a char
  500.     test    al,80h            ; high bit set?
  501.     jz    outbu6a            ; z = no, do not translate
  502.     and    al,not 80h        ; clear high bit
  503.     xlatb                ; translate via bx table
  504. outbu6a:stosb                ; store char
  505.     loop    outbu6            ; do all concerned
  506.     pop    es
  507.     pop    di
  508.     pop    si
  509.     pop    cx
  510.  
  511. outbu7:    push    bx
  512.     mov    bx,diskio.handle    ; file handle
  513.     mov    ah,write2        ; write cx bytes
  514.     int    dos
  515.     pop    bx
  516.     jc    outbf0            ; c set means writing error
  517.     cmp    ax,cx            ; did we write all the bytes?
  518.     je    outbf1            ; e = yes
  519.     push    bx
  520.     mov    bx,offset decbuf
  521.     add    bx,ax            ; look at break character
  522.     cmp    byte ptr [bx],ctlz    ; ended on Control-Z?
  523.     pop    bx
  524.     je    outbf1            ; e = yes, say no error
  525. outbf0: mov    dx,offset erms13    ; Error writing device
  526.     cmp    flags.xflg,0        ; writing to screen?
  527.     jne    outbf0a            ; ne = yes
  528.     cmp    flags.destflg,0        ; writing to printer?
  529.     jne    outbf0a            ; ne = no
  530.     mov    dx,offset ermes9    ; Printer not ready message
  531. outbf0a:call    ermsg
  532.     stc                ; return failure
  533.     ret
  534.  
  535. outbf1:    add    tfilsz,cx        ; count received chars
  536.     adc    tfilsz+2,0
  537.     test    flags.remflg,dserial    ; serial mode display?
  538.     jnz    outb11            ; nz = yes, skip kbyte and % displays
  539.     cmp    flags.xflg,0        ; receiving to screen?
  540.     jne    outb11            ; ne = yes
  541.     call    kbpr            ; display kilobytes done
  542.     call    perpr            ; display percentage done
  543. outb11:    mov    dbufpnt,offset decbuf    ; address for beginning
  544.     mov    dchrcnt,length decbuf    ; size of empty buffer
  545.     clc                ; return success
  546.     ret
  547.  
  548. ; Get chars from file, encode them to pktinfo structure pointed to by si
  549.  
  550. gtchr:    mov    [si].datlen,0        ; say no output data yet
  551.     cmp    filflg,0        ; is there anything in the buffer?
  552.     jne    gtchr0            ; ne = yes, use that material first
  553.     call    inbuf            ; do initial read from source
  554.     jc    gtchr1            ; c = no more chars, go return EOF
  555. gtchr0:    mov    encinp,offset inbuf    ; buffer refiller routine
  556.     jmp    short encode
  557.  
  558. gtchr1:    mov    [si].datlen,0        ; report EOF
  559.     mov    flags.eoflag,1        ; say eof
  560.     stc                ; return failure
  561.     ret
  562.  
  563. ; Do encoding.
  564. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr.
  565. ; Writes output to area pointed to by [si].datadr.
  566. ; Returns char count in cx and [si].datlen with carry clear if success,
  567. ; else carry set if overflow.
  568. ; SI is preserved
  569. doenc:    clc
  570.     jcxz    doen0            ; cx = 0 means nothing to encode
  571.     mov    echrcnt,cx        ; number of bytes of source data
  572.     mov    ebufpnt,offset encbuf    ; source of data
  573.     mov    encinp,offset nulref    ; null routine for refilling buffer
  574.     call    encode            ; make a packet with size in AX
  575.     mov    cx,ax
  576. doen0:    ret
  577.  
  578. nulref:    mov    echrcnt,0        ; no data to return
  579.     stc
  580.     ret
  581.  
  582. ; encode - writes data portion of kermit packet into [[si].datadr].
  583. ; expects encinp to contain the address of a routine to refill the buffer,
  584. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  585. ; the maximum size of the data packet, ebufpnt to contain a pointer to
  586. ; the source of the characters, and [si].datadr to be output address.
  587. ; Returns: AX = the number of characters actually written to the buffer
  588. ; All packets except I, S, and A types are encoded.
  589. ; Returns carry clear for success, carry set otherwise.
  590.  
  591. encode    proc    near
  592.     push    si            ; save caller's si
  593.     mov    al,trans.rptq        ; repeat quote character
  594.     mov    tmprptq,al        ; working copy
  595.     mov    rptct,1            ; number of times char is repeated
  596.     mov    rptval,0        ; value of repeated char
  597.     mov    cx,trans.maxdat        ; maximum packet size
  598.     push    ds
  599.     pop    es            ; make es:di point to data segment
  600.     mov    di,[si].datadr        ; address of output buffer
  601.     mov    temp,di            ; remember output buffer start address
  602.     mov    si,ebufpnt        ; pointer into source buffer
  603.     mov    dl,trans.rquote        ; send quote char
  604.     xor    dh,dh            ; assume no 8-bit quoting
  605.     cmp    trans.ebquot,'N'    ; refusing 8-bit quoting?
  606.     je    encod1            ; e = yes
  607.     cmp    trans.ebquot,'Y'    ; or can but won't?
  608.     je    encod1            ; e = yes
  609.     mov    dh,0ffh            ; remember we have to do it
  610. encod1: cmp    cx,0            ; any space left in output buffer?
  611.     jg    encod2            ; g = yes
  612.     mov    ax,di            ; current output location
  613.     sub    ax,temp            ; minus start of buffer, ret cnt in AX
  614.     mov    ebufpnt,si        ; update pointer into source buffer
  615.     pop    si            ; restore caller's si
  616.     mov    [si].datlen,ax
  617.     clc                ; success
  618.     ret
  619.  
  620. encod2: cmp    echrcnt,0        ; any data in buffer?
  621.     jg    encod3            ; g = yes, skip over buffer refill
  622.     call    encinp            ; get another buffer full
  623.     jnc    encod2a            ; nc = success
  624.  
  625. encod8:    pop    si            ; restore user's si
  626.     sub    di,temp            ; minus start of buffer
  627.     or    di,di            ; buffer empty?
  628.     jz    encod9            ; z = yes
  629.     mov    ax,di            ; report size encoded
  630.     mov    [si].datlen,ax
  631.     clc                ; success
  632.     ret                ; return success
  633. encod9: xor    ax,ax            ; empty buffer
  634.         mov    flags.eoflag,1        ; set eof flag
  635.     mov    filflg,0        ; nothing in input buffer
  636.     mov    [si].datlen,0
  637.     stc                ; failure
  638.     ret                ; return failure
  639.  
  640. encod2a:mov    si,ebufpnt        ; update position in source buffer
  641.     cmp    echrcnt,0         ; any characters returned?
  642.     je    encod8            ; e = none, assume eof
  643.  
  644. encod3: dec    echrcnt            ; decrement input count
  645.     cld                ; forward direction
  646.     lodsb
  647.     cmp    al,'Z'-40H        ; is this a control-Z?
  648.     jne    encd30            ; ne = no, skip eof-processing
  649.     cmp    flags.eofcz,0           ; is a Control-Z an end of file?
  650.     je    encd30            ; e = no
  651.     cmp    trans.xtype,1        ; file type binary?
  652.     je    encd30            ; e = yes, send as is
  653.     mov    flags.eoflag,1        ; yes, set eof flag
  654.     mov    filflg,0        ; say no more source data in buffer
  655.     mov    echrcnt,0        ; ditto
  656.         jmp    encod8                  ; set character count and return
  657.  
  658. encd30: cmp    tmprptq,0        ; doing repeat prefixing? 
  659.     je    encd3x            ; e = no
  660.     cmp    echrcnt,0        ; doing the last character?
  661.     jle    encd31            ; le = yes, there is no next character
  662.     cmp    rptct,94        ; max number that we can put in a byte
  663.     je    encd31            ; e = at that limit
  664.     cmp    al,[si]            ; is current char == next char?
  665.     jne    encd31            ; ne = no, break repeating
  666.     inc    rptct            ; number of times char appears
  667.     mov    rptval,al        ; remember the character
  668.     jmp    encod1            ; keep checking for more
  669.  
  670. encd31:    cmp    rptct,1            ; were previous characters repeats?
  671.     je    encd3x            ; e = no, so just add this char
  672.     cmp    rptct,3            ; within bounds for repeat prefixing?
  673.     jge    encd32            ; ge = yes, use repeat prefixing
  674.     mov    al,rptct        ; number of copies
  675.     xor    ah,ah            ; push back
  676.     sub    si,ax            ; not enough characters to warrant it
  677.     mov    rptval,0        ; clear out this value
  678.     mov    tmprptq,0        ; pretend we're not doing prefixing
  679.     add    echrcnt,ax        ; adjust input buffer pointer
  680.     jmp    encod1            ; reprocess those characters
  681.  
  682. encd32:    push    ax            ; do repeat prefixing - save data
  683.     mov    al,trans.rptq        ; insert repeat prefix char
  684.     stosb
  685.     dec    cx            ; account for it in buffer size
  686.     mov    al,rptct        ; get the repeat count
  687.     add    al,20H            ; make it printable
  688.     stosb                ; insert into buffer
  689.     dec    cx
  690.     pop    ax            ; get back the actual character
  691.     mov    rptct,1            ; reset repeat count
  692.     mov    rptval,0        ; and this
  693. encd3x:    or    dh,dh            ; doing 8-bit quoting?
  694.     jz    encod4            ; z = no, forget this
  695.     test    al,80h            ; parity on?
  696.     jz    encod4            ; z = no, don't bother with this
  697.     and    al,7fh            ; turn off parity
  698.     mov    ah,trans.ebquot        ; get quote char
  699.     mov    [di],ah            ; put in packet
  700.     inc    di
  701.     dec    cx            ; decrement # of chars left
  702. encod4:    mov    ah,al            ; save character
  703.     and    ah,80h            ; only parity
  704.     and    al,7fh            ; turn off parity in character
  705.     cmp    al,' '            ; compare to a space
  706.     jb    encod5            ; b = control char
  707.     cmp    al,del            ; delete?
  708.     je    encod5            ; e = yes, go quote it
  709.     cmp    al,dl            ; quote char?
  710.     je    encod6            ; e = yes, go add it
  711.     or    dh,dh            ; doing 8-bit quoting?
  712.     jz    encd41            ; z = no, don't translate it
  713.     cmp    al,trans.ebquot        ; 8-bit quote char?
  714.     je    encod6            ; e = yes, just output with quote
  715. encd41:    cmp    trans.rptq,0        ; doing repeat prefixing?
  716.     je    encod7            ; e = no, don't check for quote char
  717.     cmp    al,trans.rptq        ; repeat quote character?
  718.     je    encod6            ; e = yes, then quote it
  719.     jmp    short encod7        ; else don't quote it
  720.  
  721. encod5:    xor    al,40h            ; control char, uncontrollify
  722. encod6:    mov    [di],dl            ; insert control quote char
  723.     inc    di
  724.     dec    cx
  725. encod7:    or    al,ah            ; put parity back
  726.     stosb
  727.     dec    cx            ; decrement output buffer counter
  728.     cmp    rptct,1            ; one occurence of this char?
  729.     jne    encd7x            ; ne = no
  730.     mov    al,trans.rptq        ; real repeat quote char
  731.     mov    tmprptq,al        ; restore repeat quote char
  732.     jmp    encod1            ; loop around for some more
  733. encd7x:    dec    rptct            ; count another entry of this char
  734.     jmp    encod1            ; with quoting and all
  735. encode    endp 
  736.  
  737. ; Fill encode source buffer, report KB and percentage done.
  738. ; Return carry clear for success
  739. ; modifies ax
  740. inbuf    proc    near
  741.     cmp    flags.eoflag,0        ; reached the end?
  742.     je    inbuf0            ; e = no
  743.     stc                ; return failure
  744.     ret
  745. inbuf0:    push    dx
  746.     push    bx
  747.     push    cx
  748.     mov    bx,diskio.handle    ; get file handle
  749.     mov    cx,buffsz        ; record size
  750.     mov    dx,offset buff        ; buffer
  751.     mov    ebufpnt,dx        ; buffer pointer
  752.     mov    ah,readf2        ; read a record
  753.     int    dos
  754.     jc    inbuf1            ; c = error, ie file not open
  755.     or    ax,ax            ; any bytes read?
  756.     jnz    inbuf2            ; nz = yes (the number read)
  757. inbuf1:    mov    flags.eoflag,1        ; set End-of-File
  758.     mov    filflg,0        ; buffer empty
  759.     mov    echrcnt,0        ; zero bytes left in buffer
  760.     pop    cx
  761.     pop    bx
  762.     pop    dx
  763.     stc                ; failure
  764.     ret
  765. inbuf2:    add    tfilsz,ax        ; total the # bytes transferred so far
  766.     adc    tfilsz+2,0        ; it's a double word
  767.     mov    echrcnt,ax        ; number of chars read from file
  768.     mov    filflg,1        ; buffer not empty
  769.     test    flags.remflg,dserial    ; serial display mode?
  770.     jnz    inbuf3            ; nz = yes, skip kbyte and % display
  771.     push    si
  772.     push     ax
  773.     call    kbpr            ; show kilobytes sent
  774.     call    perpr            ; show percent sent
  775.     pop    ax
  776.     pop    si
  777.                     ; Character set translation section
  778. inbuf3:    cmp    trans.xchset,0        ; Transfer Transparent?
  779.     je    inbuf6            ; e = yes, no translation
  780.     cmp    trans.xtype,1        ; File Type Binary?
  781.     je    inbuf6            ; e = yes, no translation
  782.     push    ax            ; save buffer count
  783.     mov    cx,ax            ; loop counter
  784.     push    si
  785.     push    di
  786.     call    cplatin            ; set bx to offset CP to Latin-1 table
  787.     mov    si,offset buff        ; scan this buffer
  788.     mov    di,si
  789.     push    es
  790.     push    ds
  791.     pop    es
  792.     cld
  793. inbuf4:    lodsb                ; get a char
  794.     test    al,80h            ; high bit set?
  795.     jz    inbuf5            ; z = no, no translation
  796.     and    al,not 80h        ; remove high bit
  797.     xlatb                ; translate via bx table
  798. inbuf5:    stosb                ; store char
  799.     loop    inbuf4            ; do all concerned
  800.     pop    es
  801.     pop    di
  802.     pop    si
  803.     pop    ax
  804. inbuf6:    pop    cx
  805.     pop    bx
  806.     pop    dx
  807.     clc                ; success
  808.     ret
  809. inbuf    endp
  810.  
  811.  
  812. ; GETFIL, called only by send code
  813. ; Enter with raw filename pattern in diskio.string
  814. ; Returns carry clear if success, else carry set
  815. getfil    proc    near
  816.     mov    filflg,0        ; say nothing is in the buffer
  817.     mov    flags.eoflag,0        ; not the end of file
  818.     mov    dx,offset diskio.dta    ; data transfer address
  819.     mov    ah,setdma        ; set disk transfer address
  820.     int    dos
  821.     xor    cx,cx            ; attributes: find only normal files
  822.     mov    dx,offset diskio.string ; filename string (may have wild cards)
  823.     mov    ah,first2        ; DOS 2.0 search for first
  824.     int    dos            ; get file's characteristics
  825.     pushf                ; save c flag
  826.     mov    ah,setdma        ; reset dta address
  827.     mov    dx,offset buff        ; restore dta
  828.     int    dos
  829.     popf                ; restore status of search for first
  830.     jnc    getfi1            ; nc = ok so far
  831.     ret                ; else take error exit
  832. getfi1:    jmp    getfcom            ; do common code
  833. getfil    endp
  834.  
  835.  
  836. ; GTNFIL called by send code to get next file.
  837. ; Returns carry clear for success, carry set for failure.
  838. gtnfil    proc    near
  839.     cmp    flags.cxzflg,'Z'    ; Did we have a ^Z?
  840.     jne    gtnfi1            ; ne = no, else done sending files
  841.     stc                ; carry set for failure
  842.     ret                ; take failure exit
  843.  
  844. gtnfi1:    mov    filflg,0        ; Nothing in the DMA
  845.     mov    flags.eoflag,0        ; Not the end of file
  846.     mov    dx,offset diskio.dta    ; point at dta
  847.     mov    ah,setdma        ; set the dta address
  848.     int    dos
  849.     mov    ah,next2        ; DOS 2.0 search for next
  850.     int    dos
  851.     pushf                ; save carry flag
  852.     mov    ah,setdma        ; restore dta
  853.     mov    dx,offset buff
  854.     int    dos
  855.     popf                ; recover carry flag
  856.     jnc    getfcom            ; nc = success, do common code
  857.     ret                ; carry    set means no more files found
  858. gtnfil    endp
  859.                     ; worker for getfil, gtnfil
  860. getfcom    proc    near
  861.     push    si
  862.     push    di
  863.     mov    dx,offset diskio.string    ; original file spec (may be wild)
  864.     mov    di,offset templp    ; place for path part
  865.     mov    si,offset templf    ; place for filename part
  866.     call    fparse            ; split them
  867.     mov    si,offset diskio.fname    ; current filename from DOS
  868.     call    strcat            ; (di)= local path + diskio.fname
  869.     mov    di,offset encbuf    ; name to send to host (no path)
  870.     call    strcpy              ; new string = old path + DOS's filename
  871.     push    bx
  872.     push    cx
  873.     test    flags.remflg,dquiet    ; quiet display?
  874.     jnz    getfco1            ; e = yes, do not display filename
  875.     call    clrfln            ; position cursor & blank out the line
  876.     mov    dx,offset templp
  877.     call    prtasz
  878. getfco1:call    newfn            ; update encbuf with "send as" name
  879.     pop    cx
  880.     pop    bx
  881.     mov    ah,open2        ; file open
  882.     xor    al,al            ; 0 = open readonly
  883.     cmp    dosnum,300h        ; at or above DOS 2?
  884.     jb    getfco2            ; b = no, so no shared access
  885.     or    al,40h            ; open readonly, deny none
  886. getfco2:mov    dx,offset templp    ; filename string with path
  887.     int    dos
  888.     jc    getfco3            ; c = failed to open the file
  889.     mov    diskio.handle,ax    ; save file handle
  890.     xor    ax,ax
  891.     mov    tfilsz,ax        ; set bytes sent to zero
  892.     mov    tfilsz+2,ax
  893.     mov    ax,-1            ; get a minus one
  894.     mov    oldkbt,ax
  895.     mov    oldper,ax
  896.     clc                ; carry clear for success
  897. getfco3:pop    si
  898.     pop    di
  899.     ret
  900. getfcom    endp
  901.  
  902. ; Get the file name from the data portion of the F packet or from locally
  903. ; specified override filename (in auxfile), displays the filename, does any
  904. ; manipulation of the filename necessary, including changing the name to
  905. ; prevent collisions. Returns carry clear for success. Failures return
  906. ; carry set with dx pointing at error message text.
  907. ; Called by file receive module in mssrcv.asm.
  908.  
  909. gofil:    mov    si,offset decbuf    ; filename in packet
  910.     mov    di,offset diskio.string    ; place where prtfn finds name
  911.     call    strcpy            ; copy pkt filename to diskio.string
  912.     mov    di,offset fsta.xname    ; statistics external filespec area
  913.     call    strcpy            ; record external name
  914.     cmp    auxfile,0        ; have override name?
  915.     jne    gofil1            ; ne = yes
  916.     cmp    flags.xflg,0        ; receiving to screen?
  917.     jne    gofil0a            ; ne = yes, filename becomes CON
  918.     cmp    flags.destflg,1        ; destination is disk?
  919.     je    gofil1            ; e = yes
  920.     mov    di,offset printer    ; assume PRN is local file name
  921.     jb    gofil0b            ; b = yes
  922. gofil0a:mov    di,offset screen    ; use CON (screen) as local file name
  923.     mov    flags.xflg,1        ; say receiving to screen
  924. gofil0b:xchg    di,si            ; di --> decbuf, si --> file name
  925.     call    strcpy            ; put local name (si) into decbuf
  926.     mov    nmoflg,1        ; say that we have a replacement name
  927.     jmp    gofil9            ; final filename is now in 'decbuf'
  928.  
  929. gofil1:    mov    nmoflg,0        ; assume no override name
  930.     cmp    auxfile,0        ; overriding name from other side?
  931.     jne    gofi1e            ; ne = yes
  932.     jmp    gofil4            ; e = no, get the other end's filename
  933. gofi1e:    mov    nmoflg,1        ; say using an override name
  934.     mov    ax,offset auxfile    ; get local override filename
  935.     cmp    word ptr auxfile+1,003ah; colon+null?(primative drive spec A:)
  936.     je    gofil3        ; e = yes, skip screwy DOS response (No Path)
  937.     cmp    word ptr auxfile,'..'    ; parent directory?
  938.     jne    gofi1g            ; ne = no
  939.     cmp    word ptr auxfile+1,002eh ; dot dot + null?
  940.     je    gofi1b            ; e = yes, process as directory
  941. gofi1g:    cmp    word ptr auxfile,002eh    ; dot + null (current dir)?
  942.     je    gofi1b            ; e = yes, process as directory
  943.     call    isfile            ; does it exist?
  944.     jnc    gofi1f            ; nc = file exists
  945.     test    filtst.fstat,80h    ; serious error?
  946.     jz    gofil3            ; z = no, just no such file
  947.     jmp    gofi18a            ; else quit here
  948. gofi1f:    test    byte ptr filtst.dta+21,10H ; subdirectory name?
  949.     jnz    gofi1b            ; nz = yes
  950.     cmp    filtst.fname,2eh    ; directory name?
  951.     je    gofi1b            ; e = yes, process as directory
  952.     cmp    auxfile+2,5ch        ; a root directory like b:\?
  953.     jne    gofi1d            ; ne = no. (DOS is not helpful with roots)
  954.     cmp    auxfile+3,0        ; and is it terminated in a null?
  955.     je    gofi1b            ; e = yes, so it is a root spec
  956. gofi1d:    test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  957.     jz    gofil3            ; z = no
  958.      jmp    gofi18a               ; yes. Complain and don't transfer file
  959. gofi1b:    mov    dx,offset auxfile    ; auxfile is a (sub)directory name
  960.     call    strlen            ; get its length w/o terminator
  961.     jcxz    gofil2            ; zero length
  962.     dec    cx            ; examine last char
  963.     push    bx            ; save bx
  964.     mov    bx,cx
  965.     add    bx,dx
  966.     cmp    byte ptr [bx],5ch    ; ends in backslash?
  967.     je    gofil2            ; e = yes
  968.     cmp    byte ptr [bx],2fh    ; maybe forward slash?
  969.     je    gofil2            ; e = yes
  970.     mov    byte ptr [bx + 1],5ch    ; no slash yet. use backslash
  971.     mov    byte ptr [bx + 2],0    ; plant new terminator
  972. gofil2:    pop    bx
  973.  
  974. gofil3:    mov    di,offset templp    ; local path
  975.     mov    si,offset templf    ; local filename
  976.     mov    dx,offset auxfile    ; local string
  977.     call    fparse            ; split local string
  978.     mov    di,offset temprp    ; remote path
  979.     mov    si,offset temprf    ; remote file
  980.     mov    dx,offset decbuf    ; remote string
  981.     mov    decbuf+64,0        ; force filename to be <= 64 chars
  982.     call    fparse            ; split remote string
  983.     test    flags.remflg,dserver    ; running in Server mode?
  984.     jz    gofi3c            ; z = no
  985.     test    denyflg,sndflg        ; is Deny Send mode in operation?
  986.     jz    gofi3c            ; z = no
  987.     mov    temprp,0        ; DENY, means remove remote path
  988. gofi3c:    mov    si,offset templp    ; copy local path to
  989.     mov    di,offset decbuf    ;  final filename
  990.     call    strcpy            ; do the copy
  991.     mov    si,offset templf    ; assume using local file name
  992.     cmp    byte ptr templf,0    ; local file name given?
  993.     jne    gofi3b            ; ne = yes
  994.     mov    si,offset temprf    ; else use remote file name
  995. gofi3b:    call    strcat            ; append path and filename again
  996.                     ; offset decbuf holds the new filename
  997.                     ;
  998.                 ; recheck legality of filename in 'decbuf'
  999. gofil4:    mov    decbuf+64,0        ; guard against long filenames
  1000.     mov    di,offset temprp    ; remote path
  1001.     mov    si,offset temprf    ; remote file
  1002.     mov    dx,offset decbuf    ; remote string
  1003.     call    strlen            ; get original size
  1004.     push    cx            ; remember it
  1005.     call    fparse            ; further massage filename
  1006.     push    si            ; put pieces back together
  1007.     call    verfil            ; verify each char in temprf string
  1008.     mov    si,di            ; get path part first
  1009.     mov    di,dx            ; set destination
  1010.     call    strcpy            ; copy in path part
  1011.     pop    si            ; recover (new) filename
  1012.     cmp    byte ptr [si],'.'    ; does filename part start with a dot?
  1013.     jne    gofil5            ; ne = no
  1014.     push    di            ; save regs
  1015.     push    si
  1016.     mov    di,offset rdbuf        ; a work area
  1017.     mov    byte ptr [di],'X'    ; start name with letter X
  1018.     inc    di
  1019.     call    strcpy            ; copy rest of filename
  1020.     mov    di,si
  1021.     mov    si,offset rdbuf      ; copy new name back to original location
  1022.     call    strcpy
  1023.     pop    si            ; restore regs
  1024.     pop    di    
  1025. gofil5:    call    strcat            ; append it
  1026.     call    strlen            ; see if we chopped out something
  1027.     pop    si            ; get original length (from push cx above)
  1028.     cmp    cx,si            ; same size?
  1029.     je    gofil9            ; e = yes
  1030.     mov    nmoflg,1        ; say that we have a replacement name
  1031.                 ; filename is now in 'decbuf', all converted
  1032. gofil9:    test    flags.remflg,dquiet    ; quiet display mode?
  1033.     jnz    gofi10            ; nz = yes, don't print it
  1034.     test    flags.remflg,dserial    ; serial display mode?
  1035.     jz    gofi9a            ; z = no
  1036.     mov    ah,prstr
  1037.     mov    dx,offset crlf        ; display cr/lf
  1038.     int    dos
  1039. gofi9a:    call    prtfn            ; show packet filename
  1040.     cmp    nmoflg,0        ; using local override name?
  1041.     je    gofil9b            ; e = no
  1042.     cmp    flags.xflg,0        ; receiving to screen? (X versus F)
  1043.     jne    gofil9b            ; ne = yes
  1044.     mov    ah,prstr
  1045.     mov    dx,offset asmsg        ; print " as "
  1046.     int    dos
  1047.     mov    dx,offset decbuf    ; plus the local filename
  1048.     call    prtasz            ; print asciiz string
  1049. gofil9b:mov    ah,flags.remflg        ; display a following cr/lf?
  1050.     and    ah,dserial        ; for serial display mode
  1051.     or    ah,flags.xflg        ; receiving to screen
  1052.     jz    gofi10            ; z = neither, no cr/lf
  1053.     mov    ah,prstr        ; finish the line with cr/lf
  1054.     mov    dx,offset crlf
  1055.     int    dos
  1056. gofi10:    mov    ax,offset decbuf    ; point to name
  1057.     cmp    flags.flwflg,1        ; overwrite existing file?
  1058.     jne    gofi10b            ; ne = no
  1059.     jmp    gofi16            ; e = yes
  1060. gofi10b:call    isfile            ; does it exist?
  1061.     mov    ax,offset decbuf    ; reload ptr in case
  1062.     jc    gofi16            ; carry set = no, just proceed
  1063.     mov    ah,open2        ; could it be a device name?
  1064.     xor    al,al            ; open readonly
  1065.     cmp    dosnum,300h        ; above DOS 2?
  1066.     jb    gofi10a            ; b = no, so no shared access
  1067.     or    al,40h            ; open for reading, deny none
  1068. gofi10a:mov    dx,offset decbuf    ; the filename
  1069.     int    dos
  1070.     jc    gofi11            ; c = cannot open so just proceed
  1071.     mov    bx,ax            ; file handle
  1072.     mov    ah,ioctl
  1073.     xor    al,al            ; 0 = get info
  1074.     int    dos
  1075.     mov    ah,close2        ; close it
  1076.     int    dos
  1077.     mov    ax,offset decbuf    ; point to filename again
  1078.     test    dl,80h            ; ISDEV bit set?
  1079.     jz    gofi11            ; z = no, not a device
  1080.     jmp    gofi16            ; device, use name as given
  1081. gofi11:    cmp    flags.flwflg,4        ; no-supersede existing file?
  1082.     jne    gofi12            ; ne = no (i.e., do a rename)
  1083.     mov    flags.cxzflg,'X'    ; say stop this file
  1084.     mov    word ptr decbuf,'UN'
  1085.     mov    decbuf+2,'L'        ; file name of NUL
  1086.     mov    decbuf+3,0        ; asciiz
  1087.     jmp    short gofi13
  1088. gofi12:    mov    ax,offset decbuf    ; point to filename again
  1089.     call    unique            ; generate unique name
  1090.     jc    gofi14            ; could not generate a unique name
  1091.     test    flags.remflg,dquiet    ; quiet display mode?
  1092.     jnz    gofi13            ; nz = yes, skip printing
  1093.     push    ax            ; save unique name again
  1094.     call    frpos            ; position cursor
  1095.     mov    ah,prstr           ; say we are renaming the file
  1096.     mov    dx,offset infms5
  1097.     int    dos
  1098.     pop    ax            ; get name back into ax again
  1099.     push    ax            ; save around these calls
  1100.     mov    dx,ax            ; print current filename
  1101.     call    prtasz            ; display filename
  1102.     pop    ax            ; pointer to name, again
  1103. gofi13:    jmp    gofi16            ; and go handle file
  1104.  
  1105. gofi14:    mov    dx,offset ermes4
  1106.     call    ermsg
  1107.     stc                ; failure, dx has msg pointer
  1108.     ret
  1109.  
  1110. gofi16:    mov    si,ax             ; pointer to (maybe new) name
  1111.     mov    di,offset diskio.string    ; filename, used in open
  1112.     mov    dx,di            ;  for isfile and open below
  1113.     call    strcpy             ; copy name to diskio.string
  1114.     xor    ax,ax
  1115.     mov    diskio.sizehi,ax    ; original file size is unknown
  1116.     mov    diskio.sizelo,ax    ; double word
  1117.     mov    tfilsz,ax        ; set bytes received to zero
  1118.     mov    tfilsz+2,ax
  1119.     mov    ax,-1            ; get a minus one
  1120.     mov    oldkbt,ax
  1121.     mov    oldper,ax
  1122.     mov    diskio.handle,ax    ; clear handle of previous usage
  1123.     mov    ax,dx            ; filename for isfile
  1124.     call    isfile        ; check for read-only/system/vol-label/dir
  1125.     jc    gofi16a            ; c = file does not exist
  1126.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  1127.     jz    gofi16b            ; z = ok
  1128.     jmp    gofi18            ; nz = do not write over one of these
  1129. gofi16a:test    filtst.fstat,80h    ; access problem?
  1130.     jnz    gofi18            ; nz = yes, quit here
  1131.     mov    diskio.handle,-1    ; clear handle of previous usage
  1132.     mov    ah,creat2        ; create file
  1133.     xor    cx,cx            ; 0 = attributes bits
  1134.     int    dos
  1135.     jc    gofi16b            ; c = did not work, try regular open
  1136.     mov    diskio.handle,ax    ; save file handle here
  1137.     clc                ; carry clear for success
  1138.     ret
  1139. gofi16b:test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  1140.     jnz    gofi18            ; we won't touch these
  1141.     mov    ah,open2           ; open existing file (usually a device)
  1142.     mov    al,1+1            ; open for writing
  1143.     int    dos
  1144.     jc    gofi18            ; carry set means can't open
  1145.     mov    diskio.handle,ax    ; file handle
  1146.     clc                ; carry clear for success
  1147.     ret
  1148.  
  1149. gofi18a:mov    si,ax             ; pointer to local override name
  1150.     mov    di,offset diskio.string    ; filename, used in open
  1151.     call    strcpy             ; copy name to diskio.string
  1152.                     ; fall    through to gofi18
  1153. gofi18:    test    flags.remflg,dquiet    ; quiet display mode?
  1154.     jnz    gofi19            ; nz = yes, don't try printing
  1155.     mov    dx,offset erms12    ; unable to create file
  1156.     call    ermsg
  1157.     push    dx
  1158.     mov    dx,offset diskio.string    ; print offending name
  1159.     call    prtasz            ; display filename
  1160.     pop    dx
  1161. gofi19:    stc                ; failure, dx has msg pointer
  1162.     ret
  1163.  
  1164. ; Given incoming filename in 'decbuf'.  Verify that each char is legal
  1165. ; (if not change it to an "X"), force max of three chars after a period (dot)
  1166. ; Source is at ds:si (si is changed here). [jrd]
  1167.  
  1168. VERFIL    PROC    NEAR
  1169.     push    es            ; verify each char in 'data'
  1170.     push    cx
  1171.     push    ds
  1172.     pop    es
  1173.     mov    havdot,0        ; say no dot found in name yet
  1174.     cld
  1175. verfi1:    lodsb                ; get a byte of name from si
  1176.     and    al,7fH            ; strip any eighth bit
  1177.     jz    verfi5            ; z = end of name
  1178.     cmp    al,'.'            ; a dot?
  1179.     jne    verfi2            ; ne = no
  1180.     cmp    havdot,0        ; have one dot already?
  1181.     jne    verfi3            ; ne = yes, change to X
  1182.     mov    byte ptr [si+3],0    ; forceably end filename after 3 char ext
  1183.     mov    havdot,1        ; say have a dot now
  1184.     jmp    verfi4            ; continue
  1185. verfi2:    cmp    al,3ah            ; colon?
  1186.     je    verfi4
  1187.     cmp    al,5ch            ; backslash path separator?
  1188.     je    verfi4
  1189.     cmp    al,2fh            ; or forward slash?
  1190.     je    verfi4
  1191.     cmp    al,'0'
  1192.     jb    verfi3            ; see if it's a legal char < '0'
  1193.     cmp    al,'9'
  1194.     jbe    verfi4            ; it's between 0-9 so it's OK
  1195.     cmp    al,'A'
  1196.     jb    verfi3            ; check for a legal punctuation char
  1197.     cmp    al,'Z'
  1198.     jbe    verfi4            ; it's A-Z so it's OK
  1199.     cmp    al,'a'
  1200.     jb    verfi3            ; check for a legal punctuation char
  1201.     cmp    al,'z'
  1202.     ja    verfi3
  1203.     and    al,5FH            ; it's a-z, capitalize
  1204.     jmp    verfi4            ; continue with no change
  1205.  
  1206. verfi3:    push    di            ; special char. Is it on the list?
  1207.     mov    di,offset spchar2    ; list of acceptable special chars
  1208.     mov    cx,spc2len
  1209.     cld
  1210.     repne    scasb            ; search string for input char
  1211.     pop    di
  1212.     je    verfi4            ; e = in table, return it
  1213.     mov    al,'X'            ; else illegal, replace with "X"
  1214.     mov    nmoflg,1        ; say we have a replacement filename
  1215. verfi4:    mov    [si-1],al        ; update name
  1216.     jmp    short verfi1        ; loop thru rest of name
  1217. verfi5:    mov    byte ptr[si-1],0    ; make sure it's null terminated
  1218.     pop    cx
  1219.     pop    es
  1220.     ret
  1221. VERFIL    ENDP
  1222.  
  1223. ; find a unique filename.
  1224. ; Enter with a pointer to a (null-terminated) filename in ax
  1225. ; Return with same pointer but with a new name (or old if failure)
  1226. ; Success = carry clear; failure = carry set
  1227. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  1228. ; then change the last chars successively to a 1, 2, etc. until
  1229. ; a unique name is found. All registers are preserved
  1230. ; Make empty main name fields start with letter X, not digit 0
  1231. unique    proc    near
  1232.     push    bx
  1233.     push    cx
  1234.     push    dx
  1235.     push    si
  1236.     push    di
  1237.     push    es
  1238.     push    ax            ; save address of source string
  1239.     mov    dx,ds            ; make es use ds segment
  1240.     mov    es,dx
  1241.     mov    dx,ax            ; point at original filename string
  1242.     mov    di,offset templp    ; place for path
  1243.     mov    si,offset templf    ; place for filename
  1244.     call    fparse            ; separate path (di) and filename (si)
  1245.     mov    dx,di            ; point at path part
  1246.     call    strlen            ; put length in cx
  1247.     mov    si,ax            ; point to original string
  1248.     add    si,cx            ; point to filename part
  1249.     mov    di,offset templf    ; destination is temporary location
  1250.     xor    cx,cx            ; a counter
  1251.     cld                ; set direction to be forward
  1252. uniq1:    lodsb                ; get a byte
  1253.     cmp    al,'.'            ; have a dot?
  1254.     je    uniq2            ; e = yes
  1255.     or    al,al            ; maybe    null at end?
  1256.     jnz    uniq3            ; nz = no, continue loop
  1257.  
  1258. uniq2:    cmp    cl,8            ; have we copied any chars before dot?
  1259.     jge    uniq3            ; ge = all 8
  1260.     mov    byte ptr [di],'0'    ; avoid clobbers; pad with 0's
  1261.     or    cl,cl            ; first char of filename?
  1262.     jnz    uniq2a            ; nz = no
  1263.     mov    byte ptr [di],'X'    ; start name with letter X, not 0
  1264. uniq2a:    inc    di            ; and count the output chars
  1265.     inc    cl            ; and this counter too
  1266.     jmp    uniq2            ; continue until filled 8 slots
  1267. uniq3:    inc    cl            ; cl = # char in destination
  1268.     stosb                ; store the char
  1269.     or    al,al            ; null at end?
  1270.     jnz    uniq1            ; nz = no, continue copying
  1271.  
  1272.     mov    templf+7,'1'        ; put '1' in last name char
  1273.     mov    unum,1            ; start with this generation digit
  1274.  
  1275. uniq4:    mov    di,offset rdbuf        ; build a temporary full filename
  1276.     mov    si,offset templp    ; path part
  1277.     call    strcpy            ; copy that much
  1278.     mov    si,offset templf    ; get rebuilt filename part
  1279.     call    strcat            ; paste that to the end
  1280.     mov    ax,offset rdbuf        ; point to full name
  1281.     call    isfile            ; does it exist?
  1282.     jc    uniq6            ; c = no, succeed now
  1283.  
  1284.     inc    unum            ; move to next generation
  1285.     mov    di,offset templf+7    ; point to last name char
  1286.     mov    cx,7            ; max # of digits to play with
  1287.     mov    bx,10            ; divisor (16 bits)
  1288.     mov    ax,unum            ; low order part of generation #
  1289. uniq5:    xor    dx,dx            ; high order part of generation #
  1290.     div    bx            ; compute digit (unum / 10)
  1291.     add    dl,'0'            ; make remainder part printable
  1292.     mov    [di],dl            ; put into right place
  1293.     or    ax,ax            ; any more to do? (quotient nonzero)
  1294.     jz    uniq4            ; z = no, try this name
  1295.     dec    di            ; else decrement char position
  1296.     loop    uniq5            ;   and keep making a number
  1297.     stc                ; failure: set carry, keep old name
  1298.     jmp    short uniq7        ;   and exit
  1299.  
  1300. uniq6:    pop    di            ; address of original filename
  1301.     push    ax            ; save for exit clean up
  1302.     mov    si,offset rdbuf
  1303.     call    strcpy            ; copy new filename over old
  1304.     clc                ; success: clear carry flag
  1305. uniq7:    pop    ax
  1306.     pop    es
  1307.     pop    di
  1308.     pop    si
  1309.     pop    dx
  1310.     pop    cx
  1311.     pop    bx
  1312.     ret
  1313. unique    endp
  1314.     
  1315.  
  1316. ;    [jrd]
  1317. ; strlen -- computes the length, excluding the terminator, of an asciiz
  1318. ;    string. Input: ds:dx = address of the string
  1319. ;        Output: cx = the byte count
  1320. ;    All registers except cx are preserved
  1321. ;
  1322. STRLEN    PROC    NEAR
  1323.     push    di
  1324.     push    es
  1325.     push    ax
  1326.     mov    ax,ds            ; use proper segment address
  1327.     mov    es,ax
  1328.     mov    di,dx
  1329.     mov    cx,0ffffh        ; large byte count
  1330.     cld                ; set direction to be forward
  1331.     xor    al,al            ; item sought is a null
  1332.     repne    scasb            ; search for it
  1333.     add    cx,2            ; add for -1 and auto dec in scasb
  1334.     neg    cx              ; convert to count, excluding terminator
  1335.     pop    ax
  1336.     pop    es
  1337.     pop    di
  1338.     ret
  1339. STRLEN    ENDP
  1340.  
  1341. ;    [jrd]
  1342. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  1343. ;    offset of string 1 is expected to be in ds:di. input & output
  1344. ;    offset of string 2 is expected to be in ds:si. input only (unchanged)
  1345. ;    Preserves all registers. No error returns, returns normally via ret
  1346. ;
  1347. STRCAT    PROC    NEAR
  1348.     push    di            ; save work registers
  1349.     push    si
  1350.     push    es
  1351.     push    dx
  1352.     push    cx
  1353.     push    ax
  1354.     mov    ax,ds            ; get data segment value
  1355.     mov    es,ax            ; set es to ds for implied es:di usage
  1356.     mov    dx,di
  1357.     call    strlen        ; get length (w/o terminator) of dest string
  1358.     add    di,cx            ; address of first terminator
  1359.     mov    dx,si            ; start offset of source string
  1360.     call    strlen            ; find its length too (in cx)
  1361.     inc    cx            ; include its terminator in the count
  1362.     rep    movsb        ; copy source string to end of output string
  1363.     pop    ax
  1364.     pop    cx
  1365.     pop    dx
  1366.     pop    es
  1367.     pop    si
  1368.     pop    di
  1369.     ret
  1370. STRCAT    ENDP
  1371.  
  1372. ;    [jrd]
  1373. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  1374. ;    ds:di. Returns via ret. All registers are preserved
  1375. ;
  1376. STRCPY    PROC    NEAR
  1377.     mov    byte ptr [di],0        ; clear destination string
  1378.     call    strcat            ; let strcat do the real work
  1379.     ret
  1380. STRCPY    ENDP
  1381.  
  1382. ;    [jrd]
  1383. ; fparse -- separate the drive:path part from the filename.ext part of an
  1384. ;    asciiz string. Characters separating parts are  \ or / or :
  1385. ;    Inputs:    asciiz input full filename string offset in ds:dx
  1386. ;        asciiz path offset in ds:di
  1387. ;        asciiz filename offset in ds:si
  1388. ;    Outputs: the above strings in the indicated spots
  1389. ;    Strategy is simple. Reverse scan input string until one of the
  1390. ;    three separators is encountered and then cleave at that point
  1391. ;    Simple filename construction restrictions added 30 Dec 1985;
  1392. ;    to wit: mainname limited to 8 chars or less,
  1393. ;    extension field limited to 3 chars or less and is found by searching
  1394. ;    for first occurence of a dot in the filename field. Thus the whole
  1395. ;    filename part is restricted to 12 (8+dot+3) chars plus a null
  1396. ;    All registers are preserved. Return is always via ret
  1397. ;    (Microsoft should have written this for DOS 2.x et seq.)
  1398.  
  1399. FPARSE    PROC    NEAR
  1400.     push    cx            ; local counter
  1401.     push    ax            ; local work area
  1402.     push    es            ; implied segment register for di
  1403.     push    di            ; offset of path part of output
  1404.     push    si            ; offset of file name part of output
  1405.     mov    ax,ds            ; get data segment value
  1406.     mov    es,ax            ; set es to ds for implied es:di usage
  1407.     mov    byte ptr [si],0        ; clear outputs
  1408.     mov    byte ptr [di],0
  1409.  
  1410.     push    si            ; save original file name address
  1411.     mov    si,dx            ; get original string address
  1412.     call    strcpy            ; copy string to original di
  1413.     call    strlen            ; find length (w/o terminator), in cx
  1414.     mov    si,di            ; address of string start
  1415.     add    si,cx
  1416.     dec    si            ; si = address of last non-null char
  1417.     jcxz    fpars5            ; if null skip the path scan
  1418.                     ; now find last path char, if any
  1419.                     ; start at the end of input string
  1420.     std                 ; set direction to be backward
  1421. fpars4:    lodsb                 ; get a byte (dec's si afterward)
  1422.     cmp    al,5ch            ; is it a backslash ('\')? 
  1423.     je    fpars6          ; e = yes
  1424.     cmp    al,2fh            ; or forward slash ('/')?
  1425.     je    fpars6          ; e = yes
  1426.     cmp    al,3ah            ; or even the drive terminator colon?
  1427.     je    fpars6            ; e = yes
  1428.     loop    fpars4             ; else keep looking until cx == 0
  1429.                       ; si is at beginning of file name
  1430. fpars5:    dec    si            ; dec for inc below
  1431. fpars6:    inc    si
  1432.     inc    si            ; si now points at first filename char
  1433.                     ; cx holds number of path chars
  1434.                     ; get original file name address (si)
  1435.     pop    di            ; and make it place to copy filename
  1436.     cld                ; reset direction to be forward
  1437.     mov    ax,si            ; ax holds filename address for awhile
  1438.     push    dx
  1439.     mov    dx,si            ; strlen wants string pointer in dx
  1440.     call    strlen            ; get length of filename part into cx
  1441.     pop    dx
  1442.     jcxz    fpar7a            ; any chars to look at? z = no
  1443. fpars7:    cmp    byte ptr [si],'.'    ; look for a dot in filename
  1444.     je    fpars8            ; e = found one
  1445.     inc    si            ; look at next filename char
  1446.     loop    fpars7            ; keep looking until cx = zero
  1447. fpar7a:    mov    si,ax            ; no dot. recover starting address
  1448.     mov    byte ptr [si+8],0    ; forcably truncate mainname to 8 char
  1449.     call    strcpy            ; copy this part to filename field
  1450.     jmp    fparsx            ;  and exit
  1451. fpars8: mov    byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  1452.     mov    cx,si
  1453.     sub    cx,ax        ; cx now = number of chars in mainname field
  1454.     cmp    cx,9            ; more than 8?
  1455.     jb    fpars9            ; b = no, we're safe
  1456.     mov    cx,8             ; limit ourselves to 8 chars in mainname
  1457. fpars9: push    si             ; remember address of dot and extension
  1458.     mov    si,ax            ; point to start of input filename
  1459.     rep    movsb            ; copy cx chars from si to di (output)
  1460.     mov    byte ptr [di],0        ; plant terminator where dot goes
  1461.     pop    si            ; source = dot and extension address
  1462.     call    strcat        ; append the dot & ext to the filename field
  1463. fparsx: mov    si,ax        ; recover start of filename in input string
  1464.     mov    byte ptr [si],0        ; terminate path field
  1465.     pop    si
  1466.     pop    di
  1467.     pop    es
  1468.     pop    ax
  1469.     pop    cx
  1470.     ret
  1471. FPARSE    ENDP    
  1472.  
  1473. ; Print filename in offset diskio.string.
  1474. PRTFN    PROC    NEAR
  1475.     test    flags.remflg,dquiet    ; quiet display mode?
  1476.     jnz    prtfn1            ; nz = yes, don't display filename
  1477.     push    ax            ; saves for messy clrfln routine
  1478.     push    bx
  1479.     push    dx
  1480.     call    clrfln            ; position cursor & blank out the line
  1481.     mov    dx,offset diskio.string
  1482.     call    prtasz
  1483.     pop    dx
  1484.     pop    bx
  1485.     pop    ax
  1486. prtfn1:    ret
  1487. PRTFN    ENDP
  1488.  
  1489.  
  1490. ; Print string to screen from offset ds:di for # bytes given in cx,
  1491. ; regardless of $'s.  All registers are preserved.        [jrd]
  1492.  
  1493. PRTSCR    PROC    NEAR
  1494.     jcxz    prtscr4            ; cx = zero means nothing to show
  1495.     push    ax
  1496.     push    bx
  1497.     push    dx
  1498.     mov    dx,di            ; source ptr for DOS
  1499.     cmp    flags.eofcz,0        ; end on Control-Z?
  1500.     jne    prtscr3            ; ne = yes, let DOS do it
  1501.     push    cx            ; else map Control-Z to space
  1502.     push    di
  1503.     push    es
  1504.     push    ds
  1505.     pop    es            ; data to es
  1506.     mov    al,ctlz            ; look for Control-Z
  1507.     cld                ; scan buffer es:di, cx chars worth
  1508. prtscr1:repne    scasb
  1509.     jne    prtscr2            ; ne = found no Control-Z's
  1510.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  1511.     jcxz    prtscr2            ; z = examined all chars
  1512.     jmp    short prtscr1        ; until examined everything
  1513. prtscr2:pop    es
  1514.     pop    di
  1515.     pop    cx
  1516. prtscr3:mov    bx,1            ; stdout file handle
  1517.     mov    ah,write2
  1518.     int    dos
  1519.     pop    dx
  1520.     pop    bx
  1521.     pop    ax
  1522. prtscr4:ret
  1523. PRTSCR    ENDP
  1524.  
  1525. ; Print to screen asciiz string given in ds:dx. Everything preserved. [jrd]
  1526. PRTASZ    PROC    NEAR
  1527.     push    cx
  1528.     push    di
  1529.     call    strlen            ; get length of asciiz string
  1530.     mov    di,dx            ; where prtscr looks
  1531.     call    prtscr            ; print counted string
  1532.     pop    di
  1533.     pop    cx
  1534.     ret
  1535. PRTASZ    ENDP
  1536.  
  1537. ;;; Load a translation table for file transfer
  1538. load    proc    near
  1539. ;;    mov    dx,offset loadtab    ; keyword Transfer-character-set
  1540. ;;    xor    bx,bx            ; help
  1541. ;;    mov    ah,cmkey
  1542. ;;    call    comnd
  1543. ;;    jnc    load0
  1544. ;;    ret
  1545. ;;load0:    mov    dx,offset rdbuf        ; buffer for filename
  1546. ;;    mov    word ptr rdbuf,0
  1547. ;;    mov    bx,offset loadhlp    ; help
  1548. ;;    mov    ah,cmword
  1549. ;;    call    comnd            ; get filename
  1550. ;;    jnc    load1            ; nc = success
  1551. ;;    ret                ; failure
  1552. ;;load1:    mov    ax,offset rdbuf        ; place for filename for isfile
  1553. ;;    call    isfile            ; does file exist?
  1554. ;;    jnc    load1b
  1555. ;;load1a:    mov    dx,offset infms6    ; unable to open file
  1556. ;;    mov    ah,prstr
  1557. ;;    int    dos
  1558. ;;    stc
  1559. ;;    ret                ; c = does not exist
  1560. ;;load1b:    mov    dx,ax
  1561. ;;    mov    cx,134
  1562. ;;    mov    ah,open2        ; file open
  1563. ;;    xor    al,al            ; 0 = open readonly
  1564. ;;    cmp    dosnum,300h        ; at or above DOS 2?
  1565. ;;    jb    load2            ; b = no, so no shared access
  1566. ;;    or    al,40h            ; open readonly, deny none
  1567. ;;load2:    int    dos
  1568. ;;    jc    load1a            ; if carry then error
  1569. ;;    mov    diskio.handle,ax    ; file handle
  1570. ;;                    ; read and parse lines
  1571. ;;    mov    linecnt,0        ; line counter
  1572. ;;    call    readln            ; L1, read and discard table name
  1573. ;;    jc    load5            ; c = failure
  1574. ;;    call    readln            ; L2, COMMON or LOCAL
  1575. ;;    jc    load5            ; c = failure
  1576. ;;    mov    ax,word ptr rdbuf
  1577. ;;    or    ax,2020h        ; to lower case
  1578. ;;    mov    tblptr,offset userin
  1579. ;;    cmp    ax,'oc'            ; "common"? (on the wire to local)
  1580. ;;    je    load4            ; e = yes
  1581. ;;    mov    tblptr,offset userout
  1582. ;;    cmp    ax,'ol'            ; "local"? (local to on the wire)
  1583. ;;    jne    load5            ; ne = no, fail
  1584. ;;
  1585. ;;load4:    call    readln            ; L3 name of comms line char set
  1586. ;;    jnc    load6            ; success
  1587. ;;load5:    jmp    loadx
  1588. ;;
  1589. ;;load6:    call    readln            ; L4 bytes per char in above set
  1590. ;;    jc    load5
  1591. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1592. ;;    call    atoi            ; ax has value
  1593. ;;    jc    load5            ; c = no number
  1594. ;;    cmp    ax,1            ; one byte per char?
  1595. ;;    jne    load5            ; ne = no, fail here
  1596. ;;
  1597. ;;    call    readln            ; L5 chars/plane (94/96/128)
  1598. ;;    jc    load7            ; c = failure
  1599. ;;    mov    dx,offset rdbuf
  1600. ;;    call    strlen
  1601. ;;    mov    ah,cl
  1602. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1603. ;;    call    atoi            ; ax has value
  1604. ;;    jc    load7            ; c = no number
  1605. ;;    cmp    ax,128            ; too many?
  1606. ;;    ja    load7            ; a = yes, fail here
  1607. ;;
  1608. ;;    call    readln            ; L6 name of local display char set
  1609. ;;    jnc    load8
  1610. ;;load7:    jmp    loadx
  1611. ;;
  1612. ;;load8:    call    readln            ; L7 bytes per char in above set
  1613. ;;    jc    load7
  1614. ;;    mov    dx,offset rdbuf
  1615. ;;    call    strlen
  1616. ;;    mov    ah,cl
  1617. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1618. ;;    call    atoi            ; ax has value
  1619. ;;    jc    load7            ; c = no number
  1620. ;;    cmp    ax,1            ; one byte per char?
  1621. ;;    jne    load7            ; ne = no, fail here
  1622. ;;
  1623. ;;    call    readln            ; L8 chars/plane (94/96/128)
  1624. ;;    jc    load7            ; failure
  1625. ;;    mov    dx,offset rdbuf
  1626. ;;    call    strlen
  1627. ;;    mov    ah,cl
  1628. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1629. ;;    call    atoi            ; ax has value
  1630. ;;    jc    load7            ; c = no number
  1631. ;;    cmp    ax,128            ; too many?
  1632. ;;    ja    load7            ; a = yes, fail here
  1633. ;;
  1634. ;;    call    readln            ; L9 designator of comms line set
  1635. ;;    jc    load8
  1636. ;;    call    readln            ; L10 Version of comms line set
  1637. ;;    jc    load8
  1638. ;;    call    readln            ; L11 Registration num of comms set
  1639. ;;    jc    load8
  1640. ;;    call    readln            ; L12 direction of writing
  1641. ;;    jc    load8
  1642. ;;    call    readln            ; L13 number of entries in table below
  1643. ;;    jc    load7
  1644. ;;    mov    dx,offset rdbuf
  1645. ;;    call    strlen
  1646. ;;    mov    ah,cl
  1647. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1648. ;;    call    atoi            ; ax has value
  1649. ;;    jc    load7            ; c = no number
  1650. ;;    mov    xlines,ax
  1651. ;;
  1652. ;;    call    readln            ; L14 count of filler lines before
  1653. ;;    jc    load7            ;  table below
  1654. ;;    mov    dx,offset rdbuf
  1655. ;;    call    strlen            ; length to cx
  1656. ;;    mov    ah,cl
  1657. ;;    mov    si,offset rdbuf        ; text, ah has char count
  1658. ;;    call    atoi            ; ax has value
  1659. ;;    jc    load7            ; c = no number
  1660. ;;    mov    cx,ax            ; count of filler lines
  1661. ;;    jcxz    load10            ; z = none
  1662. ;;load9:    push    cx
  1663. ;;    call    readln            ; L15 et seq, filler lines
  1664. ;;    pop    cx            ; read and discard
  1665. ;;    jc    loadx
  1666. ;;    loop    load9
  1667. ;;
  1668. ;;load10:    dec    xlines            ; Translation data lines
  1669. ;;    cmp    xlines,0        ; any left?
  1670. ;;    jge    load11            ; ge = yes
  1671. ;;    jmp    loady
  1672. ;;load11:    call    readln            ; translation table line(s)
  1673. ;;    jc    loadx            ; c = failure
  1674. ;;    mov    si,offset rdbuf        ; the buffer
  1675. ;;    mov    dx,si
  1676. ;;    call    strlen            ; length to cx
  1677. ;;    mov    ah,cl            ; count for atoi
  1678. ;;    call    atoi            ; get "from" number
  1679. ;;    jc    loadx            ; failure
  1680. ;;    test    al,80h            ; referring to high bit set (GR)?
  1681. ;;    jnz    load12            ; nz = yes
  1682. ;;    jmp    loadx
  1683. ;;load12:    and    ax,not 0ff80h        ; strip bit for GR table
  1684. ;;    mov    temp,ax            ; save here
  1685. ;;    mov    dx,si
  1686. ;;    call    strlen
  1687. ;;    mov    ah,cl            ; count
  1688. ;;    call    atoi            ; get "to" number
  1689. ;;    mov    bx,tblptr        ; point at table
  1690. ;;    add    bx,temp            ; locate entry
  1691. ;;    mov    [bx],al            ; store new value
  1692. ;;    jmp    load10            ; repeat til done
  1693. ;;
  1694. ;;loadx:    mov    dx,offset badvalue    ; complain
  1695. ;;    mov    ah,prstr
  1696. ;;    int    dos
  1697. ;;    mov    ax,linecnt        ; show line number
  1698. ;;    call    decout
  1699. ;;    mov    ah,conout
  1700. ;;    mov    dl,':'
  1701. ;;    int    dos
  1702. ;;    mov    dx,offset rdbuf        ; show the line
  1703. ;;    call    prtasz
  1704. ;;loady:    mov    bx,diskio.handle
  1705. ;;    mov    ah,close2        ; close the file
  1706. ;;    int    dos
  1707.     clc
  1708.     ret
  1709. load    endp
  1710. ;;
  1711. ;;readln    proc    near
  1712. ;;    push    ax
  1713. ;;    push    bx
  1714. ;;    push    cx
  1715. ;;    push    dx
  1716. ;;    push    di
  1717. ;;    inc    linecnt            ; line counter
  1718. ;;    mov    cx,82            ; 82 bytes, including trailer
  1719. ;;    mov    temp,0            ; leading whitespace and comment flgs
  1720. ;;    mov    di,offset rdbuf        ; destination buffer
  1721. ;;    mov    bx,diskio.handle    ; file handle
  1722. ;;readln1:push    cx            ; read from file
  1723. ;;    mov    cx,1            ; read 1 char
  1724. ;;    mov    dx,di            ; place here
  1725. ;;    mov    byte ptr [di],0        ; insert terminator
  1726. ;;    mov    ah,readf2
  1727. ;;    int    dos
  1728. ;;    pop    cx
  1729. ;;    jc    readlnx            ; c = read failure
  1730. ;;    or    ax,ax            ; count of bytes read
  1731. ;;    jz    readlnx            ; z means end of file
  1732. ;;    cmp    byte ptr [di],LF    ; LF?
  1733. ;;    je    readln3            ; e = yes, ignore it
  1734. ;;    cmp    byte ptr [di],CR    ; end of line?
  1735. ;;    je    readln4            ; e = yes, exit
  1736. ;;    cmp    byte ptr [di],';'    ; start of comment?
  1737. ;;    jne    readln6            ; ne = no
  1738. ;;    mov    byte ptr temp+1,1    ; say comment has started
  1739. ;;    jmp    short readln3        ; do not store it
  1740. ;;readln6:cmp    byte ptr temp+1,0    ; seen comment semicolon yet?
  1741. ;;    jne    readln3            ; ne = yes, do not store comment
  1742. ;;    cmp    byte ptr temp,0        ; seen non-spacing char yet?
  1743. ;;    jne    readln2            ; ne = yes
  1744. ;;    cmp    byte ptr [di],' '    ; is this a space?
  1745. ;;    je    readln3            ; e = yes, skip it
  1746. ;;    cmp    byte ptr [di],TAB    ; or a tab?
  1747. ;;    je    readln3            ; e = yes, skip it
  1748. ;;    mov    byte ptr temp,1        ; say have seen non-spacing char
  1749. ;;readln2:cmp    flags.takflg,0        ; echo Take files?
  1750. ;;    je    readln2a        ; e = no
  1751. ;;    mov    ah,conout
  1752. ;;    mov    dl,byte ptr [di]
  1753. ;;    int    dos
  1754. ;;readln2a:inc    di            ; next storage cell
  1755. ;;readln3:loop    readln1            ; loop til end of line
  1756. ;;readln4:cmp    flags.takflg,0        ; echo Take files?
  1757. ;;    je    readln4a        ; e = no
  1758. ;;    mov    ah,prstr
  1759. ;;    mov    dx,offset crlf
  1760. ;;    int    dos
  1761. ;;readln4a:clc
  1762. ;;    mov    byte ptr [di],0        ; insert final terminator
  1763. ;;    jmp    short readlnx
  1764. ;;
  1765. ;;readln5:stc                ; set carry for failure to read
  1766. ;;readlnx:pop    di
  1767. ;;    pop    dx
  1768. ;;    pop    cx
  1769. ;;    pop    bx
  1770. ;;    pop    ax
  1771. ;;    ret
  1772. ;;readln    endp
  1773. code    ends 
  1774.     end
  1775.