home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msvp98b1.lzh / MSSFIL.ASM < prev    next >
Assembly Source File  |  1993-05-14  |  83KB  |  2,375 lines

  1.     NAME    mssfil
  2. ; File MSSFIL.ASM
  3.     include mssdef.h
  4. ;  Copyright (C) 1985, 1992, Trustees of Columbia University in the 
  5. ;  City of New York.  Permission is granted to any individual or institution
  6. ;  to use this software as long as it is not sold for profit.  This copyright
  7. ;  notice must be retained.  This software may not be included in commercial
  8. ;  products without written permission of Columbia University.
  9. ;
  10. ; Edit history:
  11. ; 6 Sept 1991 version 3.11
  12. ; 2 March 1991 version 3.10
  13. ; Last edit 25 May 1992
  14.  
  15.     public    buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec
  16.     public    encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr
  17.     public    strlen, strcat, strcpy, tfilsz, templp, latin1, charids
  18.     public    L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique
  19.     public    load, cplatin, goopen
  20.  
  21. SIchar    equ    0fh
  22. SOchar    equ    0eh
  23. DLE    equ    10h
  24.  
  25. data    segment
  26.     extrn    flags:byte, trans:byte, denyflg:word, dosnum:word
  27.     extrn    oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte
  28.     extrn    curdsk:byte
  29.  
  30. ermes4  db    'Unable to make unique name',0
  31. ermes9    db    'Printer not ready',0
  32. erms12    db    'Unable to create file ',0
  33. erms13    db    'Error writing output file',0
  34. infms5  db    'Renaming file to $'
  35. infms6    db    cr,lf,'?Unable to open file$'
  36. asmsg    db    ' as $'
  37. crlf    db    cr,lf,'$'
  38. printer    db    'PRN',0
  39. screen    db    'CON',0
  40. loadhlp    db    'filename$'
  41.                 ; DOS special chars allowed in filenames
  42. spchar2    db    '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh
  43.     db    5fh, 5eh, 7eh, 60h
  44. spc2len    equ    $-spchar2
  45.  
  46. textctl    db    cr,lf,tab,bell,ff,ctlz    ; controls allowed in text files
  47. textctlen equ    $-textctl
  48.     even
  49. filflg    db    0        ; input buffer has data, if non-zero
  50. rptct    db    1        ; number of times it's repeated
  51. dblbyte    db    0        ; first of two bytes in a pair
  52. dblbyteflg db    0        ; non-zero if processing second byte of pair
  53. DLEseen    db    0
  54. shiftstate db    0        ; locking shift (0 = unshifted, 1 = shifted)
  55. decoutp    dw    0        ; ptr to proc to dump decode output buffer
  56. encinp    dw    0        ; ptr to proc to refill encode input buffer
  57. dchrcnt dw    0        ; number of chars in the decode file buffer
  58. echrcnt dw    0        ; number of chars in the encode file buffer
  59. dbufpnt dw    0        ; position in file buffer, decoder
  60. ebufpnt dw    0        ; position in file buffer, encoder
  61.                 ;
  62.     db    0        ; this MUST directly preceed decbuf, jpnwrite
  63. decbuf    db    512 dup (0)    ; decoding source buffer
  64.     db    0        ; safety for possible null terminator
  65. encbuf    db    512 dup (0)    ; encoding source buffer
  66.     db    0        ; safety for possible null terminator
  67.  
  68. tfilsz    dw    0,0        ; bytes transferred (double word qty)
  69. nmoflg    db    0        ; have override filename, if non-zero
  70. templp    db    65 dup (?)    ; temp for local path part
  71. templf    db    14 dup (?)    ; temp for local filename part
  72. temprp    db    65 dup (?)    ; temp for remote path part
  73. temprf    db    14 dup (?)    ; temp for remote filename part
  74. auxfile    db    65 dup (?)    ; auxillary filename for general use
  75. diskio    filest    <>        ; ditto, for ordinary file transfers
  76. buff    db    buffsz dup (?)    ; use as our Disk Transfer Area
  77. havdot    db    0        ; dot-found status in verify
  78. unum    dw    0        ; unique filename generation number
  79. temp    dw    0
  80.                 ; charids: table of transfer char-set idents
  81. charids dw    5        ; qty, pointers to char set idents
  82.     dw    chtrans,chlatin1,chcyrill,chjapan,chjapanold
  83. chtrans    db    1,'A'        ; Transparent: char count, ident
  84. chlatin1 db    6,'I6/100'    ; Latin1: char count, ident
  85. chcyrill db    6,'I6/144'    ; Cyrillic: char count, ident
  86. chjapan    db    9,'I14/87/13'    ; Japanese-EUC: char count, ident (new)
  87. chjapanold db    7,'I14/87E'    ; Japanese-EUC: char count, ident (obsolete)
  88.                 ; end of charids info
  89. ;loadtab    db    1        ; LOAD command table
  90. ;    mkeyw    'Transfer-character-set',0
  91. ;
  92. ;filtab    macro
  93. ;    cnt = 128
  94. ;    rept    128            ; 128 idenity entries
  95. ;    db    cnt            ; initialize table to 128 .. 255
  96. ;    cnt = cnt + 1
  97. ;    endm
  98. ;endm
  99. ;
  100. ;userin    equ    this byte        ; LOAD command
  101. ;    filtab                ; init table to idenity
  102. ;namein    db    20 dup (0)        ; name of the character set
  103. ;userout    equ    this byte
  104. ;    filtab                ; init table to idenity
  105. ;nameout db    20 dup (0)        ; name of the character set
  106. ;tblptr    dw    0            ; LOAD command
  107. ;xlines    dw    0            ; LOAD command
  108. ;linecnt dw    0            ; LOAD command
  109. ;badvalue db    cr,lf,'?Bad value on line $'
  110.  
  111. ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages
  112. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  113. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  114. ; Each table is 96 translatable bytes followed by the table size (96), the
  115. ; ISO announcer ident ('A' and a null here); LATIN5/Cyrillic uses 'L'.
  116. ; The decimal tables are from Frank da Cruz working with the formal IBM docs.
  117.                     ; from ISO 8859-1 Latin-1 to Code Page
  118.                             ; to CP437
  119. L1cp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  120.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  121.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  122.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  123.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  124.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  125.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  126.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  127.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  128.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  129.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  130.     db    4fh,55h,55h,55h,  9ah,59h,3fh,0e1h
  131.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  132.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  133.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  134.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,98h
  135.     db    96,'A',0            ; 96 byte set, letter ident
  136.  
  137.                             ; to CP850
  138. L1cp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  139.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  140.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  141.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  142.     db    20h,0adh,0bdh,9ch,  0cfh,0beh,0ddh,0f5h    ; column 10
  143.     db    0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh
  144.     db    0f8h,0f1h,0fdh,0fch, 0efh,0e6h,0f4h,0fah ; column 11
  145.     db    0f7h,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h
  146.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  147.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  148.     db    0d1h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,9eh    ; column 13
  149.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,0e8h,0e1h
  150.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  151.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  152.     db    0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h    ; column 15
  153.     db    9bh,97h,0a3h,96h,   81h,0ech,0e7h,98h
  154.     db    96,'A',0            ; 96 byte set, letter ident
  155.  
  156.                             ; to CP860
  157. L1cp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  158.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  159.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  160.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  161.     db    20h,0adh,9bh,9ch,  0fh,59h,7ch,15h    ; column 10
  162.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  163.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  164.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  165.     db    91h,86h,8fh,8eh,   41h,41h,41h,80h    ; column 12
  166.     db    92h,90h,89h,45h,   8bh,98h,49h,49h
  167.     db    44h,0a5h,0a9h,9fh, 8ch,99h,4fh,58h    ; column 13
  168.     db    4fh,9dh,96h,55h,   9ah,59h,3fh,0e1h
  169.     db    85h,0a0h,83h,84h,  61h,61h,61h,87h    ; column 14
  170.     db    8ah,82h,88h,65h,   8dh,0a1h,69h,69h
  171.     db    3fh,0a4h,95h,0a2h, 93h,94h,6fh,0f6h    ; column 15
  172.     db    6fh,97h,0a3h,75h,  81h,79h,3fh,79h
  173.     db    96,'A',0            ; 96 byte set, letter ident
  174.                             ; to CP863
  175. L1cp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  176.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  177.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  178.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  179.     db    20h,3fh,9bh,9ch,   98h,59h,0a0h,8fh    ; column 10
  180.     db    0a4h,40h,61h,0aeh, 0aah,0c4h,3fh,0a7h
  181.     db    0f8h,0f1h,0fdh,0a6h, 0a1h,0e6h,86h,0fah    ; column 11
  182.     db    0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh
  183.     db    8eh,41h,84h,41h,   41h,41h,41h,80h    ; column 12
  184.     db    91h,90h,92h,94h,   49h,49h,0a8h,95h
  185.     db    44h,4eh,4fh,4fh,   99h,4fh,4fh,58h    ; column 13
  186.     db    4fh,9dh,55h,9eh,   9ah,59h,3fh,0e1h
  187.     db    85h,61h,83h,61h,   61h,61h,61h,87h    ; column 14
  188.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  189.     db    3fh,6eh,6fh,0a2h,  93h,6fh,6fh,0f6h    ; column 15
  190.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,79h
  191.     db    96,'A',0            ; 96 byte set, letter ident
  192.                             ; to CP865
  193. L1cp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  194.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  195.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  196.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  197.     db    20h,0adh,3fh,9ch,  0afh,59h,7ch,15h    ; column 10
  198.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,0c4h
  199.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  200.     db    2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h
  201.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  202.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  203.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  204.     db    9dh,55h,55h,55h,  9ah,59h,3fh,0e1h
  205.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  206.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  207.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  208.     db    9bh,97h,0a3h,96h,  81h,79h,3fh,98h
  209.     db    96,'A',0            ; 96 byte set, letter ident
  210.                             ; Latin5 to CP866
  211. L5cp866    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  212.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  213.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  214.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  215.     db    0ffh,0f0h,3fh,3fh,  0f2h,53h,49h,4fh    ; column 10
  216.     db    4ah,3fh,3fh,48h,   4bh,2dh,0f6h,3fh
  217.     db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 11
  218.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  219.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 12
  220.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  221.     db    0a0h,0a1h,0a2h,0a3h,0a4h,0a5h,0a6h,0a7h ; column 13
  222.     db    0a8h,0a9h,0aah,0abh,0ach,0adh,0aeh,0afh
  223.     db    0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h ; column 14
  224.     db    0e8h,0e9h,0eah,0ebh,0ech,0edh,0eeh,0efh
  225.     db    0fch,0f1h,3fh,3fh, 0f3h,73h,69h,0f5h    ; column 15
  226.     db    6ah,3fh,3fh,68h,   6bh,15h,0f7h,3fh
  227.     db    96,'L',0            ; 96 byte set, Latin5/Cyrillic
  228.  
  229.  
  230. ;yl143[]   /* Latin-1 to IBM Code Page 437 */
  231. ; Although the IBM CDRA does not include an official translation between CP437
  232. ; and ISO Latin Alphabet 1, it does include an official, invertible
  233. ; translation between CP437 and CP850 (page 196), and another from CP850 to
  234. ; Latin-1 (CP819) (page 153).  This translation was obtained with a two-step
  235. ; process based on those tables.
  236.  
  237. iL1cp437 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  238.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  239.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  240.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  241.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  242.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  243.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  244.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  245.     db 96,'A',0                ; 96 byte set, letter ident
  246.  
  247. ;yl185[]   /* Latin-1 to IBM Code Page 850 */
  248. ; This is IBM's official invertible translation.  Reference: IBM Character
  249. ; Data Representation Architecture (CDRA), Level 1, Registry, SC09-1291-00
  250. ; (1990), p.152.  (Note: Latin-1 is IBM Code Page 00819.)
  251. iL1cp850 db 186,205,201,187,200,188,204,185,203,202,206,223,220,219,254,242
  252.     db 179,196,218,191,192,217,195,180,194,193,197,176,177,178,213,159
  253.     db 255,173,189,156,207,190,221,245,249,184,166,174,170,240,169,238
  254.     db 248,241,253,252,239,230,244,250,247,251,167,175,172,171,243,168
  255.     db 183,181,182,199,142,143,146,128,212,144,210,211,222,214,215,216
  256.     db 209,165,227,224,226,229,153,158,157,235,233,234,154,237,232,225
  257.     db 133,160,131,198,132,134,145,135,138,130,136,137,141,161,140,139
  258.     db 208,164,149,162,147,228,148,246,155,151,163,150,129,236,231,152
  259.     db 96,'A',0                ; 96 byte set, letter ident
  260.  
  261. ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin1 or Latin5
  262. ; For GRight only (high bit set).
  263.                             ; from Code Page 437
  264. cp437L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  265.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  266.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  267.     db    0ffh,0d6h,0dch,0a2h, 0a3h,0a5h,3fh,3fh
  268.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  269.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  270.     db    16 dup (3fh)                 ; column 11
  271.     db    16 dup (3fh)                 ; column 12
  272.     db    16 dup (3fh)                 ; column 13
  273.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  274.     db    5 dup(3fh),            0f8h,3fh,3fh
  275.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  276.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  277.                              ; from Code Page 850
  278. cp850L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  279.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  280.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  281.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,0d7h,3fh
  282.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  283.     db    0bfh,0aeh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  284.     db    5 dup (3fh),              0c1h,0c2h,0c0h ; column 11
  285.     db    0a9h, 4 dup (3fh),      0a2h,0a5h,3fh
  286.     db    6 dup (3fh),0e3h,0c3h, 7 dup (3fh),0a4h     ; column 12
  287.     db    0f0h,0d0h,0cah,0cbh, 0c8h,0b9h,0cdh,0ceh ; column 13
  288.     db    0cfh, 4 dup (3fh),       0a6h,0cch,3fh
  289.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0feh ; column 14
  290.     db    0deh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  291.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,0f7h,0b8h ; column 15
  292.     db    0b0h,0a8h,0b7h,0b9h, 0b3h,0b2h,3fh,20h
  293.  
  294.                              ; from Code Page 860
  295. cp860L1    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  296.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  297.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  298.     db    0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  299.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  300.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  301.     db    16 dup (3fh)                 ; column 11
  302.     db    16 dup (3fh)                 ; column 12
  303.     db    16 dup (3fh)                 ; column 13
  304.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  305.     db    5 dup(3fh),            0f8h,3fh,3fh
  306.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  307.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  308.                              ; from Code Page 863
  309. cp863L1    db    0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8
  310.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  311.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9
  312.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  313.     db    0a6h,0b4h,0f3h,0fah, 0a8h,0b8h,0b3h,0afh ; column 10
  314.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  315.     db    16 dup (3fh)                 ; column 11
  316.     db    16 dup (3fh)                 ; column 12
  317.     db    16 dup (3fh)                 ; column 13
  318.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  319.     db    5 dup(3fh),            0f8h,3fh,3fh
  320.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  321.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  322.                                   ; from Code Page 865
  323. cp865L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  324.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  325.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  326.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  327.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  328.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  329.     db    16 dup (3fh)                 ; column 11
  330.     db    16 dup (3fh)                 ; column 12
  331.     db    16 dup (3fh)                 ; column 13
  332.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  333.     db    5 dup(3fh),            0f8h,3fh,3fh
  334.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  335.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  336.                      ; from Code Page 866 to LATIN5
  337. cp866L5    db    0b0h,0b1h,0b2h,0b3h, 0b4h,0b5h,0b6h,0b7h ; column 8
  338.     db    0b8h,0b9h,0bah,0bbh, 0bch,0bdh,0beh,0bfh
  339.     db    0c0h,0c1h,0c2h,0c3h, 0c4h,0c5h,0c6h,0c7h ; column 9
  340.     db    0c8h,0c9h,0cah,0cbh, 0cch,0cdh,0ceh,0cfh
  341.     db    0d0h,0d1h,0d2h,0d3h, 0d4h,0d5h,0d6h,0d7h ; column 10
  342.     db    0d8h,0d9h,0dah,0dbh, 0dch,0ddh,0deh,0dfh
  343.     db    16 dup (3fh)                 ; column 11
  344.     db    16 dup (3fh)                 ; column 12
  345.     db    16 dup (3fh)                 ; column 13
  346.     db    0e0h,0e1h,0e2h,0e3h, 0e4h,0e5h,0e6h,0e7h ; column 14
  347.     db    0e8h,0e9h,0eah,0ebh, 0ech,0edh,0eeh,0efh
  348.     db    0a1h,0f1h,0a4h,0f4h, 0a7h,0f7h,0aeh,0feh ; column 15
  349.     db    4 dup (3fh),         0f0h,3fh,3fh,0a0h
  350.  
  351. ;y43l1[]   /* IBM Code Page 437 to Latin-1 */
  352. ;  This table is the inverse of yl143[].
  353. icp437L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  354.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  355.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  356.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  357.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  358.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  359.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  360.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  361.  
  362. ;y85l1[]   /* IBM Code Page 850 to Latin-1 */
  363. ;  This is from IBM CDRA page 153.  It is the inverse of yl185[].
  364. icp850L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  365.     db 201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,159
  366.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  367.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,162,165,147
  368.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  369.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  370.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  371.     db 173,177,143,190,182,167,247,184,176,168,183,185,179,178,142,160
  372. data    ends
  373.  
  374. code    segment
  375.     extrn    decout:near, isfile:near, newfn:near, comnd:near, atoi:near
  376.     extrn    ermsg:near, clrfln:near, frpos:near, kbpr:near, perpr:near
  377.  
  378.     assume  cs:code, ds:data, es:nothing
  379.  
  380. ; Set register SI to the offset of the ISO Latin-1 table appropriate to the
  381. ; currently active Code Page. Defaults to CP437 if no CP found.
  382. LATIN1    proc    near
  383.     push    ax
  384.     mov    ax,flags.chrset
  385.     mov    si,offset L1cp437    ; assume CP437
  386.     cmp    ax,437            ; current Code Page is 437?
  387.     je    latin1x            ; e = yes
  388.     mov    si,offset L1cp850    ; assume CP850
  389.     cmp    ax,850            ; current Code Page is 850?
  390.     je    latin1x            ; e = yes
  391.     mov    si,offset L1cp860    ; assume CP860
  392.     cmp    ax,860            ; current Code Page is 860?
  393.     je    latin1x            ; e = yes
  394.     mov    si,offset L1cp863    ; assume CP863
  395.     cmp    ax,863            ; current Code Page is 863?
  396.     je    latin1x            ; e = yes
  397.     mov    si,offset L1cp865    ; assume CP865
  398.     cmp    ax,865            ; current Code Page is 865?
  399.     je    latin1x            ; e = yes
  400.     mov    si,offset L5cp866    ; assume CP866
  401.     cmp    ax,866            ; current Code Page is 866?
  402.     je    latin1x            ; e = yes
  403. ;    mov    si,offset userin    ; user loadable incoming table
  404. ;    cmp    ax,1            ; User-defined table?
  405. ;    je    latin1x            ; e = yes
  406.     mov    si,offset L1cp437    ; default to CP437
  407. latin1x:pop    ax
  408.     ret
  409. LATIN1    endp
  410.  
  411. ; Call after LATIN1. Revise BX to point to invertible tables rather than
  412. ; readable translation tables.
  413. latininv proc    near
  414.     cmp    trans.xchri,0        ; readable (vs invertible)?
  415.     je    latinvx            ; e = yes, do nothing
  416.     cmp    si,offset L1cp437    ; this table in use?
  417.     jne    latinv1            ; ne = no
  418.     mov    si,offset iL1cp437    ; use invertible instead
  419.     ret
  420. latinv1:cmp    si,offset L1cp850    ; this table in use?
  421.     jne    latinvx            ; ne = no
  422.     mov    si,offset iL1cp850    ; use invertible instead
  423. latinvx:ret
  424. latininv endp
  425.  
  426. ; Set reg BX to offset of table for Code Page to ISO 8859-1 Latin1/Latin5
  427. cplatin proc    near
  428.     push    ax
  429.     mov    ax,flags.chrset
  430.     mov    bx,offset cp437L1    ; assume CP437
  431.     cmp    ax,437            ; current Code Page is 437?
  432.     je    cplatx            ; e = yes
  433.     mov    bx,offset cp850L1    ; assume CP850
  434.     cmp    ax,850            ; current Code Page is 850?
  435.     je    cplatx            ; e = yes
  436.     mov    bx,offset cp860L1    ; assume CP860
  437.     cmp    ax,860            ; current Code Page is 860?
  438.     je    cplatx            ; e = yes
  439.     mov    bx,offset cp863L1    ; assume CP863
  440.     cmp    ax,863            ; current Code Page is 863?
  441.     je    cplatx            ; e = yes
  442.     mov    bx,offset cp865L1    ; assume CP865
  443.     cmp    ax,865            ; current Code Page is 865?
  444.     je    cplatx            ; e = yes
  445.     mov    bx,offset cp866L5    ; assume CP866 for LATIN5
  446.     cmp    ax,866            ; corrent Code Page is 866?
  447.     je    cplatx            ; e = yes
  448. ;    mov    bx,offset userout    ; user loadable outgoing table
  449. ;    cmp    ax,1            ; User-table?
  450. ;    je    cplatx            ; e = yes
  451.     mov    bx,offset cp437L1    ; default to CP437
  452. cplatx:    pop    ax
  453.     ret
  454. cplatin endp
  455.  
  456. ; Call after CPLATIN. Revise BX to point to invertible tables rather than
  457. ; readable translation tables.
  458. cpinvert proc    near
  459.     cmp    trans.xchri,0        ; readable (vs invertible)?
  460.     je    cpinverx        ; e = yes, do nothing
  461.     cmp    bx,offset cp437L1    ; this table in use?
  462.     jne    cpinver1        ; ne = no
  463.     mov    bx,offset icp437L1    ; use invertible instead
  464.     ret
  465. cpinver1:cmp    bx,offset cp850L1    ; this table in use?
  466.     jne    cpinverx        ; ne = no
  467.     mov    bx,offset icp850L1    ; use invertible instead
  468. cpinverx:ret
  469. cpinvert endp
  470.  
  471. ; Output the chars in a packet, called only by receiver code.
  472. ; Enter with SI equal to pktinfo structure pointer.
  473. PTCHR:    mov    decoutp,offset outbuf  ; routine to call when buffer gets full
  474.     jmp    short decode
  475.  
  476.  
  477. ; Dodecoding.
  478. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ???
  479. ; Modifies regs BX, CX.
  480. ; Enter with SI equal to pktinfo structure pointer.
  481. dodec    proc    near
  482.     push    ax            ; save reg
  483.     mov    ah,dblbyteflg        ; preserve state
  484.     mov    al,dblbyte
  485.     push    ax
  486.     mov    al,shiftstate
  487.     mov    ah,DLEseen
  488.     push    ax
  489.     mov    dblbyteflg,0        ; init decode as doubles
  490.     mov    shiftstate,0        ; init shift states
  491.     mov    DLEseen,0        ; init escape
  492.     mov    decoutp,offset dnulr    ; routine to dump buffer (null)
  493.     call    decode
  494.     pop    ax
  495.     mov    shiftstate,al        ; restore decoder state
  496.     mov    DLEseen,ah
  497.     pop    ax
  498.     mov    dblbyteflg,ah
  499.     mov    dblbyte,al
  500.     push    bx
  501.     mov    bx,dbufpnt        ; next char position
  502.     mov    byte ptr [bx],0        ; null terminator
  503.     pop    bx
  504.      pop    ax
  505.     ret
  506. dodec    endp
  507.  
  508. dnulr:    ret                ; dummy buffer emptier
  509.  
  510. ; Enter with [si].datlen = length of data, [si].datadr = address of data,
  511. ; DECOUTP = pointer to routine which writes output buffer
  512. ; Returns DBUFPNT = pointer to output buffer address (offset part).
  513. ; Trans.lshift is non-zero if locking shift encoding is active.
  514. ; DLEseen is non-zero if a DLE char (Control-P) is decoded while locking shift
  515. ; is active; under these circumstances DLE escapes DLE, SI, and SO to be
  516. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  517. ; data to non-high bit data (and we thus reverse this); SI (Control-O)
  518. ; cancels SO.
  519. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  520. ; performing Japanese translation; dblbyte is the first byte of the pair.
  521. ; All packets are decoded except I, S, and A types.
  522. ; Flushes output buffer before returning.
  523. ; Returns carry clear if success, otherwise carry set
  524. decode    proc    near
  525.     push    si
  526.     push    di
  527.     push    es
  528.     push    dx
  529.     push    ds
  530.     pop    es            ; set es to data segment
  531.     cld                ; forward direction
  532.     mov    dchrcnt,length decbuf    ; size of output buffer
  533.     mov    dbufpnt,offset decbuf ; decoded data placed here pending output
  534.     mov    cx,[si].datlen        ; length of source buffer data
  535.     mov    si,[si].datadr        ; source buffer address
  536.     mov    di,dbufpnt        ; destination of data
  537.     mov    bl,trans.squote        ; regular quote char
  538.     xor    dh,dh            ; assume no quote char
  539.     cmp    trans.ebquot,'N'    ; any 8-bit quoting?
  540.     je    decod1            ; e = no quoting
  541.     cmp    trans.ebquot,'Y'    ; or not doing it?
  542.     je    decod1            ; e = no need to quote
  543.     mov    dh,trans.ebquot        ; otherwise use 8-bit quote char
  544.  
  545. decod1:    mov    rptct,1            ; reset repeat count
  546.     or    cx,cx            ; any more chars in source?
  547.     jg    decod2            ; g = yes
  548.     jmp    decod6            ; else, we're through
  549. decod2:    lodsb                ; pick up a char
  550.     dec    cx            ; count number left
  551.     cmp    al,trans.rptq        ; repeat quote char?
  552.     jne    dcod2a            ; ne = no, continue processing it
  553.     or    al,al            ; doing repeat quoting? (0 if no)
  554.     jz    dcod2a            ; z = no, skip this part
  555.     lodsb                ; get the size
  556.     dec    cx            ; modify buffer count
  557.     sub    al,20H            ; make count numeric
  558.     mov    rptct,al        ; remember how many repetitions
  559.     lodsb                ; get the char to repeat
  560.     dec    cx            ; modify buffer count
  561.  
  562. dcod2a:    xor    ah,ah            ; assume no 8-bit quote char
  563.     cmp    al,dh            ; is this the 8-bit quot char?
  564.     jne    decod3            ; ne = no
  565.     lodsb                ; yes, get the real character
  566.     dec    cx            ; decrement # chars in packet
  567.     mov    ah,80H            ; turn on high bit
  568. decod3:    cmp    al,bl            ; quote char?
  569.     jne    decod4            ; ne = no, proceed
  570.     lodsb                ; get the quoted character
  571.     dec    cx            ; decrement # of chars in packet
  572.     or    ah,al            ; save parity (combine with prefix)
  573.     and    ax,807fh        ; only parity in ah, remove it in al
  574.     cmp    al,bl            ; quote char?
  575.     je    decod4            ; e = yes, just go write it out
  576.     cmp    al,dh            ; 8-bit quote char?
  577.     je    decod4            ; e = yes, just go write it out
  578.     cmp    al,trans.rptq        ; repeat quote character?
  579.     je    decod4            ; e = yes, just write it out
  580.     cmp    al,3fh            ; char less than '?' ?
  581.     jb    decod4            ; b = yes; leave it intact
  582.     cmp    al,5fh            ; char greater than '_' ?
  583.     ja    decod4            ; a = yes; leave it alone
  584.     add    al,40H            ; make it a control char again
  585.     and    al,7FH            ; modulo 128 (includes DEL)
  586. decod4:    xor    ah,shiftstate        ; modify high bit by shiftstate
  587.         or    al,ah            ; or in parity
  588.  
  589.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  590.     je    decod5            ; e = yes
  591.     mov    ah,al
  592.     xor    ah,shiftstate        ; adjust high bit by shift state
  593.     cmp    ah,DLE            ; DLE?
  594.     jne    dcod4c            ; ne = no
  595.     cmp    DLEseen,0        ; has DLE been escaped (by DLE)?
  596.     je    dcod4b            ; e = no, make this the escape
  597.     mov    DLEseen,0        ; unescape now
  598.     jmp    short decod5        ; process the literal DLE
  599.                     ; handle repeat counted DLE's
  600. dcod4b:    shr    rptct,1            ; divide by two, carry has lsb
  601.     rcl    DLEseen,1        ; pickup carry bit if odd number
  602.     jmp    short decod5        ; write the DLE's
  603.  
  604. dcod4c:    cmp    DLEseen,0        ; DLE prefix seen?
  605.     mov    DLEseen,0        ; clear it now too
  606.     jne    decod5            ; ne = yes, prefixed, do literal
  607.     cmp    ah,SIchar        ; SI?
  608.     jne    dcod4d            ; ne = no
  609.     mov    shiftstate,0        ; say exiting shifted state
  610.     jmp    decod1            ; nothing to write
  611. dcod4d:    cmp    ah,SOchar        ; SO?
  612.     jne    decod5            ; ne = no
  613.     mov    shiftstate,80h        ; say entering shifted state
  614.     jmp    decod1            ; nothing to write
  615.  
  616. decod5:    push    cx
  617.     mov    cl,rptct        ; repeat count
  618.     xor    ch,ch
  619.     or    cl,cl
  620.     jle    decod5c            ; le = nothing to do (94 max)
  621.     cmp    cx,dchrcnt        ; needed vs space available
  622.     jbe    decod5a            ; be = enough space for rptct chars
  623.     mov    cx,dchrcnt        ; insufficient space, do dchrcnt
  624. decod5a:sub    rptct,cl        ; reduce number left to be written
  625.     sub    dchrcnt,cx        ; reduce output free space
  626.     pushf                ; save sub status flags
  627.     shr    cx,1
  628.     jnc    decod5b            ; nc = an even number
  629.     stosb                ; store the odd byte
  630.     jcxz    decod5d            ; z = nothing else to write
  631. decod5b:mov    ah,al            ; make a copy for word writes
  632.     rep    stosw            ; store cx words
  633. decod5d:popf                ; recover flags from sub dchrcnt,cx
  634.     jg    decod5c            ; g = space remaining in output buffer
  635.     push    dx            ; flush output buffer
  636.     push    bx
  637.     push    ax            ; save the char
  638.     call    decoutp            ; output the buffer
  639.     pop    ax            ; recover repeated char
  640.     pop    bx
  641.     pop    dx
  642.     jc    decod7            ; c = error if disk is full
  643.     mov    di,dbufpnt
  644.     pop    cx
  645.     jmp    short decod5        ; see if more chars need be written
  646. decod5c:pop    cx            ; recover main loop counter
  647.     jmp    decod1            ; get next source character
  648.     
  649. decod6:    mov    dbufpnt,di        ; flush buffer before exiting decode
  650.     push    cx
  651.     call    decoutp            ; flush output buffer before final ret
  652. decod7:    pop    cx
  653.  
  654.     pop    dx
  655.     pop    es
  656.     pop    di
  657.     pop    si
  658.     ret                ; return successfully if carry clear
  659. decode    endp
  660.  
  661. outbuf    proc    near            ; output decbuf, reset bufpnt & chrcnt
  662.     mov    cx,length decbuf    ; get full size of buffer
  663.     sub    cx,dchrcnt        ; minus space remaining = # to write
  664.     jg    outbu2            ; g = something to do
  665.     jmp    outbf1
  666. outbu2:    mov    dx,offset decbuf    ; address of buffer
  667.     cmp    trans.xtype,1        ; File Type Binary?
  668.     je    outbu5            ; e = yes, no translation
  669.     cmp    flags.destflg,1        ; disk destination?
  670.     je    outbu5            ; e = yes, DOS will do it
  671.     cmp    flags.eofcz,0        ; end on Control-Z?
  672.     je    outbu5            ; e = no
  673.     push    cx            ; else map Control-Z to space
  674.     push    di
  675.     push    es
  676.     push    ds
  677.     pop    es            ; data to es
  678.     mov    di,dx            ; scan buffer es:di, cx chars worth
  679.     mov    al,ctlz            ; look for Control-Z
  680.     cld
  681. outbu3:    repne    scasb
  682.     jne    outbu4            ; ne = found no Control-Z's
  683.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  684.     jcxz    outbu4            ; z = examined all chars
  685.     jmp    short outbu3        ; until examined everything
  686. outbu4:    pop    es
  687.     pop    di
  688.     pop    cx
  689.                     ; Character set translation section
  690. outbu5:    cmp    trans.xtype,1        ; File Type Binary?
  691.     je    outbu7            ; e = yes, no translation
  692.     cmp    trans.xchset,xfr_xparent ; Transfer Transparent?
  693.     je    outbu7            ; e = yes, no translation
  694.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  695.     jne    outbu5a            ; ne = no
  696.     call    jpnwrite        ; do special decoding
  697.     jmp    outbu7
  698. outbu5a:push    cx
  699.     push    si
  700.     push    di
  701.     call    latin1            ; set si to xfr char set to CP table
  702.     call    latininv        ; select invertable or readable set
  703.     mov    bx,si            ; set to bx for xlat
  704.     mov    si,offset decbuf    ; scan this buffer
  705.     mov    di,si
  706.     push    es
  707.     push    ds
  708.     pop    es
  709.     cld
  710. outbu6:    lodsb                ; get a char
  711.     test    al,80h            ; GRight?
  712.     jnz    outbu6a            ; nz = yes
  713.     cmp    bx,offset iL1cp437    ; using invertable Latin1 to CP437?
  714.     jne    outbu6c            ; ne = no
  715.     cmp    ah,127            ; 127 goes to 28?
  716.     jne    outbu6e            ; ne = no
  717.     mov    al,28            ; 127 to 28
  718.     jmp    short outbu6b
  719. outbu6e:cmp    al,21            ; special case?
  720.     ja    outbu6b            ; a = no
  721.     cmp    al,20            ; special case?
  722.     jb    outbu6b            ; b = no
  723.     mov    ah,al
  724.     mov    al,244            ; 20 to 244
  725.     cmp    ah,21            ; special case?
  726.     jne    outbu6b            ; ne = no
  727.     mov    al,245            ; preset one answer
  728.     je    outbu6b            ; e = yes, 21 to 245
  729.     mov    al,244            ; 22 to 244
  730.     jmp    short outbu6b
  731. outbu6c:cmp    bx,offset iL1cp850    ; using invertible Latin1 to CP850?
  732.     jne    outbu6b            ; ne = no
  733.     cmp    al,26            ; special case?
  734.     jne    outbu6d            ; ne = no
  735.     mov    al,127            ; 26 to 127
  736.     jmp    outbu6b
  737. outbu6d:cmp    al,127            ; special case?
  738.     jne    outbu6b            ; ne = no
  739.     mov    al,28            ; 127 to 28
  740.     jmp    short outbu6b
  741. outbu6a:and    al,not 80h        ; strip high bit
  742.     xlatb                ; translate via bx table
  743. outbu6b:stosb                ; store char
  744.     loop    outbu6            ; do all concerned
  745.     pop    es
  746.     pop    di
  747.     pop    si
  748.     pop    cx
  749.  
  750. outbu7:    push    bx
  751.     mov    bx,diskio.handle    ; file handle
  752.     mov    ah,write2        ; write cx bytes
  753.     int    dos
  754.     pop    bx
  755.     jc    outbf0            ; c set means writing error
  756.     cmp    ax,cx            ; did we write all the bytes?
  757.     je    outbf1            ; e = yes
  758.     push    bx
  759.     mov    bx,offset decbuf
  760.     add    bx,ax            ; look at break character
  761.     cmp    byte ptr [bx],ctlz    ; ended on Control-Z?
  762.     pop    bx
  763.     je    outbf1            ; e = yes, say no error
  764. outbf0: mov    dx,offset erms13    ; Error writing device
  765.     cmp    flags.xflg,0        ; writing to screen?
  766.     jne    outbf0a            ; ne = yes
  767.     cmp    flags.destflg,0        ; writing to printer?
  768.     jne    outbf0a            ; ne = no
  769.     mov    dx,offset ermes9    ; Printer not ready message
  770. outbf0a:call    ermsg
  771.     stc                ; return failure
  772.     ret
  773.  
  774. outbf1:    add    tfilsz,cx        ; count received chars
  775.     adc    tfilsz+2,0
  776.     test    flags.remflg,dserial    ; serial mode display?
  777.     jnz    outb11            ; nz = yes, skip kbyte and % displays
  778.     cmp    flags.xflg,0        ; receiving to screen?
  779.     jne    outb11            ; ne = yes
  780.     call    kbpr            ; display kilobytes done
  781.     call    perpr            ; display percentage done
  782. outb11:    mov    dbufpnt,offset decbuf    ; address for beginning
  783.     mov    dchrcnt,length decbuf    ; size of empty buffer
  784.     clc                ; return success
  785.     ret
  786. outbuf    endp
  787.  
  788. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  789. ; Reread buffer decbuf to convert from transfer character set
  790. ; Japanese-EUC into Shift-JIS (Code Page 932). Double char translation state
  791. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  792. ; Returns registers
  793. ;    cx      number of bytes written in the buffer
  794. ;    dx      address of the output buffer
  795. ;            this points decbuf or decbuf-1, depending on dblbyteflg
  796. ; Output is otherwise written over the input. [rewritten by jrd]
  797. jpnwrite proc    near            ; [HF] write Japanese to file
  798.     push    si            ; decbuf is read/written
  799.     push    di            ; cx has incoming/outgoing byte count
  800.     push    bx            ; dblbyte has earlier first byte
  801.     push    es            ; dblbyteflg is state from prev call
  802.     mov    dx,ds
  803.     mov    es,dx
  804.     cld                ; restore state from previous call
  805.     mov    dl,dblbyteflg        ; state, non-zero if doing second byte
  806.     mov    ah,dblbyte        ;  and first byte from previous read
  807.     mov    si,offset decbuf    ; read/write this buffer
  808.     mov    di,si            ; set the address for write
  809.     mov    bx,si            ; save for computing output buf length
  810.     or    dl,dl            ; carry-in of a double byte char?
  811.     jz    jpnwri1            ; z = no
  812.     dec    di            ; start output one byte before decbuf
  813.     dec    bx            ; adjust the start address
  814. jpnwri1:lodsb                ; get a byte
  815.     or    dl,dl            ; processing 2nd byte of a pair?
  816.     jnz    jpnwri3            ; nz = yes, do second byte processor
  817.                     ; first byte processor
  818.     cmp    al,80h            ; 8th bit on?
  819.     jb    jpnwri5            ; b = no, this is a single char
  820.     cmp    al,8eh            ; JIS X 0201 Katakana prefix?
  821.     je    jpnwri2            ; e = yes, is first of two chars
  822.     cmp    al,0a1h            ; JIS X 0208 Kanji ?
  823.     jb    jpnwri5            ; b = no, is single char
  824.     cmp    al,0feh
  825.     ja    jpnwri5            ; a = no, is single char
  826. jpnwri2:mov    ah,al            ; save first of two chars
  827.     mov    dl,1            ; say need second char of pair
  828.     jmp    short jpnwri6        ; read second byte
  829.                     ; process second char of two byte pair
  830. jpnwri3:cmp    ah,8eh            ; was first char JIS X 0201 Katakana?
  831.     jne    jpnwri4            ; ne = no
  832.     or    al,80h            ; make sure 8th bit is on
  833.     jmp    short jpnwri5        ; write one char
  834. jpnwri4:call    jpnxtof            ; xfer -> file char code conversion
  835.     xchg    ah,al
  836.     stosb                ; write first byte
  837.     xchg    ah,al            ; and second byte
  838. jpnwri5:stosb                ; write a char
  839.     xor    dl,dl            ; clear multi-byte counter
  840. jpnwri6:loop    jpnwri1
  841.     mov    dblbyteflg,dl        ; save state info
  842.     mov    dblbyte,ah        ; and the first byte of a pair
  843.     sub    di,bx            ; find number of chars written
  844.     mov    cx,di            ; return new count in CX
  845.     mov    dx,bx            ; return new buffer address for write
  846.     pop    es            ; can be decbuf - 1 if carry-in of dbl
  847.     pop    bx
  848.     pop    di
  849.     pop    si
  850.     clc
  851.     ret
  852. jpnwrite endp
  853.  
  854. ; Transfer character code (EUC) to file character code (Shift-JIS) converter.
  855. ; input      AH: 1st byte of EUC code
  856. ;            AL: 2nd byte of EUC code
  857. ; output     AH: 1st byte of Shift-JIS code
  858. ;            AL: 2nd byte of Shift-JIS code
  859. ; From EUC to Shift-JIS
  860. ;   code1 = (EUC_code1 & 0x7f);
  861. ;   code2 = (EUC_code2 & 0x7f);
  862. ;   if( code1 & 1)
  863. ;     code2 += 0x1f;
  864. ;   else
  865. ;     code2 += 0x7d;
  866. ;   if( code2 >= 0x7f ) code2++;
  867. ;   code1 = ((code1 - 0x21) >> 1) + 0x81;
  868. ;   if( code1 > 0x9f ) code1 += 0x40;
  869. ;   [ fputc( code1, file ); fputc( code2, file ); ]
  870. ;
  871. jpnxtof    proc    near
  872.     and    ax,7f7fh        ; mask both 8-th bits
  873.     test    ah,1
  874.     jz    jpnxtof1
  875.     add    al,1fh
  876.     jmp    short jpnxtof2
  877. jpnxtof1:add    al,7dh
  878. jpnxtof2:cmp    al,7fh
  879.     jb    jpnxtof3
  880.     inc    al
  881. jpnxtof3:sub    ah,21h
  882.     shr    ah,1
  883.     add    ah,81h
  884.     cmp    ah,9fh
  885.     jbe    jpnxtof4
  886.     add    ah,40h
  887. jpnxtof4:ret
  888. jpnxtof    endp
  889.  
  890. ; Get chars from file, encode them to pktinfo structure pointed to by si
  891.  
  892. gtchr:    mov    [si].datlen,0        ; say no output data yet
  893.     cmp    filflg,0        ; is there anything in the buffer?
  894.     jne    gtchr0            ; ne = yes, use that material first
  895.     call    inbuf            ; do initial read from source
  896.     jc    gtchr1            ; c = no more chars, go return EOF
  897. gtchr0:    mov    encinp,offset inbuf    ; buffer refiller routine
  898.     jmp    short encode
  899.  
  900. gtchr1:    mov    [si].datlen,0        ; report EOF
  901.     mov    flags.eoflag,1        ; say eof
  902.     stc                ; return failure
  903.     ret
  904.  
  905. ; Do encoding.
  906. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr.
  907. ; Writes output to area pointed to by [si].datadr.
  908. ; Returns char count in cx and [si].datlen with carry clear if success,
  909. ; else carry set if overflow.
  910. ; SI is preserved
  911. doenc:    clc
  912.     jcxz    doen0            ; cx = 0 means nothing to encode
  913.     mov    ah,dblbyteflg        ; preserve state
  914.     mov    al,dblbyte
  915.     push    ax
  916.     mov    al,shiftstate        ; locking shift state
  917.     mov    ah,DLEseen        ; DLE state
  918.     push    ax            ; save
  919.     mov    dblbyteflg,0        ; init encode as doubles
  920.     mov    shiftstate,0        ; init shift states
  921.     mov    DLEseen,0
  922.     mov    echrcnt,cx        ; number of bytes of source data
  923.     mov    ebufpnt,offset encbuf    ; source of data
  924.     mov    encinp,offset nulref    ; null routine for refilling buffer
  925.     call    encode            ; make a packet with size in AX
  926.     mov    cx,ax
  927.     pop    ax            ; restore state
  928.     mov    shiftstate,al
  929.     mov    DLEseen,ah
  930.     pop    ax
  931.     mov    dblbyteflg,ah
  932.     mov    dblbyte,al
  933. doen0:    ret
  934.  
  935. nulref:    mov    echrcnt,0        ; no data to return
  936.     stc
  937.     ret
  938.  
  939. ; encode - writes data portion of kermit packet into [[si].datadr].
  940. ; expects encinp to contain the address of a routine to refill the buffer,
  941. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  942. ; the maximum size of the data packet, ebufpnt to contain a pointer to
  943. ; the source of the characters, and [si].datadr to be output address.
  944. ; Trans.lshift is non-zero if locking shift encoding is active.
  945. ; While locking shift is active DLE escapes DLE, SI, and SO to be
  946. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  947. ; data to non-high bit data; SI (Control-O) cancels SO. Shiftstate is
  948. ; 0 for non-shifted state, 80h for shifted state.
  949. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  950. ; performing Japanese translation; dblbyte is the first byte of the pair.
  951. ; Returns: AX = the number of characters actually written to the buffer
  952. ; All packets except I, S, and A types are encoded.
  953. ; Packet space is precomputed allowing for prefixes other than locking shifts.
  954. ; Returns carry clear for success, carry set otherwise.
  955.  
  956. encode    proc    near
  957.     push    si            ; save caller's si
  958.     mov    cx,trans.maxdat        ; maximum packet size
  959.     push    ds
  960.     pop    es            ; make es:di point to data segment
  961.     mov    di,[si].datadr        ; address of output buffer
  962.     mov    temp,di            ; remember output buffer start address
  963.     mov    si,ebufpnt        ; pointer into source buffer
  964.     mov    dl,trans.rquote        ; send quote char
  965.     xor    dh,dh            ; assume no 8-bit quoting
  966.     mov    al,trans.ebquot        ; 8-bit quote
  967.     cmp    al,'N'            ; refusing 8-bit quoting?
  968.     je    encod10            ; e = yes
  969.     cmp    al,'Y'            ; or can but won't?
  970.     je    encod10            ; e = yes, else specific char
  971.     mov    dh,0ffh            ; remember we have to do 8-bit quotes
  972.                     ; top of read loop
  973. encod10:or    cx,cx            ; any space left in output buffer?
  974.     jge    encod11            ; ge = yes
  975.     mov    ax,di            ; current output location
  976.     sub    ax,temp            ; minus start of buffer, ret cnt in AX
  977.     mov    ebufpnt,si        ; update pointer into source buffer
  978.     pop    si            ; restore caller's si
  979.     mov    [si].datlen,ax
  980.     clc                ; success
  981.     ret
  982.  
  983. encod11:cmp    echrcnt,0        ; any data in buffer?
  984.     jg    encod20            ; g = yes, skip over buffer refill
  985.     call    encinp            ; get another buffer full
  986.     jnc    encod14            ; nc = success
  987.  
  988. encod12:pop    si            ; restore user's si
  989.     sub    di,temp            ; minus start of buffer
  990.     or    di,di            ; buffer empty?
  991.     jz    encod13            ; z = yes
  992.     mov    ax,di            ; report size encoded
  993.     mov    [si].datlen,ax
  994.     clc                ; success
  995.     ret                ; return success
  996. encod13:xor    ax,ax            ; empty buffer
  997.         mov    flags.eoflag,1        ; set eof flag
  998.     mov    filflg,al        ; nothing in input buffer
  999.     mov    [si].datlen,ax
  1000.     stc                ; failure
  1001.     ret                ; return failure
  1002.  
  1003. encod14:mov    si,ebufpnt        ; update position in source buffer
  1004.     cmp    echrcnt,0         ; any characters returned?
  1005.     je    encod12            ; e = none, assume eof
  1006.  
  1007. encod20:cld                ; forward direction
  1008.     lodsb
  1009.     dec    echrcnt            ; decrement input count
  1010.     mov    ah,al
  1011.     and    ah,80h            ; keep high bit in ah
  1012.     mov    rptct,1            ; say have one copy of this char
  1013.     cmp    al,'Z'-40H        ; is this a control-Z?
  1014.     jne    encd30            ; ne = no, skip eof-processing
  1015.     cmp    flags.eofcz,0           ; is a Control-Z an end of file?
  1016.     je    encd30            ; e = no
  1017.     cmp    trans.xtype,1        ; file type binary?
  1018.     je    encd30            ; e = yes, send as is
  1019.     mov    flags.eoflag,1        ; yes, set eof flag
  1020.     mov    filflg,0        ; say no more source data in buffer
  1021.     mov    echrcnt,0        ; ditto
  1022.     jmp    short encod12        ; set character count and return
  1023.  
  1024.                     ; analyze current char (al)
  1025. encd30:    cmp    echrcnt,0        ; doing the last character?
  1026.     jle    encod40            ; le = yes, there is no next character
  1027.     or    cx,cx            ; space left in output buffer?
  1028.     jg    encd30a            ; g = yes
  1029.     jmp    encod50            ; le = no, not enough for rpt prefix
  1030. encd30a:cmp    al,[si]            ; this is char the same as the next?
  1031.     jne    encod40            ; no, do this char independently
  1032.  
  1033.     push    cx            ; scan for repeats in input buffer
  1034.     push    bx
  1035.     mov    cx,echrcnt        ; count of bytes left in input buf
  1036.     inc    cx            ; will reread current byte
  1037.     cmp    cx,94            ; max prefix of 94
  1038.     jbe    encod31            ; be = ok, else limit scan to 94
  1039.     mov    cx,94
  1040. encod31:xor    bx,bx            ; count of copies of this char in buf
  1041. encod32:inc    bx
  1042.     cmp    [si+bx-1],al        ; new [si+bx-1] same as current (al)?
  1043.     loope    encod32            ; e = yes, do all of interest
  1044.     cmp    bx,3            ; enough repeats to use prefix?
  1045.     jae    encod33            ; ae = yes
  1046.     mov    bx,1            ; say do one char
  1047. encod33:mov    rptct,bl        ; bl is qty repeated overall
  1048.     dec    bx            ; ax = number of extra chars (>1)
  1049.     add    si,bx            ; move forward by repeat group
  1050.     sub    echrcnt,bx        ; input buffer counter too
  1051.     pop    bx
  1052.     pop    cx
  1053.  
  1054.                     ; test for locking shift applicability
  1055. encod40:or    cx,cx            ; enough space left in output buffer?
  1056.     jle    encod50            ; le = no, not enough for prefix
  1057.     cmp    trans.lshift,lock_disable ; locking shifts disabled?
  1058.     je    encod50            ; e = yes, skip this material
  1059.     cmp    ah,shiftstate        ; change of high bit status?
  1060.     jne    encod41            ; ne = yes
  1061.     jmp    encod50            ; no, stay in same lock state
  1062.                     ; change of high bit
  1063. encod41:mov    bx,echrcnt        ; count chars remaining to be read
  1064.     add    bl,rptct        ; add repeat count
  1065.     adc    bh,0
  1066.     cmp    bx,4            ; at least 4 more chars to examine?
  1067.     jb    encod50            ; b = no, not worth a lock change
  1068.     cmp    rptct,4            ; enough repeats to take short cut?
  1069.     jae    encod43            ; ae = plenty of repeats
  1070.  
  1071.     push    ax            ; look for change of shift state
  1072.     push    cx
  1073.     push    si
  1074.     mov    cl,rptct        ; repeat count
  1075.     xor    ch,ch
  1076.     dec    cx            ; count is one for no repeats
  1077.     sub    si,cx            ; back up over repeated chars
  1078.     mov    cx,4            ; look ahead 4 chars
  1079. encod42:lodsb                ; read ahead
  1080.     and    al,80h            ; pick out high bit
  1081.     cmp    al,ah            ; high bit the same?
  1082.     loope    encod42            ; loop while same
  1083.     pop    si
  1084.     pop    cx
  1085.     pop    ax
  1086.     jne    encod50            ; ne = differ, don't change lock
  1087.                     ; change locking shift state
  1088. encod43:mov    [di],dl            ; insert quote char (#)
  1089.     inc    di            ; adjust output buffer pointer
  1090.     dec    cx
  1091.     push    ax
  1092.     mov    ah,shiftstate        ; get current shift state
  1093.     xor    ah,80h            ; toggle shift state
  1094.     mov    shiftstate,ah        ; remember it
  1095.     mov    al,SIchar+40h        ; assume going into unshifted state
  1096.     or    ah,ah            ; to unshifted state now?
  1097.     jz    encod44            ; z = yes, go to unshifted state
  1098.     mov    al,SOchar+40h        ; say go to shifted state
  1099. encod44:mov    [di],al            ; put lock char into packet
  1100.     inc    di
  1101.     dec    cx
  1102.     pop    ax            ; recover current character
  1103.                     ; end of locking shift tests
  1104. encod50:cmp    rptct,1            ; doing repeats?
  1105.     jbe    encod52            ; be = no
  1106.     push    ax            ; do repeat prefixing - save data
  1107.     mov    al,trans.rptq        ; insert repeat prefix char
  1108.     stosb
  1109.     dec    cx            ; account for it in buffer size
  1110.     mov    al,rptct        ; get the repeat count
  1111.     add    al,20h            ; make it printable
  1112.     stosb                ; insert into buffer
  1113.     dec    cx
  1114.     pop    ax            ; get back the actual character
  1115.  
  1116. encod52:or    dh,dh            ; doing 8-bit quoting?
  1117.     jz    encod60            ; z = no, forget this
  1118.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1119.     je    encod57            ; e = yes
  1120.     cmp    ah,shiftstate        ; different than current shift state?
  1121.     jne    encod58            ; ne = yes, specials will be prefixed
  1122.     push    ax            ; save char (stripped of high bit)
  1123.     and    al,7fh            ; consider high bit controls too
  1124.     cmp    al,SIchar        ; SI (Control-O)?
  1125.     je    encod53            ; e = yes
  1126.     cmp    al,SOchar        ; SO (Control-N)?
  1127.     je    encod53            ; e = yes
  1128.     cmp    al,DLE            ; DLE (Control-P)?
  1129.     jne    encod54            ; ne = no
  1130. encod53:mov    al,dl            ; stuff a quote (#)
  1131.     stosb
  1132.     dec    cx
  1133.     mov    al,DLE + 40h        ; then a DLE prefix (P)
  1134.     stosb
  1135.     dec    cx            ; account for it in buffer size
  1136. encod54:pop    ax            ; exit with original char in AL
  1137.     jmp    short encod60        ; no 8-bit prefixing needed here
  1138.  
  1139. encod57:cmp    ah,shiftstate        ; different than current shift state?
  1140.     je    encod60            ; e = no, don't send quoted form
  1141. encod58:mov    bl,trans.ebquot        ; get 8-bit quote char
  1142.     mov    [di],bl            ; put in packet
  1143.     inc    di
  1144.     dec    cx            ; decrement # of chars left
  1145.                     ; common prefix testing section
  1146. encod60:and    al,7fh            ; turn off 8th bit in character
  1147.     cmp    al,' '            ; compare to a space
  1148.     jb    encod64            ; b = control char
  1149.     cmp    al,del            ; delete?
  1150.     je    encod64            ; e = yes, go quote it
  1151.     cmp    al,dl            ; quote char?
  1152.     je    encod65            ; e = yes, go add it
  1153.     or    dh,dh            ; doing 8-bit quoting?
  1154.     jz    encod62            ; z = no, don't translate it
  1155.     cmp    al,trans.ebquot        ; 8-bit quote char?
  1156.     je    encod65            ; e = yes, just output with quote
  1157. encod62:cmp    trans.rptq,0        ; doing repeat prefixing?
  1158.     je    encod67            ; e = no, don't check for quote char
  1159.     cmp    al,trans.rptq        ; repeat quote character?
  1160.     je    encod65            ; e = yes, then quote it
  1161.     jmp    short encod67        ; else don't quote it
  1162.                     ; control code section
  1163. encod64:xor    al,40h            ; control char, uncontrollify
  1164. encod65:mov    [di],dl            ; insert control quote char
  1165.     inc    di
  1166.     dec    cx
  1167. encod67:or    al,ah            ; restore high bit, if stripped
  1168.     or    dh,dh            ; doing eight bit quoting?
  1169.     jz    encod68            ; z = no, retain high bit
  1170.     and    al,not 80h        ; strip high bit
  1171. encod68:stosb
  1172.     dec    cx            ; decrement output buffer counter
  1173.     jmp    encod10            ; get fresh input
  1174. encode    endp 
  1175.  
  1176. ; Fill encode source buffer, report KB and percentage done.
  1177. ; Return carry clear for success
  1178. ; modifies ax
  1179. inbuf    proc    near
  1180.     cmp    flags.eoflag,0        ; reached the end?
  1181.     je    inbuf0            ; e = no
  1182.     stc                ; return failure
  1183.     ret
  1184. inbuf0:    push    dx
  1185.     push    bx
  1186.     push    cx
  1187.     mov    bx,diskio.handle    ; get file handle
  1188.     mov    cx,buffsz        ; record size
  1189.     mov    dx,offset buff        ; buffer
  1190.     mov    ebufpnt,dx        ; buffer pointer
  1191.     cmp    trans.xtype,1        ; [HF3] File type binary?
  1192.     je    inbuf0a            ; [HF3] e = yes, no translation
  1193.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1194.     jne    inbuf0a            ; ne = no
  1195.     shr    cx,1            ; allow for double char encoding
  1196.     mov    dx,offset rdbuf        ; use this as source buffer
  1197. inbuf0a:mov    ah,readf2        ; read a record
  1198.     int    dos
  1199.     jnc    inbuf7            ; nc = no error
  1200.     mov    flags.cxzflg,'X'    ; error, set ^X flag
  1201.      jmp    short inbuf1        ; and truncate the file here
  1202. inbuf7:    or    ax,ax            ; any bytes read?
  1203.     jnz    inbuf2            ; nz = yes (the number read)
  1204. inbuf1:    mov    flags.eoflag,1        ; set End-of-File
  1205.     mov    filflg,0        ; buffer empty
  1206.     mov    echrcnt,0        ; zero bytes left in buffer
  1207.     pop    cx
  1208.     pop    bx
  1209.     pop    dx
  1210.     stc                ; failure
  1211.     ret
  1212.  
  1213. inbuf2:    cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1214.     jne    inbuf2a            ; ne = no
  1215.     call    jpnread            ; revise buffer for Japanese
  1216. inbuf2a:add    tfilsz,ax        ; total the # bytes transferred so far
  1217.     adc    tfilsz+2,0        ; it's a double word
  1218.     mov    echrcnt,ax        ; number of chars read from file
  1219.     mov    filflg,1        ; buffer not empty
  1220.     test    flags.remflg,dserial    ; serial display mode?
  1221.     jnz    inbuf3            ; nz = yes, skip kbyte and % display
  1222.     push    si
  1223.     push     ax
  1224.     call    kbpr            ; show kilobytes sent
  1225.     call    perpr            ; show percent sent
  1226.     pop    ax
  1227.     pop    si
  1228.                     ; Character set translation section
  1229. inbuf3:    cmp    trans.xchset,xfr_xparent ; Transparent transfer char set?
  1230.     je    inbuf6            ; e = yes, no translation
  1231.     cmp    trans.xtype,1        ; File Type Binary?
  1232.     je    inbuf6            ; e = yes, no translation
  1233.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1234.     je    inbuf6            ; e = yes, processed already
  1235.     push    ax            ; save buffer count
  1236.     mov    cx,ax            ; loop counter
  1237.     push    si
  1238.     push    di
  1239.     call    cplatin            ; set bx to offset CP to Xfr chr table
  1240.     call    cpinvert        ; check readable vs invertible set
  1241.     mov    si,offset buff        ; scan this buffer
  1242.     mov    di,si
  1243.     push    es
  1244.     push    ds
  1245.     pop    es
  1246.     cld
  1247. inbuf4:    lodsb                ; get a char
  1248.     cmp    bx,offset icp437L1    ; invertible CP 437 to Latin1?
  1249.     jne    inbuf4b            ; ne = no
  1250.     mov    ah,al
  1251.     cmp    ah,127            ; special case?
  1252.     jne    inbuf4d            ; ne = no
  1253.     mov    al,26            ; 127 to 26
  1254.     jmp    short inbuf5
  1255. inbuf4d:cmp    al,20            ; range for special cases?
  1256.     jb    inbuf5            ; b = no
  1257.     cmp    al,21
  1258.     ja    inbuf5            ; a = no
  1259.     mov    al,167
  1260.     je    inbuf5            ; 21 to 167
  1261.     mov    al,182
  1262.     jmp    short inbuf5        ; 20 to 182
  1263. inbuf4b:cmp    bx,offset icp850L1    ; invertible CP 850 to Latin1?
  1264.     jne    inbuf4a            ; ne = no
  1265.     cmp    al,28            ; special case?
  1266.     jne    inbuf4c            ; ne = no
  1267.     mov    al,127            ; 28 to 127
  1268.     jmp    short inbuf5
  1269. inbuf4c:cmp    al,127            ; special case?
  1270.     jne    inbuf4a
  1271.     mov    al,26            ; 127 to 26
  1272. inbuf4a:test    al,80h            ; GRight?
  1273.     jz    inbuf5            ; z = no
  1274.     and    al,not 80h        ; strip high bit
  1275.     xlatb                ; translate via bx table
  1276. inbuf5:    stosb                ; store char
  1277.     loop    inbuf4            ; do all concerned
  1278.     pop    es
  1279.     pop    di
  1280.     pop    si
  1281.     pop    ax
  1282. inbuf6:    pop    cx
  1283.     pop    bx
  1284.     pop    dx
  1285.     clc                ; success
  1286.     ret
  1287. inbuf    endp
  1288.  
  1289. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  1290. ; Read buffer rdbuf to convert from file character set Shift-JIS (Code Page 
  1291. ; 932) to transfer character set Japanese-EUC. Double char translation state
  1292. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  1293. ; Output is written to buff, with byte count in register AX. The output
  1294. ; could be twice the size of the input. [rewritten by jrd]
  1295. jpnread    proc    near            ; [HF] read Japanese from file
  1296.     push    si
  1297.     push    di
  1298.     push    es
  1299.     mov    cx,ax            ; number of chars in source buffer
  1300.     mov    ax,ds
  1301.     mov    es,ax
  1302.     mov    dl,dblbyteflg        ; get state info from previous call
  1303.     mov    ah,dblbyte        ;  first byte too
  1304.     mov    si,offset rdbuf        ; read from here
  1305.     mov    di,offset buff        ; write to here (avoids overwrites)
  1306.     cld
  1307. jpnrea1:lodsb                ; get a byte
  1308.     or    dl,dl            ; doing first byte?
  1309.     jnz    jpnread3        ; nz = no, second of a pair
  1310.     cmp    al,81h            ; is it Kanji?
  1311.     jb    jpnrea5            ; b = no
  1312.     cmp    al,0fch
  1313.     ja    jpnrea5            ; a = no
  1314.     cmp    al,9fh
  1315.     jbe    jpnrea2            ; be = yes
  1316.     cmp    al,0e0h
  1317.     jb    jpnrea5            ; b = no
  1318. jpnrea2:mov    ah,al            ; AL is first byte of Kanji, save it
  1319.     mov    dl,1            ; say ready to do second byte next
  1320.     jmp    short jpnrea8        ; continue loop
  1321.  
  1322. jpnread3:cmp    al,40h            ; is second byte Kanji?
  1323.     jb    jpnrea6            ; b = no
  1324.     cmp    al,0fch
  1325.     ja    jpnrea6            ; a = no
  1326.     cmp    al,7eh
  1327.     jbe    jpnrea4            ; be = yes
  1328.     cmp    al,80h
  1329.     jb    jpnrea6            ; b = no
  1330. jpnrea4:call    jpnftox            ; convert to xfer char code
  1331.     jmp    short jpnrea6        ; write the pair
  1332.  
  1333. jpnrea5:cmp    al,0a1h            ; Katakana?
  1334.     jb    jpnrea7            ; b = no
  1335.     cmp    al,0dfh
  1336.     ja    jpnrea7            ; a = no
  1337.     mov    ah,8eh            ; set Katakana prefix
  1338. jpnrea6:xchg    ah,al            ; write two bytes
  1339.     stosb                ; store first byte
  1340.     xchg    ah,al            ; get second byte into AL again
  1341. jpnrea7:stosb                ; store a byte
  1342.     xor    dl,dl            ; say all bytes have been written
  1343. jpnrea8:loop    jpnrea1
  1344.     mov    dblbyteflg,dl        ; save state info
  1345.     mov    dblbyte,ah        ; and first char of a pair
  1346.     sub    di,offset buff        ; compute number of bytes written
  1347.     mov    ax,di            ; report new count in AX
  1348.     pop    es
  1349.     pop    di
  1350.     pop    si
  1351.     ret
  1352. jpnread    endp
  1353.  
  1354. ; File character code (Shift-JIS) to xfer character code (EUC) converter.
  1355. ; From Shift-JIS to EUC
  1356. ;   if( code1 <= 0x9f )
  1357. ;     code1 -= 0x71;
  1358. ;   else
  1359. ;     code1 -= 0xb1;
  1360. ;   code1 = code1 * 2 + 1;
  1361. ;   if( code2 > 0x7f ) code2 -= 1;
  1362. ;   if( code2 >= 0x9e ){
  1363. ;     code2 -= 0x7d;
  1364. ;     code1 += 1;
  1365. ;   } else
  1366. ;     code2 -= 0x1f;
  1367. ;   EUC_code1 = (code1 | 0x80);
  1368. ;   EUC_code2 = (code2 | 0x80);
  1369. ;   [ fputc( EUC_code1, packet ); fputc( EUC_code2, packet ); ]
  1370. ;
  1371. jpnftox    proc    near
  1372.     cmp    ah,9fh
  1373.     ja    jpnftox1
  1374.     sub    ah,71h
  1375.     jmp    short jpnftox2
  1376. jpnftox1:sub    ah,0b1h
  1377. jpnftox2:shl    ah,1
  1378.     inc    ah
  1379.     cmp    al,7fh
  1380.     jbe    jpnftox3
  1381.     dec    al
  1382. jpnftox3:cmp    al,9eh
  1383.     jb    jpnftox4
  1384.     sub    al,7dh
  1385.     inc    ah
  1386.     jmp    jpnftox5
  1387. jpnftox4:sub    al,1fh
  1388. jpnftox5:or    ax,8080h
  1389.     ret
  1390. jpnftox    endp
  1391.  
  1392. ; GETFIL, called only by send code
  1393. ; Enter with raw filename pattern in diskio.string
  1394. ; Returns carry clear if success, else carry set
  1395. getfil    proc    near
  1396.     mov    dblbyteflg,0        ; clear encoder state variable
  1397.     mov    shiftstate,0        ; locking shift state
  1398.     mov    DLEseen,0        ; escape state
  1399.     mov    filflg,0        ; say nothing is in the buffer
  1400.     mov    flags.eoflag,0        ; not the end of file
  1401.     mov    dx,offset diskio.dta    ; data transfer address
  1402.     mov    ah,setdma        ; set disk transfer address
  1403.     int    dos
  1404.     xor    cx,cx            ; attributes: find only normal files
  1405.     mov    dx,offset diskio.string ; filename string (may have wild cards)
  1406.     mov    ah,first2        ; DOS 2.0 search for first
  1407.     int    dos            ; get file's characteristics
  1408.     pushf                ; save c flag
  1409.     mov    ah,setdma        ; reset dta address
  1410.     mov    dx,offset buff        ; restore dta
  1411.     int    dos
  1412.     popf                ; restore status of search for first
  1413.     jnc    getfi1            ; nc = ok so far
  1414.     ret                ; else take error exit
  1415. getfi1:    jmp    getfcom            ; do common code
  1416. getfil    endp
  1417.  
  1418.  
  1419. ; GTNFIL called by send code to get next file.
  1420. ; Returns carry clear for success, carry set for failure.
  1421. gtnfil    proc    near
  1422.     mov    dblbyteflg,0        ; clear encoder state variable
  1423.     mov    shiftstate,0        ; locking shift state
  1424.     mov    DLEseen,0        ; escape state
  1425.     cmp    flags.cxzflg,'Z'    ; Did we have a ^Z?
  1426.     jne    gtnfi1            ; ne = no, else done sending files
  1427.     stc                ; carry set for failure
  1428.     ret                ; take failure exit
  1429.  
  1430. gtnfi1:    xor    al,al
  1431.     mov    filflg,al        ; nothing in the DMA
  1432.     mov    flags.eoflag,al        ; not the end of file
  1433.     mov    dx,offset diskio.dta    ; point at dta
  1434.     mov    ah,setdma        ; set the dta address
  1435.     int    dos
  1436.     mov    ah,next2        ; DOS 2.0 search for next
  1437.     int    dos
  1438.     pushf                ; save carry flag
  1439.     mov    ah,setdma        ; restore dta
  1440.     mov    dx,offset buff
  1441.     int    dos
  1442.     popf                ; recover carry flag
  1443.     jnc    getfcom            ; nc = success, do common code
  1444.     ret                ; carry    set means no more files found
  1445. gtnfil    endp
  1446.                     ; worker for getfil, gtnfil
  1447. getfcom    proc    near
  1448.     push    si
  1449.     push    di
  1450.     mov    dx,offset diskio.string    ; original file spec (may be wild)
  1451.     mov    di,offset templp    ; place for path part
  1452.     mov    si,offset templf    ; place for filename part
  1453.     call    fparse            ; split them
  1454.     mov    si,offset diskio.fname    ; current filename from DOS
  1455.     call    strcat            ; (di)= local path + diskio.fname
  1456.     mov    di,offset encbuf    ; name to send to host (no path)
  1457.     call    strcpy              ; new string = old path + DOS's filename
  1458.     push    bx
  1459.     push    cx
  1460.     test    flags.remflg,dquiet    ; quiet display?
  1461.     jnz    getfco1            ; e = yes, do not display filename
  1462.     call    clrfln            ; position cursor & blank out the line
  1463.     mov    dx,offset templp
  1464.     call    prtasz
  1465. getfco1:call    newfn            ; update encbuf with "send as" name
  1466.     pop    cx
  1467.     pop    bx
  1468.     mov    ah,open2        ; file open
  1469.     xor    al,al            ; 0 = open readonly
  1470.     cmp    dosnum,300h        ; at or above DOS 3?
  1471.     jb    getfco2            ; b = no, so no shared access
  1472.     or    al,40h            ; open readonly, deny none
  1473. getfco2:mov    dx,offset templp    ; filename string with path
  1474.     int    dos
  1475.     jc    getfco3            ; c = failed to open the file
  1476.     mov    diskio.handle,ax    ; save file handle
  1477.     xor    ax,ax
  1478.     mov    tfilsz,ax        ; set bytes sent to zero
  1479.     mov    tfilsz+2,ax
  1480.     mov    ax,-1            ; get a minus one
  1481.     mov    oldkbt,ax
  1482.     mov    oldper,ax
  1483.     clc                ; carry clear for success
  1484. getfco3:pop    si
  1485.     pop    di
  1486.     ret
  1487. getfcom    endp
  1488.  
  1489. ; Get the file name from the data portion of the F packet or from locally
  1490. ; specified override filename (in auxfile), displays the filename, does any
  1491. ; manipulation of the filename necessary, including changing the name to
  1492. ; prevent collisions. Returns carry clear for success. Failures return
  1493. ; carry set with dx pointing at error message text.
  1494. ; Called by file receive module in mssrcv.asm.
  1495.  
  1496. gofil    proc    near
  1497.     mov    si,offset decbuf    ; filename in packet
  1498.     mov    di,offset diskio.string    ; place where prtfn finds name
  1499.     call    strcpy            ; copy pkt filename to diskio.string
  1500.     mov    di,offset fsta.xname    ; statistics external filespec area
  1501.     call    strcpy            ; record external name
  1502.     cmp    auxfile,0        ; have override name?
  1503.     jne    gofil1            ; ne = yes
  1504.     cmp    flags.xflg,0        ; receiving to screen?
  1505.     jne    gofil0a            ; ne = yes, filename becomes CON
  1506.     cmp    flags.destflg,1        ; destination is disk?
  1507.     je    gofil1            ; e = yes
  1508.     mov    di,offset printer    ; assume PRN is local file name
  1509.     jb    gofil0b            ; b = yes
  1510. gofil0a:mov    di,offset screen    ; use CON (screen) as local file name
  1511.     mov    flags.xflg,1        ; say receiving to screen
  1512. gofil0b:xchg    di,si            ; di --> decbuf, si --> file name
  1513.     call    strcpy            ; put local name (si) into decbuf
  1514.     mov    nmoflg,1        ; say that we have a replacement name
  1515.     jmp    gofil9            ; final filename is now in 'decbuf'
  1516.  
  1517. gofil1:    xor    ax,ax
  1518.     mov    nmoflg,al        ; assume no override name
  1519.     cmp    auxfile,al        ; overriding name from other side?
  1520.     jne    gofi1e            ; ne = yes
  1521.     jmp    gofil4            ; e = no, get the other end's filename
  1522. gofi1e:    mov    nmoflg,1        ; say using an override name
  1523.     mov    ax,offset auxfile    ; get local override filename
  1524.     cmp    word ptr auxfile+1,003ah; colon+null?(primative drive spec A:)
  1525.     je    gofil3        ; e = yes, skip screwy DOS response (No Path)
  1526.     cmp    word ptr auxfile,'..'    ; parent directory?
  1527.     jne    gofi1g            ; ne = no
  1528.     cmp    word ptr auxfile+1,002eh ; dot dot + null?
  1529.     je    gofi1b            ; e = yes, process as directory
  1530. gofi1g:    cmp    word ptr auxfile,002eh    ; dot + null (current dir)?
  1531.     je    gofi1b            ; e = yes, process as directory
  1532.     call    isfile            ; does it exist?
  1533.     jnc    gofi1f            ; nc = file exists
  1534.     test    filtst.fstat,80h    ; serious error?
  1535.     jz    gofil3            ; z = no, just no such file
  1536.     jmp    gofi18a            ; else quit here
  1537. gofi1f:    test    byte ptr filtst.dta+21,10H ; subdirectory name?
  1538.     jnz    gofi1b            ; nz = yes
  1539.     cmp    filtst.fname,2eh    ; directory name?
  1540.     je    gofi1b            ; e = yes, process as directory
  1541.     cmp    auxfile+2,5ch        ; a root directory like b:\?
  1542.     jne    gofi1d            ; ne = no. (DOS is not helpful with roots)
  1543.     cmp    auxfile+3,0        ; and is it terminated in a null?
  1544.     je    gofi1b            ; e = yes, so it is a root spec
  1545. gofi1d:    test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  1546.     jz    gofil3            ; z = no
  1547.      jmp    gofi18a               ; yes. Complain and don't transfer file
  1548. gofi1b:    mov    dx,offset auxfile    ; auxfile is a (sub)directory name
  1549.     call    strlen            ; get its length w/o terminator
  1550.     jcxz    gofil2            ; zero length
  1551.     dec    cx            ; examine last char
  1552.     push    bx            ; save bx
  1553.     mov    bx,cx
  1554.     add    bx,dx
  1555.     cmp    byte ptr [bx],5ch    ; ends in backslash?
  1556.     je    gofil2            ; e = yes
  1557.     cmp    byte ptr [bx],2fh    ; maybe forward slash?
  1558.     je    gofil2            ; e = yes
  1559.     mov    byte ptr [bx + 1],5ch    ; no slash yet. use backslash
  1560.     mov    byte ptr [bx + 2],0    ; plant new terminator
  1561. gofil2:    pop    bx
  1562.  
  1563. gofil3:    mov    di,offset templp    ; local path
  1564.     mov    si,offset templf    ; local filename
  1565.     mov    dx,offset auxfile    ; local string
  1566.     call    fparse            ; split local string
  1567.     mov    di,offset temprp    ; remote path
  1568.     mov    si,offset temprf    ; remote file
  1569.     mov    dx,offset decbuf    ; remote string
  1570.     mov    decbuf+64,0        ; force filename to be <= 64 chars
  1571.     call    fparse            ; split remote string
  1572.     test    flags.remflg,dserver    ; running in Server mode?
  1573.     jz    gofi3c            ; z = no
  1574.     test    denyflg,sndflg        ; is Deny Send mode in operation?
  1575.     jz    gofi3c            ; z = no
  1576.     mov    temprp,0        ; DENY, means remove remote path
  1577. gofi3c:    mov    si,offset templp    ; copy local path to
  1578.     mov    di,offset decbuf    ;  final filename
  1579.     call    strcpy            ; do the copy
  1580.     mov    si,offset templf    ; assume using local file name
  1581.     cmp    byte ptr templf,0    ; local file name given?
  1582.     jne    gofi3b            ; ne = yes
  1583.     mov    si,offset temprf    ; else use remote file name
  1584. gofi3b:    call    strcat            ; append path and filename again
  1585.                     ; offset decbuf holds the new filename
  1586.                     ;
  1587.                 ; recheck legality of filename in 'decbuf'
  1588. gofil4:    mov    decbuf+64,0        ; guard against long filenames
  1589.     mov    di,offset temprp    ; remote path
  1590.     mov    si,offset temprf    ; remote file
  1591.     mov    dx,offset decbuf    ; remote string
  1592.     call    strlen            ; get original size
  1593.     push    cx            ; remember it
  1594.     call    fparse            ; further massage filename
  1595.     push    si            ; put pieces back together
  1596.     call    verfil            ; verify each char in temprf string
  1597.     mov    si,di            ; get path part first
  1598.     mov    di,dx            ; set destination
  1599.     call    strcpy            ; copy in path part
  1600.     pop    si            ; recover (new) filename
  1601.     cmp    byte ptr [si],'.'    ; does filename part start with a dot?
  1602.     jne    gofil5            ; ne = no
  1603.     push    di            ; save regs
  1604.     push    si
  1605.     mov    di,offset rdbuf        ; a work area
  1606.     mov    byte ptr [di],'X'    ; start name with letter X
  1607.     inc    di
  1608.     call    strcpy            ; copy rest of filename
  1609.     mov    di,si
  1610.     mov    si,offset rdbuf      ; copy new name back to original location
  1611.     call    strcpy
  1612.     pop    si            ; restore regs
  1613.     pop    di    
  1614. gofil5:    call    strcat            ; append it
  1615.     call    strlen            ; see if we chopped out something
  1616.     pop    si            ; get original length (from push cx above)
  1617.     cmp    cx,si            ; same size?
  1618.     je    gofil9            ; e = yes
  1619.     mov    nmoflg,1        ; say that we have a replacement name
  1620.                 ; filename is now in 'decbuf', all converted
  1621. gofil9:    test    flags.remflg,dquiet    ; quiet display mode?
  1622.     jnz    gofi10            ; nz = yes, don't print it
  1623.     test    flags.remflg,dserial    ; serial display mode?
  1624.     jz    gofi9a            ; z = no
  1625.     mov    ah,prstr
  1626.     mov    dx,offset crlf        ; display cr/lf
  1627.     int    dos
  1628. gofi9a:    call    prtfn            ; show packet filename
  1629.     cmp    nmoflg,0        ; using local override name?
  1630.     je    gofil9b            ; e = no
  1631.     cmp    flags.xflg,0        ; receiving to screen? (X versus F)
  1632.     jne    gofil9b            ; ne = yes
  1633.     mov    ah,prstr
  1634.     mov    dx,offset asmsg        ; print " as "
  1635.     int    dos
  1636.     mov    dx,offset decbuf    ; plus the local filename
  1637.     call    prtasz            ; print asciiz string
  1638. gofil9b:mov    ah,flags.remflg        ; display a following cr/lf?
  1639.     and    ah,dserial        ; for serial display mode
  1640.     or    ah,flags.xflg        ; receiving to screen
  1641.     jz    gofi10            ; z = neither, no cr/lf
  1642.     mov    ah,prstr        ; finish the line with cr/lf
  1643.     mov    dx,offset crlf
  1644.     int    dos
  1645. gofi10:    mov    ax,offset decbuf    ; point to name
  1646.     cmp    flags.flwflg,1        ; overwrite existing file?
  1647.     jne    gofi10b            ; ne = no
  1648.     jmp    gofi16            ; e = yes
  1649. gofi10b:call    isfile            ; does it exist?
  1650.     mov    ax,offset decbuf    ; reload ptr in case
  1651.     jc    gofi16            ; carry set = no, just proceed
  1652.     mov    ah,open2        ; could it be a device name?
  1653.     xor    al,al            ; open readonly
  1654.     cmp    dosnum,300h        ; above DOS 2?
  1655.     jb    gofi10a            ; b = no, so no shared access
  1656.     or    al,40h            ; open for reading, deny none
  1657. gofi10a:mov    dx,offset decbuf    ; the filename
  1658.     int    dos
  1659.     jc    gofi11            ; c = cannot open so just proceed
  1660.     mov    bx,ax            ; file handle
  1661.     mov    ah,ioctl
  1662.     xor    al,al            ; 0 = get info
  1663.     int    dos
  1664.     mov    ah,close2        ; close it
  1665.     int    dos
  1666.     mov    ax,offset decbuf    ; point to filename again
  1667.     test    dl,80h            ; ISDEV bit set?
  1668.     jz    gofi11            ; z = no, not a device
  1669.     jmp    gofi16            ; device, use name as given
  1670. gofi11:    cmp    flags.flwflg,4        ; no-supersede existing file?
  1671.     jne    gofi12            ; ne = no (i.e., do a rename)
  1672.     mov    flags.cxzflg,'X'    ; say stop this file
  1673.     mov    word ptr decbuf,'UN'
  1674.     mov    decbuf+2,'L'        ; file name of NUL
  1675.     mov    decbuf+3,0        ; asciiz
  1676.     jmp    short gofi13
  1677. gofi12:    mov    ax,offset decbuf    ; point to filename again
  1678.     call    unique            ; generate unique name
  1679.     jc    gofi14            ; could not generate a unique name
  1680.     test    flags.remflg,dquiet    ; quiet display mode?
  1681.     jnz    gofi13            ; nz = yes, skip printing
  1682.     push    ax            ; save unique name again
  1683.     call    frpos            ; position cursor
  1684.     mov    ah,prstr           ; say we are renaming the file
  1685.     mov    dx,offset infms5
  1686.     int    dos
  1687.     pop    ax            ; get name back into ax again
  1688.     push    ax            ; save around these calls
  1689.     mov    dx,ax            ; print current filename
  1690.     call    prtasz            ; display filename
  1691.     pop    ax            ; pointer to name, again
  1692. gofi13:    jmp    short gofi16        ; and go handle file
  1693.  
  1694. gofi14:    mov    dx,offset ermes4
  1695.     call    ermsg
  1696.     stc                ; failure, dx has msg pointer
  1697.     ret
  1698.  
  1699. gofi16:    mov    si,ax             ; pointer to (maybe new) name
  1700.     mov    di,offset diskio.string    ; filename, used in open
  1701.     mov    dx,di            ;  for isfile and open below
  1702.     call    strcpy             ; copy name to diskio.string
  1703.     xor    ax,ax
  1704.     mov    diskio.sizehi,ax    ; original file size is unknown
  1705.     mov    diskio.sizelo,ax    ; double word
  1706.     mov    tfilsz,ax        ; set bytes received to zero
  1707.     mov    tfilsz+2,ax
  1708.     mov    ax,-1            ; get a minus one
  1709.     mov    oldkbt,ax
  1710.     mov    oldper,ax
  1711.     clc                ; finished composing filename
  1712.     ret                ; in diskio.string
  1713.                     ; Come here to formally open the file
  1714.  
  1715. gofi18a:mov    si,ax             ; pointer to local override name
  1716.     mov    di,offset diskio.string    ; filename, used in open
  1717.     call    strcpy             ; copy name to diskio.string
  1718.                     ; fall    through to gofi18
  1719. gofi18:    test    flags.remflg,dquiet    ; quiet display mode?
  1720.     jnz    gofi19            ; nz = yes, don't try printing
  1721.     mov    dx,offset erms12    ; unable to create file
  1722.     call    ermsg
  1723.     push    dx
  1724.     mov    dx,offset diskio.string    ; print offending name
  1725.     call    prtasz            ; display filename
  1726.     pop    dx
  1727. gofi19:    stc                ; failure, dx has msg pointer
  1728.     ret
  1729. gofil    endp
  1730.  
  1731. ; Open file for writing with name in diskio.string
  1732. goopen    proc    near
  1733.     mov    dblbyteflg,0        ; clear decoder state variable
  1734.     mov    shiftstate,0        ; locking shift state
  1735.     mov    DLEseen,0        ; escape state
  1736.     mov    dx,offset diskio.string    ; filename, asciiz
  1737.     mov    diskio.handle,0        ; clear handle of previous usage
  1738.     mov    ax,dx            ; filename for isfile
  1739.     call    isfile        ; check for read-only/system/vol-label/dir
  1740.     jc    goopen1            ; c = file does not exist
  1741.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  1742.     jnz    gofi18            ; nz = do not write over one of these
  1743. goopen1:test    filtst.fstat,80h    ; access problem?
  1744.     jnz    gofi18            ; nz = yes, quit here
  1745.     mov    diskio.handle,-1    ; clear handle of previous usage
  1746.     mov    ah,creat2        ; create file
  1747.     xor    cx,cx            ; 0 = attributes bits
  1748.     int    dos
  1749.     jc    goopen2            ; c = did not work, try regular open
  1750.     mov    diskio.handle,ax    ; save file handle here
  1751.     clc                ; carry clear for success
  1752.     ret
  1753. goopen2:test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  1754.     jnz    gofi18            ; we won't touch these
  1755.     mov    ah,open2           ; open existing file (usually a device)
  1756.     mov    al,1+1            ; open for writing
  1757.     int    dos
  1758.     jc    gofi18            ; carry set means can't open
  1759.     mov    diskio.handle,ax    ; file handle
  1760.     clc                ; carry clear for success
  1761.     ret
  1762. goopen    endp
  1763.  
  1764. ; Given incoming filename in 'decbuf'.  Verify that each char is legal
  1765. ; (if not change it to an "X"), force max of three chars after a period (dot)
  1766. ; Source is at ds:si (si is changed here).
  1767.  
  1768. VERFIL    PROC    NEAR
  1769.     push    es            ; verify each char in 'data'
  1770.     push    cx
  1771.     push    ds
  1772.     pop    es
  1773.     mov    havdot,0        ; say no dot found in name yet
  1774.     cld
  1775. verfi1:    lodsb                ; get a byte of name from si
  1776.     and    al,7fH            ; strip any eighth bit
  1777.     jz    verfi5            ; z = end of name
  1778.     cmp    al,'.'            ; a dot?
  1779.     jne    verfi2            ; ne = no
  1780.     cmp    havdot,0        ; have one dot already?
  1781.     jne    verfi3            ; ne = yes, change to X
  1782.     mov    byte ptr [si+3],0    ; forceably end filename after 3 char ext
  1783.     mov    havdot,1        ; say have a dot now
  1784.     jmp    short verfi4        ; continue
  1785. verfi2:    cmp    al,3ah            ; colon?
  1786.     je    verfi4
  1787.     cmp    al,5ch            ; backslash path separator?
  1788.     je    verfi4
  1789.     cmp    al,2fh            ; or forward slash?
  1790.     je    verfi4
  1791.     cmp    al,'0'
  1792.     jb    verfi3            ; see if it's a legal char < '0'
  1793.     cmp    al,'9'
  1794.     jbe    verfi4            ; it's between 0-9 so it's OK
  1795.     cmp    al,'A'
  1796.     jb    verfi3            ; check for a legal punctuation char
  1797.     cmp    al,'Z'
  1798.     jbe    verfi4            ; it's A-Z so it's OK
  1799.     cmp    al,'a'
  1800.     jb    verfi3            ; check for a legal punctuation char
  1801.     cmp    al,'z'
  1802.     ja    verfi3
  1803.     and    al,5FH            ; it's a-z, capitalize
  1804.     jmp    short verfi4        ; continue with no change
  1805.  
  1806. verfi3:    push    di            ; special char. Is it on the list?
  1807.     mov    di,offset spchar2    ; list of acceptable special chars
  1808.     mov    cx,spc2len
  1809.     cld
  1810.     repne    scasb            ; search string for input char
  1811.     pop    di
  1812.     je    verfi4            ; e = in table, return it
  1813.     mov    al,'X'            ; else illegal, replace with "X"
  1814.     mov    nmoflg,1        ; say we have a replacement filename
  1815. verfi4:    mov    [si-1],al        ; update name
  1816.     jmp    short verfi1        ; loop thru rest of name
  1817. verfi5:    mov    byte ptr[si-1],0    ; make sure it's null terminated
  1818.     pop    cx
  1819.     pop    es
  1820.     ret
  1821. VERFIL    ENDP
  1822.  
  1823. ; find a unique filename.
  1824. ; Enter with a pointer to a (null-terminated) filename in ax
  1825. ; Return with same pointer but with a new name (or old if failure)
  1826. ; Success = carry clear; failure = carry set
  1827. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  1828. ; then change the last chars successively to a 1, 2, etc. until
  1829. ; a unique name is found. All registers are preserved
  1830. ; Make empty main name fields start with letter X, not digit 0
  1831. unique    proc    near
  1832.     push    bx
  1833.     push    cx
  1834.     push    dx
  1835.     push    si
  1836.     push    di
  1837.     push    es
  1838.     push    ax            ; save address of source string
  1839.     mov    dx,ds            ; make es use ds segment
  1840.     mov    es,dx
  1841.     mov    dx,ax            ; point at original filename string
  1842.     mov    di,offset templp    ; place for path
  1843.     mov    si,offset templf    ; place for filename
  1844.     call    fparse            ; separate path (di) and filename (si)
  1845.     mov    dx,di            ; point at path part
  1846.     call    strlen            ; put length in cx
  1847.     mov    si,ax            ; point to original string
  1848.     add    si,cx            ; point to filename part
  1849.     mov    di,offset templf    ; destination is temporary location
  1850.     xor    cx,cx            ; a counter
  1851.     cld                ; set direction to be forward
  1852. uniq1:    lodsb                ; get a byte
  1853.     cmp    al,'.'            ; have a dot?
  1854.     je    uniq2            ; e = yes
  1855.     or    al,al            ; maybe    null at end?
  1856.     jnz    uniq3            ; nz = no, continue loop
  1857.  
  1858. uniq2:    cmp    cl,8            ; have we copied any chars before dot?
  1859.     jge    uniq3            ; ge = all 8
  1860.     mov    byte ptr [di],'0'    ; avoid clobbers; pad with 0's
  1861.     or    cl,cl            ; first char of filename?
  1862.     jnz    uniq2a            ; nz = no
  1863.     mov    byte ptr [di],'X'    ; start name with letter X, not 0
  1864. uniq2a:    inc    di            ; and count the output chars
  1865.     inc    cl            ; and this counter too
  1866.     jmp    short uniq2        ; continue until filled 8 slots
  1867. uniq3:    inc    cl            ; cl = # char in destination
  1868.     stosb                ; store the char
  1869.     or    al,al            ; null at end?
  1870.     jnz    uniq1            ; nz = no, continue copying
  1871.  
  1872.     mov    templf+7,'1'        ; put '1' in last name char
  1873.     mov    unum,1            ; start with this generation digit
  1874.  
  1875. uniq4:    mov    di,offset rdbuf        ; build a temporary full filename
  1876.     mov    si,offset templp    ; path part
  1877.     call    strcpy            ; copy that much
  1878.     mov    si,offset templf    ; get rebuilt filename part
  1879.     call    strcat            ; paste that to the end
  1880.     mov    ax,offset rdbuf        ; point to full name
  1881.     call    isfile            ; does it exist?
  1882.     jc    uniq6            ; c = no, succeed now
  1883.  
  1884.     inc    unum            ; move to next generation
  1885.     mov    di,offset templf+7    ; point to last name char
  1886.     mov    cx,7            ; max # of digits to play with
  1887.     mov    bx,10            ; divisor (16 bits)
  1888.     mov    ax,unum            ; low order part of generation #
  1889. uniq5:    xor    dx,dx            ; high order part of generation #
  1890.     div    bx            ; compute digit (unum / 10)
  1891.     add    dl,'0'            ; make remainder part printable
  1892.     mov    [di],dl            ; put into right place
  1893.     or    ax,ax            ; any more to do? (quotient nonzero)
  1894.     jz    uniq4            ; z = no, try this name
  1895.     dec    di            ; else decrement char position
  1896.     loop    uniq5            ;   and keep making a number
  1897.     stc                ; failure: set carry, keep old name
  1898.     jmp    short uniq7        ;   and exit
  1899.  
  1900. uniq6:    pop    di            ; address of original filename
  1901.     push    ax            ; save for exit clean up
  1902.     mov    si,offset rdbuf
  1903.     call    strcpy            ; copy new filename over old
  1904.     clc                ; success: clear carry flag
  1905. uniq7:    pop    ax
  1906.     pop    es
  1907.     pop    di
  1908.     pop    si
  1909.     pop    dx
  1910.     pop    cx
  1911.     pop    bx
  1912.     ret
  1913. unique    endp
  1914.     
  1915.  
  1916. ; strlen -- computes the length, excluding the terminator, of an asciiz
  1917. ;    string. Input: ds:dx = address of the string
  1918. ;        Output: cx = the byte count
  1919. ;    All registers except cx are preserved
  1920. ;
  1921. STRLEN    PROC    NEAR
  1922.     push    di
  1923.     push    es
  1924.     push    ax
  1925.     mov    ax,ds            ; use proper segment address
  1926.     mov    es,ax
  1927.     mov    di,dx
  1928.     mov    cx,0ffffh        ; large byte count
  1929.     cld                ; set direction to be forward
  1930.     xor    al,al            ; item sought is a null
  1931.     repne    scasb            ; search for it
  1932.     add    cx,2            ; add for -1 and auto dec in scasb
  1933.     neg    cx              ; convert to count, excluding terminator
  1934.     pop    ax
  1935.     pop    es
  1936.     pop    di
  1937.     ret
  1938. STRLEN    ENDP
  1939.  
  1940. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  1941. ;    offset of string 1 is expected to be in ds:di. input & output
  1942. ;    offset of string 2 is expected to be in ds:si. input only (unchanged)
  1943. ;    Preserves all registers. No error returns, returns normally via ret
  1944. ;
  1945. STRCAT    PROC    NEAR
  1946.     push    di            ; save work registers
  1947.     push    si
  1948.     push    es
  1949.     push    dx
  1950.     push    cx
  1951.     push    ax
  1952.     mov    ax,ds            ; get data segment value
  1953.     mov    es,ax            ; set es to ds for implied es:di usage
  1954.     mov    dx,di
  1955.     call    strlen        ; get length (w/o terminator) of dest string
  1956.     add    di,cx            ; address of first terminator
  1957.     mov    dx,si            ; start offset of source string
  1958.     call    strlen            ; find its length too (in cx)
  1959.     inc    cx            ; include its terminator in the count
  1960.     cld
  1961.     rep    movsb        ; copy source string to end of output string
  1962.     pop    ax
  1963.     pop    cx
  1964.     pop    dx
  1965.     pop    es
  1966.     pop    si
  1967.     pop    di
  1968.     ret
  1969. STRCAT    ENDP
  1970.  
  1971. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  1972. ;    ds:di. Returns via ret. All registers are preserved
  1973. ;
  1974. STRCPY    PROC    NEAR
  1975.     cmp    si,di            ; same place?
  1976.     jne    strcpy1            ; ne = no
  1977.     ret                ; having done nothing
  1978. strcpy1:mov    byte ptr [di],0        ; clear destination string
  1979.     call    strcat            ; let strcat do the real work
  1980.     ret
  1981. STRCPY    ENDP
  1982.  
  1983. ; fparse -- separate the drive:path part from the filename.ext part of an
  1984. ;    asciiz string. Characters separating parts are  \ or / or :
  1985. ;    Inputs:    asciiz input full filename string offset in ds:dx
  1986. ;        asciiz path offset in ds:di
  1987. ;        asciiz filename offset in ds:si
  1988. ;    Outputs: the above strings in the indicated spots
  1989. ;    Strategy is simple. Reverse scan input string until one of the
  1990. ;    three separators is encountered and then cleave at that point
  1991. ;    Simple filename construction restrictions added 30 Dec 1985;
  1992. ;    to wit: mainname limited to 8 chars or less,
  1993. ;    extension field limited to 3 chars or less and is found by searching
  1994. ;    for first occurence of a dot in the filename field. Thus the whole
  1995. ;    filename part is restricted to 12 (8+dot+3) chars plus a null
  1996. ;    All registers are preserved. Return is always via ret
  1997. ;    (Microsoft should have written this for DOS 2.x et seq.)
  1998.  
  1999. FPARSE    PROC    NEAR
  2000.     push    cx            ; local counter
  2001.     push    ax            ; local work area
  2002.     push    es            ; implied segment register for di
  2003.     push    di            ; offset of path part of output
  2004.     push    si            ; offset of file name part of output
  2005.     mov    ax,ds            ; get data segment value
  2006.     mov    es,ax            ; set es to ds for implied es:di usage
  2007.     mov    byte ptr [si],0        ; clear outputs
  2008.     mov    byte ptr [di],0
  2009.  
  2010.     push    si            ; save original file name address
  2011.     mov    si,dx            ; get original string address
  2012.     call    strcpy            ; copy string to original di
  2013.     call    strlen            ; find length (w/o terminator), in cx
  2014.     mov    si,di            ; address of string start
  2015.     add    si,cx
  2016.     dec    si            ; si = address of last non-null char
  2017.     jcxz    fpars5            ; if null skip the path scan
  2018.                     ; now find last path char, if any
  2019.                     ; start at the end of input string
  2020.     std                 ; set direction to be backward
  2021. fpars4:    lodsb                 ; get a byte (dec's si afterward)
  2022.     cmp    al,5ch            ; is it a backslash ('\')? 
  2023.     je    fpars6          ; e = yes
  2024.     cmp    al,2fh            ; or forward slash ('/')?
  2025.     je    fpars6          ; e = yes
  2026.     cmp    al,3ah            ; or even the drive terminator colon?
  2027.     je    fpars6            ; e = yes
  2028.     loop    fpars4             ; else keep looking until cx == 0
  2029.                       ; si is at beginning of file name
  2030. fpars5:    dec    si            ; dec for inc below
  2031. fpars6:    inc    si
  2032.     inc    si            ; si now points at first filename char
  2033.                     ; cx holds number of path chars
  2034.                     ; get original file name address (si)
  2035.     pop    di            ; and make it place to copy filename
  2036.     cld                ; reset direction to be forward
  2037.     mov    ax,si            ; ax holds filename address for awhile
  2038.     push    dx
  2039.     mov    dx,si            ; strlen wants string pointer in dx
  2040.     call    strlen            ; get length of filename part into cx
  2041.     pop    dx
  2042.     jcxz    fpar7a            ; any chars to look at? z = no
  2043. fpars7:    cmp    byte ptr [si],'.'    ; look for a dot in filename
  2044.     je    fpars8            ; e = found one
  2045.     inc    si            ; look at next filename char
  2046.     loop    fpars7            ; keep looking until cx = zero
  2047. fpar7a:    mov    si,ax            ; no dot. recover starting address
  2048.     mov    byte ptr [si+8],0    ; forcably truncate mainname to 8 char
  2049.     call    strcpy            ; copy this part to filename field
  2050.     jmp    short fparsx        ;  and exit
  2051. fpars8: mov    byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  2052.     mov    cx,si
  2053.     sub    cx,ax        ; cx now = number of chars in mainname field
  2054.     cmp    cx,9            ; more than 8?
  2055.     jb    fpars9            ; b = no, we're safe
  2056.     mov    cx,8             ; limit ourselves to 8 chars in mainname
  2057. fpars9: push    si             ; remember address of dot and extension
  2058.     mov    si,ax            ; point to start of input filename
  2059.     rep    movsb            ; copy cx chars from si to di (output)
  2060.     mov    byte ptr [di],0        ; plant terminator where dot goes
  2061.     pop    si            ; source = dot and extension address
  2062.     call    strcat        ; append the dot & ext to the filename field
  2063. fparsx: mov    si,ax        ; recover start of filename in input string
  2064.     mov    byte ptr [si],0        ; terminate path field
  2065.     pop    si
  2066.     pop    di
  2067.     pop    es
  2068.     pop    ax
  2069.     pop    cx
  2070.     ret
  2071. FPARSE    ENDP    
  2072.  
  2073. ; Print filename in offset diskio.string.
  2074. PRTFN    PROC    NEAR
  2075.     test    flags.remflg,dquiet    ; quiet display mode?
  2076.     jnz    prtfn1            ; nz = yes, don't display filename
  2077.     push    ax            ; saves for messy clrfln routine
  2078.     push    bx
  2079.     push    dx
  2080.     call    clrfln            ; position cursor & blank out the line
  2081.     mov    dx,offset diskio.string
  2082.     call    prtasz
  2083.     pop    dx
  2084.     pop    bx
  2085.     pop    ax
  2086. prtfn1:    ret
  2087. PRTFN    ENDP
  2088.  
  2089.  
  2090. ; Print string to screen from offset ds:di for # bytes given in cx,
  2091. ; regardless of $'s.  All registers are preserved.
  2092.  
  2093. PRTSCR    PROC    NEAR
  2094.     jcxz    prtscr4            ; cx = zero means nothing to show
  2095.     push    ax
  2096.     push    bx
  2097.     push    dx
  2098.     mov    dx,di            ; source ptr for DOS
  2099.     cmp    flags.eofcz,0        ; end on Control-Z?
  2100.     jne    prtscr3            ; ne = yes, let DOS do it
  2101.     push    cx            ; else map Control-Z to space
  2102.     push    di
  2103.     push    es
  2104.     push    ds
  2105.     pop    es            ; data to es
  2106.     mov    al,ctlz            ; look for Control-Z
  2107.     cld                ; scan buffer es:di, cx chars worth
  2108. prtscr1:repne    scasb
  2109.     jne    prtscr2            ; ne = found no Control-Z's
  2110.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  2111.     jcxz    prtscr2            ; z = examined all chars
  2112.     jmp    short prtscr1        ; until examined everything
  2113. prtscr2:pop    es
  2114.     pop    di
  2115.     pop    cx
  2116. prtscr3:mov    bx,1            ; stdout file handle
  2117.     mov    ah,write2
  2118.     int    dos
  2119.     pop    dx
  2120.     pop    bx
  2121.     pop    ax
  2122. prtscr4:ret
  2123. PRTSCR    ENDP
  2124.  
  2125. ; Print to screen asciiz string given in ds:dx. Everything preserved.
  2126. PRTASZ    PROC    NEAR
  2127.     push    cx
  2128.     push    di
  2129.     call    strlen            ; get length of asciiz string
  2130.     mov    di,dx            ; where prtscr looks
  2131.     call    prtscr            ; print counted string
  2132.     pop    di
  2133.     pop    cx
  2134.     ret
  2135. PRTASZ    ENDP
  2136.  
  2137. ;;; Load a translation table for file transfer
  2138. load    proc    near
  2139. ;;    mov    dx,offset loadtab    ; keyword Transfer-character-set
  2140. ;;    xor    bx,bx            ; help
  2141. ;;    mov    ah,cmkey
  2142. ;;    call    comnd
  2143. ;;    jnc    load0
  2144. ;;    ret
  2145. ;;load0:    mov    dx,offset rdbuf        ; buffer for filename
  2146. ;;    mov    word ptr rdbuf,0
  2147. ;;    mov    bx,offset loadhlp    ; help
  2148. ;;    mov    ah,cmword
  2149. ;;    call    comnd            ; get filename
  2150. ;;    jnc    load1            ; nc = success
  2151. ;;    ret                ; failure
  2152. ;;load1:    mov    ax,offset rdbuf        ; place for filename for isfile
  2153. ;;    call    isfile            ; does file exist?
  2154. ;;    jnc    load1b
  2155. ;;load1a:    mov    dx,offset infms6    ; unable to open file
  2156. ;;    mov    ah,prstr
  2157. ;;    int    dos
  2158. ;;    stc
  2159. ;;    ret                ; c = does not exist
  2160. ;;load1b:    mov    dx,ax
  2161. ;;    mov    cx,134
  2162. ;;    mov    ah,open2        ; file open
  2163. ;;    xor    al,al            ; 0 = open readonly
  2164. ;;    cmp    dosnum,300h        ; at or above DOS 2?
  2165. ;;    jb    load2            ; b = no, so no shared access
  2166. ;;    or    al,40h            ; open readonly, deny none
  2167. ;;load2:    int    dos
  2168. ;;    jc    load1a            ; if carry then error
  2169. ;;    mov    diskio.handle,ax    ; file handle
  2170. ;;                    ; read and parse lines
  2171. ;;    mov    linecnt,0        ; line counter
  2172. ;;    call    readln            ; L1, read and discard table name
  2173. ;;    jc    load5            ; c = failure
  2174. ;;    call    readln            ; L2, COMMON or LOCAL
  2175. ;;    jc    load5            ; c = failure
  2176. ;;    mov    ax,word ptr rdbuf
  2177. ;;    or    ax,2020h        ; to lower case
  2178. ;;    mov    tblptr,offset userin
  2179. ;;    cmp    ax,'oc'            ; "common"? (on the wire to local)
  2180. ;;    je    load4            ; e = yes
  2181. ;;    mov    tblptr,offset userout
  2182. ;;    cmp    ax,'ol'            ; "local"? (local to on the wire)
  2183. ;;    jne    load5            ; ne = no, fail
  2184. ;;
  2185. ;;load4:    call    readln            ; L3 name of comms line char set
  2186. ;;    jnc    load6            ; success
  2187. ;;load5:    jmp    loadx
  2188. ;;
  2189. ;;load6:    call    readln            ; L4 bytes per char in above set
  2190. ;;    jc    load5
  2191. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2192. ;;    call    atoi            ; ax has value
  2193. ;;    jc    load5            ; c = no number
  2194. ;;    cmp    ax,1            ; one byte per char?
  2195. ;;    jne    load5            ; ne = no, fail here
  2196. ;;
  2197. ;;    call    readln            ; L5 chars/plane (94/96/128)
  2198. ;;    jc    load7            ; c = failure
  2199. ;;    mov    dx,offset rdbuf
  2200. ;;    call    strlen
  2201. ;;    mov    ah,cl
  2202. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2203. ;;    call    atoi            ; ax has value
  2204. ;;    jc    load7            ; c = no number
  2205. ;;    cmp    ax,128            ; too many?
  2206. ;;    ja    load7            ; a = yes, fail here
  2207. ;;
  2208. ;;    call    readln            ; L6 name of local display char set
  2209. ;;    jnc    load8
  2210. ;;load7:    jmp    loadx
  2211. ;;
  2212. ;;load8:    call    readln            ; L7 bytes per char in above set
  2213. ;;    jc    load7
  2214. ;;    mov    dx,offset rdbuf
  2215. ;;    call    strlen
  2216. ;;    mov    ah,cl
  2217. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2218. ;;    call    atoi            ; ax has value
  2219. ;;    jc    load7            ; c = no number
  2220. ;;    cmp    ax,1            ; one byte per char?
  2221. ;;    jne    load7            ; ne = no, fail here
  2222. ;;
  2223. ;;    call    readln            ; L8 chars/plane (94/96/128)
  2224. ;;    jc    load7            ; failure
  2225. ;;    mov    dx,offset rdbuf
  2226. ;;    call    strlen
  2227. ;;    mov    ah,cl
  2228. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2229. ;;    call    atoi            ; ax has value
  2230. ;;    jc    load7            ; c = no number
  2231. ;;    cmp    ax,128            ; too many?
  2232. ;;    ja    load7            ; a = yes, fail here
  2233. ;;
  2234. ;;    call    readln            ; L9 designator of comms line set
  2235. ;;    jc    load8
  2236. ;;    call    readln            ; L10 Version of comms line set
  2237. ;;    jc    load8
  2238. ;;    call    readln            ; L11 Registration num of comms set
  2239. ;;    jc    load8
  2240. ;;    call    readln            ; L12 direction of writing
  2241. ;;    jc    load8
  2242. ;;    call    readln            ; L13 number of entries in table below
  2243. ;;    jc    load7
  2244. ;;    mov    dx,offset rdbuf
  2245. ;;    call    strlen
  2246. ;;    mov    ah,cl
  2247. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2248. ;;    call    atoi            ; ax has value
  2249. ;;    jc    load7            ; c = no number
  2250. ;;    mov    xlines,ax
  2251. ;;
  2252. ;;    call    readln            ; L14 count of filler lines before
  2253. ;;    jc    load7            ;  table below
  2254. ;;    mov    dx,offset rdbuf
  2255. ;;    call    strlen            ; length to cx
  2256. ;;    mov    ah,cl
  2257. ;;    mov    si,offset rdbuf        ; text, ah has char count
  2258. ;;    call    atoi            ; ax has value
  2259. ;;    jc    load7            ; c = no number
  2260. ;;    mov    cx,ax            ; count of filler lines
  2261. ;;    jcxz    load10            ; z = none
  2262. ;;load9:    push    cx
  2263. ;;    call    readln            ; L15 et seq, filler lines
  2264. ;;    pop    cx            ; read and discard
  2265. ;;    jc    loadx
  2266. ;;    loop    load9
  2267. ;;
  2268. ;;load10:    dec    xlines            ; Translation data lines
  2269. ;;    cmp    xlines,0        ; any left?
  2270. ;;    jge    load11            ; ge = yes
  2271. ;;    jmp    loady
  2272. ;;load11:    call    readln            ; translation table line(s)
  2273. ;;    jc    loadx            ; c = failure
  2274. ;;    mov    si,offset rdbuf        ; the buffer
  2275. ;;    mov    dx,si
  2276. ;;    call    strlen            ; length to cx
  2277. ;;    mov    ah,cl            ; count for atoi
  2278. ;;    call    atoi            ; get "from" number
  2279. ;;    jc    loadx            ; failure
  2280. ;;    test    al,80h            ; referring to high bit set (GR)?
  2281. ;;    jnz    load12            ; nz = yes
  2282. ;;    jmp    loadx
  2283. ;;load12:    and    ax,not 0ff80h        ; strip bit for GR table
  2284. ;;    mov    temp,ax            ; save here
  2285. ;;    mov    dx,si
  2286. ;;    call    strlen
  2287. ;;    mov    ah,cl            ; count
  2288. ;;    call    atoi            ; get "to" number
  2289. ;;    mov    bx,tblptr        ; point at table
  2290. ;;    add    bx,temp            ; locate entry
  2291. ;;    mov    [bx],al            ; store new value
  2292. ;;    jmp    load10            ; repeat til done
  2293. ;;
  2294. ;;loadx:    mov    dx,offset badvalue    ; complain
  2295. ;;    mov    ah,prstr
  2296. ;;    int    dos
  2297. ;;    mov    ax,linecnt        ; show line number
  2298. ;;    call    decout
  2299. ;;    mov    ah,conout
  2300. ;;    mov    dl,':'
  2301. ;;    int    dos
  2302. ;;    mov    dx,offset rdbuf        ; show the line
  2303. ;;    call    prtasz
  2304. ;;loady:    mov    bx,diskio.handle
  2305. ;;    mov    ah,close2        ; close the file
  2306. ;;    int    dos
  2307.     clc
  2308.     ret
  2309. load    endp
  2310. ;;
  2311. ;;readln    proc    near
  2312. ;;    push    ax
  2313. ;;    push    bx
  2314. ;;    push    cx
  2315. ;;    push    dx
  2316. ;;    push    di
  2317. ;;    inc    linecnt            ; line counter
  2318. ;;    mov    cx,82            ; 82 bytes, including trailer
  2319. ;;    mov    temp,0            ; leading whitespace and comment flgs
  2320. ;;    mov    di,offset rdbuf        ; destination buffer
  2321. ;;    mov    bx,diskio.handle    ; file handle
  2322. ;;readln1:push    cx            ; read from file
  2323. ;;    mov    cx,1            ; read 1 char
  2324. ;;    mov    dx,di            ; place here
  2325. ;;    mov    byte ptr [di],0        ; insert terminator
  2326. ;;    mov    ah,readf2
  2327. ;;    int    dos
  2328. ;;    pop    cx
  2329. ;;    jc    readlnx            ; c = read failure
  2330. ;;    or    ax,ax            ; count of bytes read
  2331. ;;    jz    readlnx            ; z means end of file
  2332. ;;    cmp    byte ptr [di],LF    ; LF?
  2333. ;;    je    readln3            ; e = yes, ignore it
  2334. ;;    cmp    byte ptr [di],CR    ; end of line?
  2335. ;;    je    readln4            ; e = yes, exit
  2336. ;;    cmp    byte ptr [di],';'    ; start of comment?
  2337. ;;    jne    readln6            ; ne = no
  2338. ;;    mov    byte ptr temp+1,1    ; say comment has started
  2339. ;;    jmp    short readln3        ; do not store it
  2340. ;;readln6:cmp    byte ptr temp+1,0    ; seen comment semicolon yet?
  2341. ;;    jne    readln3            ; ne = yes, do not store comment
  2342. ;;    cmp    byte ptr temp,0        ; seen non-spacing char yet?
  2343. ;;    jne    readln2            ; ne = yes
  2344. ;;    cmp    byte ptr [di],' '    ; is this a space?
  2345. ;;    je    readln3            ; e = yes, skip it
  2346. ;;    cmp    byte ptr [di],TAB    ; or a tab?
  2347. ;;    je    readln3            ; e = yes, skip it
  2348. ;;    mov    byte ptr temp,1        ; say have seen non-spacing char
  2349. ;;readln2:cmp    flags.takflg,0        ; echo Take files?
  2350. ;;    je    readln2a        ; e = no
  2351. ;;    mov    ah,conout
  2352. ;;    mov    dl,byte ptr [di]
  2353. ;;    int    dos
  2354. ;;readln2a:inc    di            ; next storage cell
  2355. ;;readln3:loop    readln1            ; loop til end of line
  2356. ;;readln4:cmp    flags.takflg,0        ; echo Take files?
  2357. ;;    je    readln4a        ; e = no
  2358. ;;    mov    ah,prstr
  2359. ;;    mov    dx,offset crlf
  2360. ;;    int    dos
  2361. ;;readln4a:clc
  2362. ;;    mov    byte ptr [di],0        ; insert final terminator
  2363. ;;    jmp    short readlnx
  2364. ;;
  2365. ;;readln5:stc                ; set carry for failure to read
  2366. ;;readlnx:pop    di
  2367. ;;    pop    dx
  2368. ;;    pop    cx
  2369. ;;    pop    bx
  2370. ;;    pop    ax
  2371. ;;    ret
  2372. ;;readln    endp
  2373. code    ends 
  2374.     end
  2375.