NAME mssfil ; File MSSFIL.ASM include mssdef.h ; Copyright (C) 1982, 1997, Trustees of Columbia University in the ; City of New York. The MS-DOS Kermit software may not be, in whole ; or in part, licensed or sold for profit as a software product itself, ; nor may it be included in or distributed with commercial products ; or otherwise distributed by commercial concerns to their clients ; or customers without written permission of the Office of Kermit ; Development and Distribution, Columbia University. This copyright ; notice must not be removed, altered, or obscured. ; ; Edit history ; 12 Jan 1995 version 3.14 ; Last edit ; 12 Jan 1995 ; 27 August 1992 version 3.13 ; 6 Sept 1991 version 3.11 ; 2 March 1991 version 3.10 public buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec public encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr public strlen, strcat, strcpy, tfilsz, templp, latin1, charids public L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique public cplatin, goopen, latininv, protlist, jpnxtof, templf public jpnftox, echrcnt, rcvpathflg, sndpathflg, atfile, atflag public l5cp866, lccp866r, k8cp866r, k7cp866r, cp866koi7, cp866koi8 public cp866lci SIchar equ 0fh SOchar equ 0eh DLE equ 10h data segment extrn flags:byte, trans:byte, dtrans:byte, denyflg:word,dosnum:word extrn oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte extrn curdsk:byte, fdate:byte, ftime:byte, wrpmsg:byte ermes4 db 'Unable to make unique name',0 ermes9 db 'Printer not ready',0 erms12 db 'Unable to create file ',0 erms13 db 'Error writing output file',0 infms5 db 'Renaming file to $' infms6 db cr,lf,'?Unable to open file$' asmsg db ' as $' crlf db cr,lf,'$' printer db 'PRN',0 screen db 'CON',0 vacuum db 'NUL',0 loadhlp db 'filename$' ; DOS special chars allowed in filenames spchar2 db '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh db 5fh, 5eh, 7eh, 60h spc2len equ $-spchar2 textctl db cr,lf,tab,bell,ff,ctlz ; controls allowed in text files textctlen equ $-textctl even filflg db 0 ; input buffer has data, if non-zero rptct db 1 ; number of times it's repeated dblbyte db 0 ; first of two bytes in a pair dblbyteflg db 0 ; non-zero if processing second byte of pair DLEseen db 0 shiftstate db 0 ; locking shift (0 = unshifted, 80h = shifted) decoutp dw 0 ; ptr to proc to dump decode output buffer encinp dw 0 ; ptr to proc to refill encode input buffer dchrcnt dw 0 ; number of chars in the decode file buffer echrcnt dw 0 ; number of chars in the encode file buffer dbufpnt dw 0 ; position in file buffer, decoder ebufpnt dw 0 ; position in file buffer, encoder db 0 ; this MUST directly preceed decbuf, jpnwrite decbuf db decbuflen dup (0) ; decoding source buffer db 0 ; safety for possible null terminator encbuf db encbuflen dup (0) ; encoding source buffer db 0 ; safety for possible null terminator protlist db 32 dup (0) ; list of protected control codes (if = 0) tfilsz dw 0,0 ; bytes transferred (double word qty) nmoflg db 0 ; have override filename, if non-zero templp db 65 dup (0) ; temp for local path part templf db 14 dup (0) ; temp for local filename part temprp db 65 dup (0) ; temp for remote path part temprf db 14 dup (0) ; temp for remote filename part auxfile db 65 dup (0) ; auxillary filename for general use atfile db 67 dup (0) ; at sign sending source file atflag db 0 ; non-zero if using at sign file sending diskio filest <> ; ditto, for ordinary file transfers buff db buffsz dup (?) ; use as our Disk Transfer Area havdot db 0 ; dot-found status in verify unum dw 0 ; unique filename generation number ifdef no_terminal rcvpathflg db 0 ; remove(0)/retain(1) remote paths on RECEIVE else rcvpathflg db 1 ; remove(0)/retain(1) remote paths on RECEIVE endif ; no_terminal BBS flavor gets no receive pathnames sndpathflg db 0 ; remove(0)/retain(1) local paths on SEND temp dw 0 ; charids: table of transfer char-set idents charids dw 7 ; qty, pointers to char set idents dw chtrans,chlatin1,chlatin2,chhebiso,chcyrill,chjapan,chjapanold chtrans db 1,'A' ; Transparent: char count, ident chlatin1 db 6,'I6/100' ; Latin1: char count, ident chlatin2 db 6,'I6/101' ; Latin2: char count, ident chhebiso db 6,'I6/138' ; Hebrew-ISO: char count, ident chcyrill db 6,'I6/144' ; Cyrillic: char count, ident chjapan db 9,'I14/87/13' ; Japanese-EUC: char count, ident (new) chjapanold db 7,'I14/87E' ; Japanese-EUC: char count, ident (obsolete) ; end of charids info ;loadtab db 1 ; LOAD command table ; mkeyw 'Transfer-character-set',0 ; ;filtab macro ; cnt = 128 ; rept 128 ; 128 idenity entries ; db cnt ; initialize table to 128 .. 255 ; cnt = cnt + 1 ; endm ;endm ; ;userin equ this byte ; LOAD command ; filtab ; init table to idenity ;namein db 20 dup (0) ; name of the character set ;userout equ this byte ; filtab ; init table to idenity ;nameout db 20 dup (0) ; name of the character set ;tblptr dw 0 ; LOAD command ;xlines dw 0 ; LOAD command ;linecnt dw 0 ; LOAD command ;badvalue db cr,lf,'?Bad value on line $' data ends data1 segment ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is ; considered to be a control code, 80h..9fh are 8-bit controls (C1). ; Each table is 96 translatable bytes followed by the table size (96), the ; ISO announcer ident ('A' and a null here); LATIN5/Cyrillic uses 'L'. ; The decimal tables are from Frank da Cruz working with the formal IBM docs. ; from ISO 8859-1 Latin-1 to Code Page ; to CP437 United States L1cp437 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,0adh,9bh,9ch, 0fh,9dh,7ch,15h ; column 10 db 22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh db 0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah ; column 11 db 2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h db 41h,41h,41h,41h, 8eh,8fh,92h,80h ; column 12 db 45h,90h,45h,45h, 49h,49h,49h,49h db 44h,0a5h,4fh,4fh, 4fh,4fh,99h,58h ; column 13 db 4fh,55h,55h,55h, 9ah,59h,3fh,0e1h db 85h,0a0h,83h,61h, 84h,86h,91h,87h ; column 14 db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh db 3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h ; column 15 db 6fh,97h,0a3h,96h, 81h,79h,3fh,98h db 96,'A',0 ; 96 byte set, letter ident ; to CP850 Multilingual L1cp850 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,0adh,0bdh,9ch, 0cfh,0beh,0ddh,0f5h ; column 10 db 0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh db 0f8h,0f1h,0fdh,0fch, 0efh,0e6h,0f4h,0fah ; column 11 db 0f7h,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h db 0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h ; column 12 db 0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h db 0d1h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,9eh ; column 13 db 9dh,0ebh,0e9h,0eah, 9ah,0edh,0e8h,0e1h db 85h,0a0h,83h,0c6h, 84h,86h,91h,87h ; column 14 db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh db 0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h ; column 15 db 9bh,97h,0a3h,96h, 81h,0ech,0e7h,98h db 96,'A',0 ; 96 byte set, letter ident ; to CP860 Portugal L1cp860 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,0adh,9bh,9ch, 0fh,59h,7ch,15h ; column 10 db 22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh db 0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah ; column 11 db 2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h db 91h,86h,8fh,8eh, 41h,41h,41h,80h ; column 12 db 92h,90h,89h,45h, 8bh,98h,49h,49h db 44h,0a5h,0a9h,9fh, 8ch,99h,4fh,58h ; column 13 db 4fh,9dh,96h,55h, 9ah,59h,3fh,0e1h db 85h,0a0h,83h,84h, 61h,61h,61h,87h ; column 14 db 8ah,82h,88h,65h, 8dh,0a1h,69h,69h db 3fh,0a4h,95h,0a2h, 93h,94h,6fh,0f6h ; column 15 db 6fh,97h,0a3h,75h, 81h,79h,3fh,79h db 96,'A',0 ; 96 byte set, letter ident ; to CP861 Iceland L1cp861 db 80h,0fch,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,0adh,43h,9ch, 0fh,59h,7ch,15h ; column 10 db 22h,3fh,0a6h,0aeh, 0aah,16h,3fh,2dh db 0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah ; column 11 db 2ch,31h,3fh,0afh, 0ach,0abh,3fh,0a8h db 41h,0a4h,41h,41h, 8eh,8fh,92h,80h ; column 12 db 45h,90h,45h,45h, 49h,0a5h,49h,49h db 8bh,4eh,4fh,0a6h, 4fh,4fh,99h,58h ; column 13 db 9dh,55h,0a7h,55h, 9ah,97h,8dh,0e1h db 85h,0a0h,83h,61h, 84h,86h,91h,87h ; column 14 db 8ah,82h,88h,89h, 69h,0a1h,69h,69h db 8ch,6eh,6fh,0a2h, 93h,6fh,94h,0f6h ; column 15 db 9bh,75h,0a3h,96h, 81h,98h,95h,79h db 96,'A',0 ; 96 byte set, letter ident ; to CP863 Canada-French L1cp863 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,3fh,9bh,9ch, 98h,59h,0a0h,8fh ; column 10 db 0a4h,40h,61h,0aeh, 0aah,0c4h,3fh,0a7h db 0f8h,0f1h,0fdh,0a6h, 0a1h,0e6h,86h,0fah ; column 11 db 0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh db 8eh,41h,84h,41h, 41h,41h,41h,80h ; column 12 db 91h,90h,92h,94h, 49h,49h,0a8h,95h db 44h,4eh,4fh,4fh, 99h,4fh,4fh,58h ; column 13 db 4fh,9dh,55h,9eh, 9ah,59h,3fh,0e1h db 85h,61h,83h,61h, 61h,61h,61h,87h ; column 14 db 8ah,82h,88h,89h, 69h,69h,8ch,8bh db 3fh,6eh,6fh,0a2h, 93h,6fh,6fh,0f6h ; column 15 db 6fh,97h,0a3h,96h, 81h,79h,3fh,79h db 96,'A',0 ; 96 byte set, letter ident ; to CP865 Norway L1cp865 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 20h,0adh,3fh,9ch, 0afh,59h,7ch,15h ; column 10 db 22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,0c4h db 0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah ; column 11 db 2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h db 41h,41h,41h,41h, 8eh,8fh,92h,80h ; column 12 db 45h,90h,45h,45h, 49h,49h,49h,49h db 44h,0a5h,4fh,4fh, 4fh,4fh,99h,58h ; column 13 db 9dh,55h,55h,55h, 9ah,59h,3fh,0e1h db 85h,0a0h,83h,61h, 84h,86h,91h,87h ; column 14 db 8ah,82h,88h,89h, 8dh,0a1h,8ch,8bh db 3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h ; column 15 db 9bh,97h,0a3h,96h, 81h,79h,3fh,98h db 96,'A',0 ; 96 byte set, letter ident ; Latin2 to CP852 L2cp852 db 174,175,176,177,178,179,180,185,186,187,188,191,192,193,194,195 db 196,197,200,201,202,203,204,205,206,217,218,219,220,223,240,254 db 255,164,244,157,207,149,151,245,249,230,184,155,141,170,166,189 db 248,165,242,136,239,150,152,243,247,231,173,156,171,241,167,190 db 232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210 db 209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225 db 234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212 db 208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250 db 96,'B',0 ; 96 byte set, letter ident ; Hebrew-ISO to Code Page 862, GLeft HIcp862 db 158,159,160,161,162,163,164,165,166,167,168,169,173,176,177,178 db 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194 db 255,195,155,156,196,157,197,198,199,200,201,174,170,202,203,204 db 248,241,253,206,207,230,208,249,209,210,246,175,172,171,211,212 db 213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228 db 229,231,232,233,234,235,236,237,238,239,240,242,243,244,245,205 db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 db 144,145,146,147,148,149,150,151,152,153,154,247,250,251,252,254 db 96,'H',0 ; Latin5 to CP866 L5cp866 db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 8 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 9 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 0ffh,0f0h,3fh,3fh, 0f2h,53h,49h,4fh ; column 10 db 4ah,3fh,3fh,48h, 4bh,2dh,0f6h,3fh db 80h,81h,82h,83h, 84h,85h,86h,87h ; column 11 db 88h,89h,8ah,8bh, 8ch,8dh,8eh,8fh db 90h,91h,92h,93h, 94h,95h,96h,97h ; column 12 db 98h,99h,9ah,9bh, 9ch,9dh,9eh,9fh db 0a0h,0a1h,0a2h,0a3h,0a4h,0a5h,0a6h,0a7h ; column 13 db 0a8h,0a9h,0aah,0abh,0ach,0adh,0aeh,0afh db 0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h ; column 14 db 0e8h,0e9h,0eah,0ebh,0ech,0edh,0eeh,0efh db 0fch,0f1h,3fh,3fh, 0f3h,73h,69h,0f5h ; column 15 db 6ah,3fh,3fh,68h, 6bh,15h,0f7h,3fh db 96,'L',0 ; 96 byte set, Latin5/Cyrillic ;yl143[] /* Latin-1 to IBM Code Page 437 */ ; Although the IBM CDRA does not include an official translation between CP437 ; and ISO Latin Alphabet 1,it does include an official,invertible ; translation between CP437 and CP850 (page 196),and another from CP850 to ; Latin-1 (CP819) (page 153). This translation was obtained with a two-step ; process based on those tables. iL1cp437 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197 db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159 db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187 db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147 db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164 db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139 db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180 db 173,177,143,190,20,21,247,184,176,168,183,185,179,178,142,160 db 96,'A',0 ; 96 byte set,letter ident ;yl185[] /* Latin-1 to IBM Code Page 850 */ ; This is IBM's official invertible translation. Reference: IBM Character ; Data Representation Architecture (CDRA),Level 1, Registry, SC09-1291-00 ; (1990), p.152. (Note: Latin-1 is IBM Code Page 00819.) iL1cp850 db 186,205,201,187,200,188,204,185,203,202,206,223,220,219,254,242 db 179,196,218,191,192,217,195,180,194,193,197,176,177,178,213,159 db 255,173,189,156,207,190,221,245,249,184,166,174,170,240,169,238 db 248,241,253,252,239,230,244,250,247,251,167,175,172,171,243,168 db 183,181,182,199,142,143,146,128,212,144,210,211,222,214,215,216 db 209,165,227,224,226,229,153,158,157,235,233,234,154,237,232,225 db 133,160,131,198,132,134,145,135,138,130,136,137,141,161,140,139 db 208,164,149,162,147,228,148,246,155,151,163,150,129,236,231,152 db 96,'A',0 ; 96 byte set, letter ident ; invertable Latin-1 to CP861 iL1cp861 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197 db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159 db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187 db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147 db 148,164,152,150,145,154,227,195,132,130,137,136,134,165,138,164 db 139,208,202,166,200,158,205,206,157,149,167,141,140,151,141,139 db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180 db 140,177,143,190, 20, 21,247,184,155,168,183,185,179,152,149,160 db 96,'A',0 ; 96 byte set, letter ident ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin1 or Latin5 ; For GRight only (high bit set). ; from Code Page 437 cp437L1 db 0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8 db 0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h db 0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9 db 0ffh,0d6h,0dch,0a2h,0a3h,0a5h,3fh,3fh db 0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10 db 0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0bbh db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 3fh,0dfh,4 dup (3fh), 0b5h,3fh ; column 14 db 5 dup(3fh), 0f8h,3fh,3fh db 3fh,0b1h,4 dup (3fh), 0f7h,3fh ; column 15 db 0b0h,0b7h,0b7h,3fh,3fh, 0b2h,3fh,3fh ; from Code Page 850 cp850L1 db 0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8 db 0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h db 0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9 db 0ffh,0d6h,0dch,0f8h,0a3h,0d8h,0d7h,3fh db 0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10 db 0bfh,0aeh,0ach,0bdh,0bch,0a1h,0abh,0bbh db 5 dup (3fh), 0c1h,0c2h,0c0h ; column 11 db 0a9h,4 dup (3fh), 0a2h,0a5h,3fh db 6 dup (3fh),0e3h,0c3h,7 dup (3fh),0a4h ; column 12 db 0f0h,0d0h,0cah,0cbh,0c8h,0b9h,0cdh,0ceh ; column 13 db 0cfh, 4 dup (3fh), 0a6h,0cch,3fh db 0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0feh ; column 14 db 0deh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h db 0adh,0b1h,3dh,0beh, 0b6h,0a7h,0f7h,0b8h ; column 15 db 0b0h,0a8h,0b7h,0b9h, 0b3h,0b2h,3fh,20h ; from Code Page 860 cp860L1 db 0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8 db 0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h db 0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9 db 0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h db 0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10 db 0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14 db 5 dup(3fh), 0f8h,3fh,3fh db 3fh,0b1h, 4 dup (3fh), 0f7h,3fh ; column 15 db 0b0h,0b7h,0b7h,3fh, 3fh,0b2h,3fh,3fh ; from Code Page 861 cp861L1 db 0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8 db 0eah,0ebh,0e8h,0d0h, 0f0h,0deh,0c4h,0c5h db 0c9h,0e6h,0c6h,0f4h, 0f6h,0feh,0fbh,0ddh ; column 9 db 0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh db 0e1h,0edh,0f3h,0fah, 0c1h,0cdh,0d3h,0dah ; column 10 db 0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0bbh db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14 db 5 dup(3fh), 0f8h,3fh,3fh db 3fh,0b1h, 4 dup (3fh), 0f7h,3fh ; column 15 db 0b0h,0b7h,0b7h,3fh,3fh, 0b2h,3fh,3fh ; from Code Page 863 cp863L1 db 0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8 db 0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h db 0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9 db 0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh db 0a6h,0b4h,0f3h,0fah, 0a8h,0b8h,0b3h,0afh ; column 10 db 0ceh,3fh,0ach,0bdh, 0bch,0beh,0abh,0bbh db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14 db 5 dup(3fh), 0f8h,3fh,3fh db 3fh,0b1h, 4 dup (3fh), 0f7h,3fh ; column 15 db 0b0h,0b7h,0b7h,3fh, 3fh,0b2h,3fh,3fh ; from Code Page 865 cp865L1 db 0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8 db 0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h db 0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9 db 0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh db 0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10 db 0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0a4h db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 3fh,0dfh, 4 dup (3fh), 0b5h,3fh ; column 14 db 5 dup(3fh), 0f8h,3fh,3fh db 3fh,0b1h, 4 dup (3fh), 0f7h,3fh ; column 15 db 0b0h,0b7h,0b7h,3fh, 3fh,0b2h,3fh,3fh ; from Code Page 852 to LATIN2 cp852L2 db 199,252,233,226,228,249,230,231,179,235,213,245,238,172,196,198 db 201,197,229,244,246,165,181,166,182,214,220,171,187,163,215,232 db 225,237,243,250,161,177,174,190,202,234,173,188,200,186,128,129 db 130,131,132,133,134,193,194,204,170,135,136,137,138,175,191,139 db 140,141,142,143,144,145,195,227,146,147,148,149,150,151,152,164 db 240,208,207,203,239,210,205,206,236,153,154,155,156,222,217,157 db 211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180 db 158,189,178,183,162,167,247,184,176,168,255,251,216,248,159,160 ; Code Page 862 to Hebrew-ISO cp862HI db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 db 240,241,242,243,244,245,246,247,248,249,250,162,163,165,128,129 db 130,131,132,133,134,135,136,137,138,139,172,189,188,140,171,187 db 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156 db 157,158,159,161,164,166,167,168,169,170,173,174,175,223,179,180 db 182,184,185,190,191,192,193,194,195,196,197,198,199,200,201,202 db 203,204,205,206,207,208,181,209,210,211,212,213,214,215,216,217 db 218,177,219,220,221,222,186,251,176,183,252,253,254,178,255,160 ; from Code Page 866 to LATIN5 cp866L5 db 0b0h,0b1h,0b2h,0b3h, 0b4h,0b5h,0b6h,0b7h ; column 8 db 0b8h,0b9h,0bah,0bbh, 0bch,0bdh,0beh,0bfh db 0c0h,0c1h,0c2h,0c3h, 0c4h,0c5h,0c6h,0c7h ; column 9 db 0c8h,0c9h,0cah,0cbh, 0cch,0cdh,0ceh,0cfh db 0d0h,0d1h,0d2h,0d3h, 0d4h,0d5h,0d6h,0d7h ; column 10 db 0d8h,0d9h,0dah,0dbh, 0dch,0ddh,0deh,0dfh db 16 dup (3fh) ; column 11 db 16 dup (3fh) ; column 12 db 16 dup (3fh) ; column 13 db 0e0h,0e1h,0e2h,0e3h, 0e4h,0e5h,0e6h,0e7h ; column 14 db 0e8h,0e9h,0eah,0ebh, 0ech,0edh,0eeh,0efh db 0a1h,0f1h,0a4h,0f4h, 0a7h,0f7h,0aeh,0feh ; column 15 db 4 dup (3fh), 0f0h,3fh,3fh,0a0h ;y43l1[] /* IBM Code Page 437 to Latin-1 */ ; This table is the inverse of yl143[]. icp437L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197 db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159 db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187 db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147 db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164 db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139 db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180 db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160 ;y85l1[] /* IBM Code Page 850 to Latin-1 */ ; This is from IBM CDRA page 153. It is the inverse of yl185[]. icp850L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197 db 201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,159 db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187 db 155,156,157,144,151,193,194,192,169,135,128,131,133,162,165,147 db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164 db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139 db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180 db 173,177,143,190,182,167,247,184,176,168,183,185,179,178,142,160 ;y86l1[] /* IBM Code Page 861 to Latin-1 */ ; This table is the inverse of yl186[]. icp861L1 db 199,252,233,226,228,224,229,231,234,235,232,208,240,222,196,197 db 201,230,198,244,246,254,251,221,253,214,220,248,163,216,215,159 db 225,237,243,250,193,205,211,218,191,174,172,189,188,161,171,187 db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147 db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164 db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139 db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180 db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160 UNK equ '?' ;Latin/Cyrillic -> CP866 Readable: lccp866r db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216 db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253 db 255,240,132,131,242, 83, 73,244, 74,139,141,151,138, 45,246,135 db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159 db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 db 252,241,164,163,243,115,105,245,106,171,173,231,170,181,247,167 ;Latin/Cyrillic -> CP866 Invertible: lccp866i db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216 db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253 db 255,240,208,207,242,189,183,244,184,212,213,214,210,182,246,209 db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159 db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 db 252,241,221,215,243,199,190,245,198,249,250,251,248,181,247,222 ;KOI8 to CP866 Readable: k8cp866r db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159 db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db 238,160,161,230,164,165,228,163,229,168,169,170,171,172,173,174 db 175,239,224,225,226,227,166,162,236,235,167,232,237,233,231,234 db 158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142 db 143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK ;KOI7 to CP866 Readable: k7cp866r db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 db 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 db 32, 33, 34, 35,253, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 db 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,UNK db 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 db 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 db 158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142 db 143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK ;CP866 Invertible -> Latin/Cyrillic: cp866lci db 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191 db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207 db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223 db 139,140,141,129,136,253,173,166,168,152,145,148,147,165,246,132 db 130,135,137,134,128,138,248,245,146,149,151,153,150,144,154,163 db 162,175,172,142,169,170,171,243,143,131,133,157,156,242,255,155 db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 db 161,241,164,244,167,247,174,254,252,249,250,251,240,159,158,160 ; CP866 to KOI7: cp866koi7 db 97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112 db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113 db 97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112 db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113 db 101,101,UNK,UNK, 73, 73,117,117,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32 ; CP866 to KOI8: cp866koi8 db 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240 db 242,243,244,245,230,232,227,254,251,253,223,249,248,252,224,241 db 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208 db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK db 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209 db 229,197,UNK,UNK, 73,105,245,213,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32 data1 ends ; L/C = ISO Latin/Cyrillic ; CP866R = Readable <-- use this for terminal emulation ; CP866I = Invertible <-- use this for file transfer ; KOI8 = "Old" KOI-8 <-- use this for terminal emulation ; KOI7 = Short KOI <-- use this for terminal emulation ; ;KOI8 and KOI7 are used only as terminal character sets, so they only ;need to be readable. So since we aren't worried about keyboarding, we ;only need five tables: ; ; CP866I -> L/C (for file transfer) ; L/C -> CP866I (for file transfer) ; L/C -> CP866R (terminal emulation) ; KOI8 -> CP866R (terminal emulation) ; KOI7 -> CP866R (terminal emulation) ; ; L/C CP866R CP866I KOI8 KOI7 UNICODE ; 0 0 0 0 0 0x0000 ; 1 1 1 1 1 0x0001 ; 2 2 2 2 2 0x0002 ; 3 3 3 3 3 0x0003 ; 4 4 4 4 4 0x0004 ; 5 5 5 5 5 0x0005 ; 6 6 6 6 6 0x0006 ; 7 7 7 7 7 0x0007 ; 8 8 8 8 8 0x0008 ; 9 9 9 9 9 0x0009 ; 10 10 10 10 10 0x000A ; 11 11 11 11 11 0x000B ; 12 12 12 12 12 0x000C ; 13 13 13 13 13 0x000D ; 14 14 14 14 14 0x000E ; 15 15 15 15 15 0x000F ; 16 16 16 16 16 0x0010 ; 17 17 17 17 17 0x0011 ; 18 18 18 18 18 0x0012 ; 19 19 19 19 19 0x0013 ; 20 20 20 20 20 0x0014 ; 21 21 21 21 21 0x0015 ; 22 22 22 22 22 0x0016 ; 23 23 23 23 23 0x0017 ; 24 24 24 24 24 0x0018 ; 25 25 25 25 25 0x0019 ; 26 26 26 26 26 0x001A ; 27 27 27 27 27 0x001B ; 28 28 28 28 28 0x001C ; 29 29 29 29 29 0x001D ; 30 30 30 30 30 0x001E ; 31 31 31 31 31 0x001F ; 32 32 32 32 32 0x0020 SPACE ; 33 33 33 33 33 0x0021 EXCLAMATION MARK ; 34 34 34 34 34 0x0022 QUOTATION MARK ; 35 35 35 35 35 0x0023 NUMBER SIGN ; 36 36 36 36 36 0x0024 DOLLAR SIGN ; 37 37 37 37 37 0x0025 PERCENT SIGN ; 38 38 38 38 38 0x0026 AMPERSAND ; 39 39 39 39 39 0x0027 APOSTROPHE ; 40 40 40 40 40 0x0028 LEFT PARENTHESIS ; 41 41 41 41 41 0x0029 RIGHT PARENTHESIS ; 42 42 42 42 42 0x002A ASTERISK ; 43 43 43 43 43 0x002B PLUS SIGN ; 44 44 44 44 44 0x002C COMMA ; 45 45 45 45 45 0x002D HYPHEN, MINUS SIGN ; 46 46 46 46 46 0x002E PERIOD, FULL STOP ; 47 47 47 47 47 0x002F SOLIDUS, SLASH ; 48 48 48 48 48 0x0030 DIGIT ZERO ; 49 49 49 49 49 0x0031 DIGIT ONE ; 50 50 50 50 50 0x0032 DIGIT TWO ; 51 51 51 51 51 0x0033 DIGIT THREE ; 52 52 52 52 52 0x0034 DIGIT FOUR ; 53 53 53 53 53 0x0035 DIGIT FIVE ; 54 54 54 54 54 0x0036 DIGIT SIX ; 55 55 55 55 55 0x0037 DIGIT SEVEN ; 56 56 56 56 56 0x0038 DIGIT EIGHT ; 57 57 57 57 57 0x0039 DIGIT NINE ; 58 58 58 58 58 0x003A COLON ; 59 59 59 59 59 0x003B SEMICOLON ; 60 60 60 60 60 0x003C LEFT ANGLE BRACKET ; 61 61 61 61 61 0x003D EQUALS SIGN ; 62 62 62 62 62 0x003E RIGHT ANGLE BRACKET ; 63 63 63 63 63 0x003F QUESTION MARK ; 64 64 64 64 64 0x0040 COMMERCIAL AT SIGN ; 65 65 65 65 65 0x0041 CAPITAL LETTER A ; 66 66 66 66 66 0x0042 CAPITAL LETTER B ; 67 67 67 67 67 0x0043 CAPITAL LETTER C ; 68 68 68 68 68 0x0044 CAPITAL LETTER D ; 69 69 69 69 69 0x0045 CAPITAL LETTER E ; 70 70 70 70 70 0x0046 CAPITAL LETTER F ; 71 71 71 71 71 0x0047 CAPITAL LETTER G ; 72 72 72 72 72 0x0048 CAPITAL LETTER H ; 73 73 73 73 73 0x0049 CAPITAL LETTER I ; 74 74 74 74 74 0x004A CAPITAL LETTER J ; 75 75 75 75 75 0x004B CAPITAL LETTER K ; 76 76 76 76 76 0x004C CAPITAL LETTER L ; 77 77 77 77 77 0x004D CAPITAL LETTER M ; 78 78 78 78 78 0x004E CAPITAL LETTER N ; 79 79 79 79 79 0x004F CAPITAL LETTER O ; 80 80 80 80 80 0x0050 CAPITAL LETTER P ; 81 81 81 81 81 0x0051 CAPITAL LETTER Q ; 82 82 82 82 82 0x0052 CAPITAL LETTER R ; 83 83 83 83 83 0x0053 CAPITAL LETTER S ; 84 84 84 84 84 0x0054 CAPITAL LETTER T ; 85 85 85 85 85 0x0055 CAPITAL LETTER U ; 86 86 86 86 86 0x0056 CAPITAL LETTER V ; 87 87 87 87 87 0x0057 CAPITAL LETTER W ; 88 88 88 88 88 0x0058 CAPITAL LETTER X ; 89 89 89 89 89 0x0059 CAPITAL LETTER Y ; 90 90 90 90 90 0x005A CAPITAL LETTER Z ; 91 91 91 91 91 0x005B LEFT SQUARE BRACKET ; 92 92 92 92 92 0x005C REVERSE SOLIDUS, BACKSLASH ; 93 93 93 93 93 0x005D RIGHT SQUARE BRACKET ; 94 94 94 94 94 0x005E CIRCUMFLEX ACCENT ; 95 95 95 95 95 0x005F LOW LINE, UNDERLINE ; 96 96 96 96 64 0x0060 GRAVE ACCENT ; 97 97 97 97 65 0x0061 SMALL LETTER a ; 98 98 98 98 66 0x0062 SMALL LETTER b ; 99 99 99 99 67 0x0063 SMALL LETTER c ;100 100 100 100 68 0x0064 SMALL LETTER d ;101 101 101 101 69 0x0065 SMALL LETTER e ;102 102 102 102 70 0x0066 SMALL LETTER f ;103 103 103 103 71 0x0067 SMALL LETTER g ;104 104 104 104 72 0x0068 SMALL LETTER h ;105 105 105 105 73 0x0069 SMALL LETTER i ;106 106 106 106 74 0x006A SMALL LETTER j ;107 107 107 107 75 0x006B SMALL LETTER k ;108 108 108 108 76 0x006C SMALL LETTER l ;109 109 109 109 77 0x006D SMALL LETTER m ;110 110 110 110 78 0x006E SMALL LETTER n ;111 111 111 111 79 0x006F SMALL LETTER o ;112 112 112 112 80 0x0070 SMALL LETTER p ;113 113 113 113 81 0x0071 SMALL LETTER q ;114 114 114 114 82 0x0072 SMALL LETTER r ;115 115 115 115 83 0x0073 SMALL LETTER s ;116 116 116 116 84 0x0074 SMALL LETTER t ;117 117 117 117 85 0x0075 SMALL LETTER u ;118 118 118 118 86 0x0076 SMALL LETTER v ;119 119 119 119 87 0x0077 SMALL LETTER w ;120 120 120 120 88 0x0078 SMALL LETTER x ;121 121 121 121 89 0x0079 SMALL LETTER y ;122 122 122 122 90 0x007A SMALL LETTER z ;123 123 123 123 91 0x007B LEFT BRACE ;124 124 124 124 92 0x007C VERTICAL BAR ;125 125 125 125 93 0x007D RIGHT BRACE ;126 126 126 126 94 0x007E TILDE ;127 127 127 127 127 0x00A0 RUBOUT, DELETE ;128 196 196 128 0 ;129 179 179 129 1 ;130 192 192 130 2 ;131 217 217 131 3 ;132 191 191 132 4 ;133 218 218 133 5 ;134 195 195 134 6 ;135 193 193 135 7 ;136 180 180 136 8 ;137 194 194 137 9 ;138 197 197 138 10 ;139 176 176 139 11 ;140 177 177 140 12 ;141 178 178 141 13 ;142 211 211 142 14 ;143 216 216 143 15 ;144 205 205 144 16 ;145 186 186 145 17 ;146 200 200 146 18 ;147 188 188 147 19 ;148 187 187 148 20 ;149 201 201 149 21 ;150 204 204 150 22 ;151 202 202 151 23 ;152 185 185 152 24 ;153 203 203 153 25 ;154 206 206 154 26 ;155 223 223 155 27 ;156 220 220 156 28 ;157 219 219 157 29 ;158 254 254 158 30 ;159 253 253 159 31 ;160 255 255 UNK 32 0x0401 No-break space ;161 240 240 229 101 0x0402 Cyrillic Io ;162 132 208 UNK UNK 0x0403 Serbocroation Dje ;163 131 207 UNK UNK 0x0404 Macedonian Gje ;164 242 242 UNK UNK 0x0405 Ukranian Ie ;165 83 189 83 83 0x0406 Macedonian Dze ;166 73 183 73 73 0x0407 Cyrillic I ;167 244 244 73 73 0x0408 Ukranian Yi ;168 74 184 74 74 0x0409 Cyrillic Je ;169 139 212 UNK UNK 0x040A Cyrillic Lje ;170 141 213 UNK UNK 0x040B Cyrillic Nje ;171 151 214 UNK UNK 0x040C Serbocroation Chje ;172 138 210 235 107 0x00AD Macedonian Kje ;173 45 182 UNK 45 0x040E Soft hyphen ;174 246 246 245 117 0x040F Bielorussian Short U ;175 135 209 UNK UNK 0x0410 Cyrillic Dze ;176 128 128 225 97 0x0411 Cyrillic A ;177 129 129 226 98 0x0412 Cyrillic Be ;178 130 130 247 119 0x0413 Cyrillic Ve ;179 131 131 231 103 0x0414 Cyrillic Ghe ;180 132 132 228 100 0x0415 Cyrillic De ;181 133 133 229 101 0x0416 Cyrillic Ie ;182 134 134 246 118 0x0417 Cyrillic Zhe ;183 135 135 250 122 0x0418 Cyrillic Ze ;184 136 136 233 105 0x0419 Cyrillic I ;185 137 137 234 106 0x041A Cyrillic Short I ;186 138 138 235 107 0x041B Cyrillic Ka ;187 139 139 236 108 0x041C Cyrillic El ;188 140 140 237 109 0x041D Cyrillic Em ;189 141 141 238 110 0x041E Cyrillic En ;190 142 142 239 111 0x041F Cyrillic O ;191 143 143 240 112 0x0420 Cyrillic Pe ;192 144 144 242 114 0x0421 Cyrillic Er ;193 145 145 243 115 0x0422 Cyrillic Es ;194 146 146 244 116 0x0423 Cyrillic Te ;195 147 147 245 117 0x0424 Cyrillic U ;196 148 148 230 102 0x0425 Cyrillic Ef ;197 149 149 232 104 0x0426 Cyrillic Ha ;198 150 150 227 99 0x0427 Cyrillic Tse ;199 151 151 254 126 0x0428 Cyrillic Che ;200 152 152 251 123 0x0429 Cyrillic Sha ;201 153 153 253 125 0x042A Cyrillic Shcha ;202 154 154 255 39 0x042B Cyrillic Hard Sign ;203 155 155 249 121 0x042C Cyrillic Yeri ;204 156 156 248 120 0x042D Cyrillic Soft Sign ;205 157 157 252 124 0x042E Cyrillic E ;206 158 158 224 96 0x042F Cyrillic Yu ;207 159 159 241 113 0x0430 Cyrillic Ya ;208 160 160 193 97 0x0431 Cyrillic a ;209 161 161 194 98 0x0432 Cyrillic be ;210 162 162 215 119 0x0433 Cyrillic ve ;211 163 163 199 103 0x0434 Cyrillic ghe ;212 164 164 196 100 0x0435 Cyrillic de ;213 165 165 197 101 0x0436 Cyrillic ie ;214 166 166 214 118 0x0437 Cyrillic zhe ;215 167 167 218 122 0x0438 Cyrillic ze ;216 168 168 201 105 0x0439 Cyrillic i ;217 169 169 202 106 0x043A Cyrillic Short i ;218 170 170 203 107 0x043B Cyrillic ka ;219 171 171 204 108 0x043C Cyrillic el ;220 172 172 205 109 0x043D Cyrillic em ;221 173 173 206 110 0x043E Cyrillic en ;222 174 174 207 111 0x043F Cyrillic o ;223 175 175 208 112 0x0440 Cyrillic pe ;224 224 224 210 114 0x0441 Cyrillic er ;225 225 225 211 115 0x0442 Cyrillic es ;226 226 226 212 116 0x0443 Cyrillic te ;227 227 227 213 117 0x0444 Cyrillic u ;228 228 228 198 102 0x0445 Cyrillic ef ;229 229 229 200 104 0x0446 Cyrillic ha ;230 230 230 195 99 0x0447 Cyrillic tse ;231 231 231 222 126 0x0448 Cyrillic che ;232 232 232 219 123 0x0449 Cyrillic sha ;233 233 233 221 125 0x044A Cyrillic shcha ;234 234 234 223 39 0x044B Cyrillic hard sign ;235 235 235 217 121 0x044C Cyrillic yeri ;236 236 236 216 120 0x044D Cyrillic soft sign ;237 237 237 220 124 0x044E Cyrillic e ;238 238 238 192 96 0x044F Cyrillic yu ;239 239 239 209 113 0x2116 Cyrillic ya ;240 252 252 UNK UNK 0x0451 Number Acronym ;241 241 241 197 10 0x0452 Cyrillic io ;242 164 221 UNK UNK 0x0453 Serbocroation dje ;243 163 215 UNK UNK 0x0454 Macedonian gje ;244 243 243 UNK UNK 0x0455 Ukranian ie ;245 115 199 115 83 0x0456 Macedonian dze ;246 105 190 105 73 0x0457 Cyrillic i ;247 245 245 105 73 0x0458 Ukranian yi ;248 106 198 106 74 0x0459 Cyrillic je ;249 171 249 UNK UNK 0x045A Cyrillic lje ;250 173 250 UNK UNK 0x045B Cyrillic nje ;251 231 251 UNK UNK 0x045C Serbocroatian chje ;252 170 248 203 107 0x00A7 Macedonian kje ;253 181 181 UNK UNK 0x045E Paragraph sign ;254 247 247 213 117 0x045F Bielorussian short u ;255 167 222 UNK UNK Cyrillic dze code1 segment extrn isfile:far,decout:far assume cs:code1 code1 ends code segment extrn newfn:near,comnd:near extrn ermsg:near,clrfln:far,frpos:near,kbpr:near,perpr:near assume cs:code,ds:data,es:nothing ; Set DS:BX to the ISO Latin-1 table appropriate to the ; currently active Code Page. Defaults to CP437 if no CP found. LATIN1 proc near push ax mov ax,seg flags mov DS,ax mov ax,flags.chrset ; in segment data mov bx,seg L1cp437 mov DS,bx ; set returned DS to table mov bx,offset L1cp437 ; assume CP437 cmp ax,437 ; current Code Page is 437? je latin1x ; e = yes mov bx,offset L1cp850 ; assume CP850 cmp ax,850 ; current Code Page is 850? je latin1x ; e = yes mov bx,offset L1cp860 ; assume CP860 cmp ax,860 ; current Code Page is 860? je latin1x ; e = yes mov bx,offset L1cp861 ; assume CP861 cmp ax,861 ; current Code Page is 861? je latin1x ; e = yes mov bx,offset L2cp852 ; assume CP852 cmp ax,852 ; current Code Page is 852? je latin1x ; e = yes mov bx,offset HIcp862 ; assume CP862 cmp ax,862 ; current Code Page is 862? je latin1x ; e = yes mov bx,offset L1cp863 ; assume CP863 cmp ax,863 ; current Code Page is 863? je latin1x ; e = yes mov bx,offset L1cp865 ; assume CP865 cmp ax,865 ; current Code Page is 865? je latin1x ; e = yes mov bx,offset L5cp866 ; assume CP866 cmp ax,866 ; current Code Page is 866? je latin1x ; e = yes mov bx,offset L1cp437 ; default to CP437 latin1x:pop ax ret LATIN1 endp ; Call after LATIN1. Revise DS:BX to point to invertible tables rather than ; readable translation tables. Does not change DS. latininv proc near push ax push ds mov ax,seg trans mov ds,ax cmp trans.xchri,0 ; readable (vs invertible)? pop ds pop ax je latinvx ; e = yes, do nothing cmp bx,offset L1cp437 ; this table in use? jne latinv1 ; ne = no mov bx,offset iL1cp437 ; use invertible instead jmp short latinvx latinv1:cmp bx,offset L1cp850 ; this table in use? jne latinv2 ; ne = no mov bx,offset iL1cp850 ; use invertible instead jmp short latinvx latinv2:cmp bx,offset L1cp861 ; this table? jne latinvx ; ne = no mov bx,offset iL1cp861 ; use invertible instead latinvx:ret latininv endp ; Set DS:BX to the table for Code Page to ISO 8859-1 Latin1/Latin5 cplatin proc near push ax mov ax,seg flags mov DS,ax mov ax,flags.chrset mov bx,seg cp437L1 mov DS,bx ; set returned DS to table mov bx,offset cp437L1 ; assume CP437 cmp ax,437 ; current Code Page is 437? je cplatx ; e = yes mov bx,offset cp850L1 ; assume CP850 cmp ax,850 ; current Code Page is 850? je cplatx ; e = yes mov bx,offset cp860L1 ; assume CP860 cmp ax,860 ; current Code Page is 860? je cplatx ; e = yes mov bx,offset cp861L1 ; assume CP861 cmp ax,861 ; current Code Page is 861? je cplatx ; e = yes mov bx,offset cp852L2 ; assume CP852 cmp ax,852 ; current Code Page is 852? je cplatx ; e = yes mov bx,offset cp862HI ; assume CP862 cmp ax,862 ; current Code Page is 862? je cplatx ; e = yes mov bx,offset cp863L1 ; assume CP863 cmp ax,863 ; current Code Page is 863? je cplatx ; e = yes mov bx,offset cp865L1 ; assume CP865 cmp ax,865 ; current Code Page is 865? je cplatx ; e = yes mov bx,offset cp866L5 ; assume CP866 for LATIN5 cmp ax,866 ; corrent Code Page is 866? je cplatx ; e = yes mov bx,offset cp437L1 ; default to CP437 cplatx: pop ax ret cplatin endp ; Call after CPLATIN. Revise DS:BX to point to invertible tables rather than ; readable translation tables. cpinvert proc near push ds push ax mov ax,seg trans mov ds,ax cmp trans.xchri,0 ; readable (vs invertible)? pop ax pop ds je cpinverx ; e = yes, do nothing cmp bx,offset cp437L1 ; this table in use? jne cpinver1 ; ne = no mov bx,offset icp437L1 ; use invertible instead ret cpinver1:cmp bx,offset cp850L1 ; this table in use? jne cpinver2 ; ne = no mov bx,offset icp850L1 ; use invertible instead ret cpinver2:cmp bx,offset cp861L1 ; this table in use? jne cpinverx ; ne = no mov bx,offset icp861L1 ; use invertible instead cpinverx:ret cpinvert endp ; Output the chars in a packet, called only by receiver code. ; Enter with SI equal to pktinfo structure pointer. PTCHR: mov decoutp,offset outbuf ; routine to call when buffer gets full jmp short decode ; Dodecoding. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ??? ; Modifies regs BX, CX. ; Enter with SI equal to pktinfo structure pointer. dodec proc near push ax ; save reg mov ah,dblbyteflg ; preserve state mov al,dblbyte push ax mov al,shiftstate mov ah,DLEseen push ax mov dblbyteflg,0 ; init decode as doubles mov shiftstate,0 ; init shift states mov DLEseen,0 ; init escape mov decoutp,offset dnulr ; routine to dump buffer (null) call decode pop ax mov shiftstate,al ; restore decoder state mov DLEseen,ah pop ax mov dblbyteflg,ah mov dblbyte,al push bx mov bx,dbufpnt ; next char position mov byte ptr [bx],0 ; null terminator pop bx pop ax ret dodec endp dnulr: mov dbufpnt,di ; point off end of buffer stc ; fail if needs this ret ; dummy buffer emptier ; Enter with [si].datlen = length of data, [si].datadr = dw address of data, ; DECOUTP = pointer to routine which writes output buffer ; Returns DBUFPNT = pointer to output buffer address (offset part). ; Trans.lshift is non-zero if locking shift encoding is active. ; DLEseen is non-zero if a DLE char (Control-P) is decoded while locking shift ; is active; under these circumstances DLE escapes DLE, SI, and SO to be ; data characters. Under locking shift rules SO (Control-N) shifts high bit ; data to non-high bit data (and we thus reverse this); SI (Control-O) ; cancels SO. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while ; performing Japanese translation; dblbyte is the first byte of the pair. ; All packets are decoded except I, S, and A types. ; Flushes output buffer before returning. ; Returns carry clear if success, otherwise carry set decode proc near push si push di push es push dx push ds pop es cld ; forward direction mov dchrcnt,decbuflen ; size of output buffer mov dbufpnt,offset decbuf ; decoded data placed here pending output mov decbuf,0 ; nothing written yet mov cx,[si].datlen ; length of source buffer data les si,[si].datadr ; source buffer address to es:[si] mov di,dbufpnt ; destination of data mov bl,trans.squote ; regular quote char xor dh,dh ; assume no quote char cmp trans.ebquot,'N' ; any 8-bit quoting? je decod1 ; e = no quoting cmp trans.ebquot,'Y' ; or not doing it? je decod1 ; e = no need to quote mov dh,trans.ebquot ; otherwise use 8-bit quote char decod1: mov rptct,1 ; reset repeat count or cx,cx ; any more chars in source? jg decod2 ; g = yes jmp decod6 ; else, we're through decod2: mov al,es:[si] ; pick up a char inc si dec cx ; count number left cmp al,trans.rptq ; repeat quote char? jne dcod2a ; ne = no, continue processing it mov al,es:[si] ; get the size inc si dec cx ; modify buffer count sub al,20H ; make count numeric mov rptct,al ; remember how many repetitions mov al,es:[si] ; get the char to repeat inc si dec cx ; modify buffer count dcod2a: xor ah,ah ; assume no 8-bit quote char cmp al,dh ; is this the 8-bit quot char? jne decod3 ; ne = no mov al,es:[si] ; yes, get the real character inc si dec cx ; decrement # chars in packet mov ah,80H ; turn on high bit decod3: cmp al,bl ; quote char? jne decod4 ; ne = no, proceed mov al,es:[si] ; get the quoted character inc si dec cx ; decrement # of chars in packet or ah,al ; save parity (combine with prefix) and ax,807fh ; only parity in ah, remove it in al cmp al,bl ; quote char? je decod4 ; e = yes, just go write it out cmp al,dh ; 8-bit quote char? je decod4 ; e = yes, just go write it out cmp trans.rptq,0 ; disabled repeat quoting? je decod3a ; e = yes, disabled cmp al,trans.rptq ; repeat quote character? je decod4 ; e = yes, just write it out decod3a:cmp al,3fh ; char less than '?' ? jb decod4 ; b = yes; leave it intact cmp al,5fh ; char greater than '_' ? ja decod4 ; a = yes; leave it alone add al,40H ; make it a control char again and al,7FH ; modulo 128 (includes DEL) decod4: xor ah,shiftstate ; modify high bit by shiftstate or al,ah ; or in parity cmp trans.lshift,lock_disable ; locking shift disabled? je decod5 ; e = yes mov ah,al xor ah,shiftstate ; adjust high bit by shift state cmp ah,DLE ; DLE? jne dcod4c ; ne = no cmp DLEseen,0 ; has DLE been escaped (by DLE)? je dcod4b ; e = no, make this the escape mov DLEseen,0 ; unescape now jmp short decod5 ; process the literal DLE ; handle repeat counted DLE's dcod4b: shr rptct,1 ; divide by two, carry has lsb rcl DLEseen,1 ; pickup carry bit if odd number jmp short decod5 ; write the DLE's dcod4c: cmp DLEseen,0 ; DLE prefix seen? mov DLEseen,0 ; clear it now too jne decod5 ; ne = yes, prefixed, do literal cmp ah,SIchar ; SI? jne dcod4d ; ne = no mov shiftstate,0 ; say exiting shifted state jmp decod1 ; nothing to write dcod4d: cmp ah,SOchar ; SO? jne decod5 ; ne = no mov shiftstate,80h ; say entering shifted state jmp decod1 ; nothing to write decod5: push cx mov cl,rptct ; repeat count xor ch,ch or cl,cl jle decod5c ; le = nothing to do (94 max) cmp cx,dchrcnt ; needed vs space available jbe decod5a ; be = enough space for rptct chars mov cx,dchrcnt ; insufficient space, do dchrcnt decod5a:sub rptct,cl ; reduce number left to be written sub dchrcnt,cx ; reduce output free space pushf ; save sub status flags shr cx,1 jnc decod5b ; nc = an even number mov [di],al ; store the odd byte inc di jcxz decod5d ; z = nothing else to write decod5b:mov ah,al ; make a copy for word writes push bx ; source is es:[si], dest is ds:[di] push es ; save and swap ds and es push ds mov bx,es pop es ; old ds to es push ds ; restore mov ds,bx ; old es to ds rep stosw ; store cx words pop ds pop es pop bx decod5d:popf ; recover flags from sub dchrcnt,cx jg decod5c ; g = space remaining in output buffer push dx ; flush output buffer push bx push ax ; save the char push es call decoutp ; output the buffer pop es pop ax ; recover repeated char pop bx pop dx jc decod7 ; c = error if disk is full mov di,dbufpnt pop cx jmp short decod5 ; see if more chars need be written decod5c:pop cx ; recover main loop counter jmp decod1 ; get next source character decod6: mov dbufpnt,di ; flush buffer before exiting decode push cx push es call decoutp ; flush output buffer before final ret pop es decod7: pop cx pop dx pop es pop di pop si ret ; return successfully if carry clear decode endp outbuf proc near ; output decbuf, reset bufpnt & chrcnt mov cx,decbuflen ; get full size of buffer sub cx,dchrcnt ; minus space remaining = # to write jg outbu2 ; g = something to do jmp outbf1 outbu2: mov dx,offset decbuf ; address of buffer cmp trans.xtype,1 ; File Type Binary? je outbu5 ; e = yes, no translation cmp flags.destflg,dest_disk ; disk destination? je outbu5 ; e = yes, DOS will do it cmp flags.eofcz,0 ; end on Control-Z? je outbu5 ; e = no push cx ; else map Control-Z to space push di mov di,seg decbuf mov es,di ; data to es mov di,dx ; scan buffer es:di, cx chars worth mov al,ctlz ; look for Control-Z cld outbu3: repne scasb jne outbu4 ; ne = found no Control-Z's mov byte ptr [di-1],' ' ; replace Control-Z with space jcxz outbu4 ; z = examined all chars jmp short outbu3 ; until examined everything outbu4: pop di pop cx ; Character set translation section outbu5: cmp trans.xtype,1 ; File Type Binary? je outbu7 ; e = yes, no translation cmp trans.xchset,xfr_xparent ; Transfer Transparent? je outbu7 ; e = yes, no translation cmp trans.xchset,xfr_japanese ; Japanese-EUC? jne outbu5a ; ne = no call jpnwrite ; do special decoding jmp outbu7 outbu5a:push cx push di push es PUSH DS call latin1 ; set DS:BX to xfr char set to CP table call latininv ; select invertable or readable set mov di,seg decbuf mov es,di mov di,offset decbuf ; scan this buffer cld outbu6: mov al,es:[di] ; get a char, keep pointer fixed test al,80h ; GRight? jnz outbu6a ; nz = yes cmp bx,offset iL1cp437 ; using invertable Latin1 to CP437? jne outbu6c ; ne = no cmp ah,127 ; 127 goes to 28? jne outbu6e ; ne = no mov al,28 ; 127 to 28 jmp short outbu6b outbu6e:cmp al,21 ; special case? ja outbu6b ; a = no cmp al,20 ; special case? jb outbu6b ; b = no mov ah,al mov al,244 ; 20 to 244 cmp ah,21 ; special case? jne outbu6b ; ne = no mov al,245 ; preset one answer je outbu6b ; e = yes, 21 to 245 mov al,244 ; 22 to 244 jmp short outbu6b outbu6c:cmp bx,offset iL1cp850 ; using invertible Latin1 to CP850? jne outbu6b ; ne = no cmp al,26 ; special case? jne outbu6d ; ne = no mov al,127 ; 26 to 127 jmp outbu6b outbu6d:cmp al,127 ; special case? jne outbu6b ; ne = no mov al,28 ; 127 to 28 jmp short outbu6b outbu6a:and al,not 80h ; strip high bit xlatb ; translate via bx table outbu6b:stosb ; store char loop outbu6 ; do all concerned POP DS pop es pop di pop cx outbu7: push bx mov bx,diskio.handle ; file handle or bx,bx jle outbf0 ; le = illegal handle, fail mov ah,write2 ; write cx bytes int dos pop bx jc outbf0 ; c set means writing error cmp ax,cx ; did we write all the bytes? je outbf1 ; e = yes push bx mov bx,offset decbuf add bx,ax ; look at break character cmp byte ptr [bx],ctlz ; ended on Control-Z? pop bx je outbf1 ; e = yes, say no error outbf0: mov dx,offset erms13 ; Error writing device cmp flags.xflg,0 ; writing to screen? jne outbf0a ; ne = yes cmp flags.destflg,dest_printer ; writing to printer? jne outbf0a ; ne = no mov dx,offset ermes9 ; Printer not ready message outbf0a:call ermsg stc ; return failure ret outbf1: add tfilsz,cx ; count received chars adc tfilsz+2,0 add fsta.frbyte,cx adc fsta.frbyte+2,0 test flags.remflg,dserial ; serial mode display? jnz outb11 ; nz = yes, skip kbyte and % displays cmp flags.xflg,0 ; receiving to screen? jne outb11 ; ne = yes call kbpr ; display kilobytes done call perpr ; display percentage done outb11: mov dbufpnt,offset decbuf ; address for beginning mov dchrcnt,decbuflen ; size of empty buffer clc ; return success ret outbuf endp ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp) ; Reread buffer decbuf to convert from transfer character set ; Japanese-EUC into Shift-JIS (Code Page 932). Double char translation state ; is maintained across file buffers. Init dblbyte to 0 before each new file. ; Returns registers ; cx number of bytes written in the buffer ; dx address of the output buffer ; this points decbuf or decbuf-1, depending on dblbyteflg ; Output is otherwise written over the input. [rewritten by jrd] jpnwrite proc near ; [HF] write Japanese to file push si ; decbuf is read/written push di ; cx has incoming/outgoing byte count push bx ; dblbyte has earlier first byte push es ; dblbyteflg is state from prev call mov dx,ds mov es,dx cld ; restore state from previous call mov dl,dblbyteflg ; state, non-zero if doing second byte mov ah,dblbyte ; and first byte from previous read mov si,offset decbuf ; read/write this buffer mov di,si ; set the address for write mov bx,si ; save for computing output buf length or dl,dl ; carry-in of a double byte char? jz jpnwri1 ; z = no dec di ; start output one byte before decbuf dec bx ; adjust the start address jpnwri1:lodsb ; get a byte or dl,dl ; processing 2nd byte of a pair? jnz jpnwri3 ; nz = yes, do second byte processor ; first byte processor cmp al,80h ; 8th bit on? jb jpnwri5 ; b = no, this is a single char cmp al,8eh ; JIS X 0201 Katakana prefix? je jpnwri2 ; e = yes, is first of two chars cmp al,0a1h ; JIS X 0208 Kanji ? jb jpnwri5 ; b = no, is single char cmp al,0feh ja jpnwri5 ; a = no, is single char jpnwri2:mov ah,al ; save first of two chars mov dl,1 ; say need second char of pair jmp short jpnwri6 ; read second byte ; process second char of two byte pair jpnwri3:cmp ah,8eh ; was first char JIS X 0201 Katakana? jne jpnwri4 ; ne = no or al,80h ; make sure 8th bit is on jmp short jpnwri5 ; write one char jpnwri4:call jpnxtof ; xfer -> file char code conversion xchg ah,al stosb ; write first byte xchg ah,al ; and second byte jpnwri5:stosb ; write a char xor dl,dl ; clear multi-byte counter jpnwri6:loop jpnwri1 mov dblbyteflg,dl ; save state info mov dblbyte,ah ; and the first byte of a pair sub di,bx ; find number of chars written mov cx,di ; return new count in CX mov dx,bx ; return new buffer address for write pop es ; can be decbuf - 1 if carry-in of dbl pop bx pop di pop si clc ret jpnwrite endp ; Transfer character code (EUC) to file character code (Shift-JIS) converter. ; input AH: 1st byte of EUC code ; AL: 2nd byte of EUC code ; output AH: 1st byte of Shift-JIS code ; AL: 2nd byte of Shift-JIS code ; From EUC to Shift-JIS ; code1 = (EUC_code1 & 0x7f); ; code2 = (EUC_code2 & 0x7f); ; if( code1 & 1) ; code2 += 0x1f; ; else ; code2 += 0x7d; ; if( code2 >= 0x7f ) code2++; ; code1 = ((code1 - 0x21) >> 1) + 0x81; ; if( code1 > 0x9f ) code1 += 0x40; ; [ fputc( code1, file ); fputc( code2, file ); ] ; jpnxtof proc near and ax,7f7fh ; mask both 8-th bits test ah,1 jz jpnxtof1 add al,1fh jmp short jpnxtof2 jpnxtof1:add al,7dh jpnxtof2:cmp al,7fh jb jpnxtof3 inc al jpnxtof3:sub ah,21h shr ah,1 add ah,81h cmp ah,9fh jbe jpnxtof4 add ah,40h jpnxtof4:ret jpnxtof endp ; Get chars from file, encode them to pktinfo structure pointed to by si gtchr: mov [si].datlen,0 ; say no output data yet cmp filflg,0 ; is there anything in the buffer? jne gtchr0 ; ne = yes, use that material first call inbuf ; do initial read from source jc gtchr1 ; c = no more chars, go return EOF gtchr0: mov encinp,offset inbuf ; buffer refiller routine jmp short encode gtchr1: mov [si].datlen,0 ; report EOF mov flags.eoflag,1 ; say eof stc ; return failure ret ; Kermit encoding rules: ; Prefix codes per se are sent as ; C0 and C1 control codes are prefixed by ; 8th bit set prefixing is <8th bit prefix, &> ; where composite byte is ; Run length encoding is ; where composite byte is <8th bit prefix> ; So far the maximum transmitted size of any raw byte is three bytes, ; and a run of them is six bytes. ; ; Locking shifts, applies only if locking shifts have been negotiated. ; Data whose lower seven bits are DLE, SI, SO data are sent as other C0/C1 ; codes, but they are preceeded by DLE. Such pairs of control codes are ; subject to control code prefixing (#) and 8th bit prefixing (&); runs ; of them are preceeded by the byte pair. ; Control SO locks on implication of 8th bit set on all following data, ; and that data is sent without the 8th bit set. ; Control SI unlocks SO shift. ; DLE, SI, and SO shift controls are sent as bare control codes, unencoded. ; A single shift operation is used when appropriate to change the state ; of implied 8th bit value (set or reset). The 8th bit prefix character ; is used as a prefix to denote: change the 8th bit from the current state ; to the opposite value for the following data byte only. ; ;The Control Prefix ; For transparency on serial communication links that are sensitive to ; control characters, the file sender precedes each C0 and C1 control with ; the control prefix, normally "#" (ASCII 35), and then encodes the control ; character itself by "exclusive-ORing" it with 64 decimal (i.e. inverting ; bit 6) to produce a character in the printable ASCII range. For example, ; Control-C (ASCII 3) becomes "#C" (3 XOR 64 = 67, which is the ASCII code ; for the letter C). Similarly, NUL becomes "#@", Control-A becomes "#A", ; Control-Z becomes "#Z", Escape becomes "#[", and DEL becomes "#?". The ; receiver decodes by discarding the prefix and XORing the character with ; 64 again. For example, in "#C", C = ASCII 67, and 67 XOR 64 = 3 = ; Control-C. Control prefixing is mandatory. The control prefix is also ; used for quoting prefix characters that occur in the data itself; see ; "The Prefix Quote" below. ; ;The 8th-bit Prefix ; When one or both of the two Kermit programs knows that the connection ; between them is not transparent to the 8th bit (e.g. because the Kermit ; PARITY variable is not NONE, or because the program always operates that ; way), a feature called "8th-bit prefixing" is used if the two Kermit ; programs negotiate an agreement to do so. The 8th-bit prefix is Kermit's ; single shift, normally the ampersand character "&" (ASCII 38). When the ; file sender encounters an 8-bit character, it inserts the "&" prefix in ; front of it, and then inserts the data character itself with its 8th bit ; set to 0. If the data character is a control character, it is inserted ; after the 8th-bit prefix in control-prefixed form. Examples: an "A" with ; its 8th bit set to 1 ("<1>A") becomes "&A"; a Control-A with its 8th bit ; set to 1 ("<1>") becomes "&#A". ; ;The Repeat-Count Prefix ; The repeat-count prefix provides a simple form of data compression. It ; is used only when both Kermit programs support this feature and agree to ; use it. This prefix, normally tilde "~" (ASCII 126), precedes a repeat ; count, which can range from 0 to 94. The repeat count is encoded as a ; printable ASCII character in the range SP (32) - tilde (126) by adding ; 32. For example, a series of 36 G's would be encoded as "~DG" (D = ASCII ; 68 - 32 = 36). The repeat-count prefix applies to the following prefixed ; sequence, which may be a single character ("~DG"), an 8th-bit prefixed ; character ("~D&G" = 36 Control-G characters with their 8th bits set to ; 1), a control-prefixed character ("~D#M" = 36 Control-M's), or an ; 8th-bit-and-control-prefixed character ("~~&#Z" = 94 Control-Z's with ; their 8th bits set to 1). ; ;The Prefix Quote ; The control prefix, normally "#", is also used to quote the control ; prefix itself if it occurs in the data: "##", meaning that the "#" ; character should be taken literally. If 8th-bit prefixing is in effect, ; the control prefix also quotes the 8th-bit prefix: "#&", so "#&D" stands ; for "&D" rather than "<1>D". If repeat count prefixing is in effect, the ; control prefix is also used to quote the repeat count prefix: "#~", so ; "#~CG" stands for "~CG" rather than 35 "G" characters. So the complete ; meaning of the "#" prefix is: if the value of the following character is ; 77, 64-95, 192-223 or 205, the prefixed character is to be XORed with 64, ; otherwise it is to be taken literally. The prefix quote can also be used ; harmlessly to quote 8th-bit or repeat-count prefixing characters even ; when these types of prefixing are not in effect. ; ; Examples, using notation of : ; ; Original data stream ; <0>A<0>B<0>C<1>D<1>E<1>F<1>G<1>H<1>I<0>J<0>K<0>L<0>M (13 characters) ; would be transmitted like this with single shifts: ; &A&B&C&D&E&F&G&H&I&J&K&L&M (26 characters) ; and like this with locking shifts: ; ABCDEFGHIJKLM (15 characters) ; On an 8-bit connection, of course, this string of characters can be ; transmitted as-is, with no overhead at all. ; ; Now suppose we have the following character sequence: ; <1>A<1>B<1>C<0>D<1>E<1>F<1>G<0>H<1>I<1>J<1>K<0>L<1>M (13 characters) ; Several isolated 7-bit characters are found in the middle of a long run ; of 8-bit characters. Using locking shifts alone, this would be encoded as: ; ABCDEFGHIJKLM (20 characters) ; But using a combination of locking and single shifts, it can be encoded more ; compactly, as in this example, in which "&" is the single-shift character: ; ABC&DEFG&HIJK&LM (17 characters) ; ; ; Do encoding. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr. ; Writes output to area pointed to by [si].datadr. ; Returns char count in cx and [si].datlen with carry clear if success, ; else carry set if overflow. ; SI is preserved doenc: clc jcxz doen0 ; cx = 0 means nothing to encode mov ah,dblbyteflg ; preserve state mov al,dblbyte push ax mov al,shiftstate ; locking shift state mov ah,DLEseen ; DLE state push ax ; save mov dblbyteflg,0 ; init encode as doubles mov shiftstate,0 ; init shift states mov DLEseen,0 mov echrcnt,cx ; number of bytes of source data mov ebufpnt,offset encbuf ; source of data mov encinp,offset nulref ; null routine for refilling buffer call encode ; make a packet with size in AX mov cx,ax pop ax ; restore state mov shiftstate,al mov DLEseen,ah pop ax mov dblbyteflg,ah mov dblbyte,al doen0: ret nulref: mov echrcnt,0 ; no data to return stc ret ; encode - writes data portion of kermit packet into [[si].datadr]. ; expects encinp to contain the address of a routine to refill the buffer, ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain ; the maximum size of the data packet, ebufpnt to contain a pointer to ; the source of the characters, and [si].datadr to be output address. ; Trans.lshift is non-zero if locking shift encoding is active. ; While locking shift is active DLE escapes DLE, SI, and SO to be ; data characters. Under locking shift rules SO (Control-N) shifts high bit ; data to non-high bit data; SI (Control-O) cancels SO. Shiftstate is ; 0 for non-shifted state, 80h for shifted state. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while ; performing Japanese translation; dblbyte is the first byte of the pair. ; Returns: AX = the number of characters actually written to the buffer ; All packets except I, S, and A types are encoded. ; Packet space is precomputed allowing for prefixes other than locking shifts. ; Returns carry clear for success, carry set otherwise. encode proc near push es push si ; save caller's si mov cx,trans.maxdat ; maximum packet size cmp cx,[si].datsize ; buffer capacity of this slot jbe encod1 ; be = not overflowing slot mov cx,[si].datsize ; use smaller pkt buffer encod1: les di,[si].datadr ; address of output buffer to es:[di] mov temp,di ; remember output buffer start address mov si,ebufpnt ; pointer into source buffer mov dl,trans.rquote ; send quote char xor dh,dh ; assume no 8-bit quoting mov al,trans.ebquot ; 8-bit quote cmp al,'N' ; refusing 8-bit quoting? je encod10 ; e = yes cmp al,'Y' ; or can but won't? je encod10 ; e = yes, else specific char mov dh,0ffh ; remember we have to do 8-bit quotes ; top of read loop encod10:or cx,cx ; any space left in output buffer? jg encod11 ; g = yes mov ax,di ; current output location sub ax,temp ; minus start of buffer, ret cnt in AX mov ebufpnt,si ; update pointer into source buffer pop si ; restore caller's si pop es mov [si].datlen,ax clc ; success ret encod11:cmp echrcnt,0 ; any data in buffer? jg encod20 ; g = yes, skip over buffer refill push es call encinp ; get another buffer full pop es jnc encod14 ; nc = success encod12:pop si ; restore user's si sub di,temp ; minus start of buffer or di,di ; buffer empty? jz encod13 ; z = yes mov ax,di ; report size encoded mov [si].datlen,ax pop es clc ; success ret ; return success encod13:xor ax,ax ; empty buffer mov flags.eoflag,1 ; set eof flag mov filflg,al ; nothing in input buffer mov [si].datlen,ax pop es stc ; failure ret ; return failure encod14:mov si,ebufpnt ; update position in source buffer cmp echrcnt,0 ; any characters returned? je encod12 ; e = none, assume eof encod20:cld ; forward direction lodsb dec echrcnt ; decrement input count mov ah,al and ah,80h ; keep high bit in ah mov rptct,1 ; say have one copy of this char cmp al,'Z'-40H ; is this a control-Z? jne encd30 ; ne = no, skip eof-processing cmp flags.eofcz,0 ; is a Control-Z an end of file? je encd30 ; e = no cmp trans.xtype,1 ; file type binary? je encd30 ; e = yes, send as is mov flags.eoflag,1 ; yes, set eof flag mov filflg,0 ; say no more source data in buffer mov echrcnt,0 ; ditto jmp short encod12 ; set character count and return ; analyze current char (al) encd30: cmp echrcnt,0 ; doing the last character? jle encod40 ; le = yes, there is no next character or cx,cx ; space for repeat group in output? jle encod40a ; le = no, not enough for rpt prefix cmp al,[si] ; this is char the same as the next? jne encod40 ; no, do this char independently cmp trans.rptq,0 ; repeat prefixing disabled? je encod40 ; e = yes push cx ; scan for repeats in input buffer push bx mov cx,echrcnt ; count of bytes left in input buf inc cx ; will reread current byte cmp cx,94 ; max prefix of 94 jbe encod31 ; be = ok, else limit scan to 94 mov cx,94 encod31:xor bx,bx ; count of copies of this char in buf encod32:inc bx cmp [si+bx-1],al ; new [si+bx-1] same as current (al)? loope encod32 ; e = yes, do all of interest cmp bx,3 ; enough repeats to use prefix? jae encod33 ; ae = yes mov bx,1 ; say do one char encod33:mov rptct,bl ; bl is qty repeated overall dec bx ; bx = number of extra chars (>1) add si,bx ; move forward by repeat group sub echrcnt,bx ; adjust input buffer counter too pop bx pop cx ; test for locking shift applicability encod40:cmp cx,2 ; space left for prefixed lock? jb encod50 ; b = no, not enough for prefix cmp trans.lshift,lock_disable ; locking shifts disabled? je encod50 ; e = yes, skip this material cmp ah,shiftstate ; change of high bit status? jne encod41 ; ne = yes encod40a:jmp encod50 ; no, stay in same lock state ; change of high bit encod41:mov bx,echrcnt ; count chars remaining to be read add bl,rptct ; add repeat count adc bh,0 cmp bx,4 ; at least 4 more chars to examine? jb encod50 ; b = no, not worth a lock change cmp rptct,4 ; enough repeats to take short cut? jae encod43 ; ae = plenty of repeats push ax ; look for change of shift state push cx push si mov cl,rptct ; repeat count xor ch,ch dec cx ; count is one for no repeats sub si,cx ; back up over repeated chars mov cx,4 ; look ahead 4 chars encod42:lodsb ; read ahead and al,80h ; pick out high bit cmp al,ah ; high bit the same? loope encod42 ; loop while same pop si pop cx pop ax jne encod50 ; ne = differ, don't change lock ; change locking shift state encod43:mov es:[di],dl ; insert quote char (#) inc di ; adjust output buffer pointer dec cx push ax mov ah,shiftstate ; get current shift state xor ah,80h ; toggle shift state mov shiftstate,ah ; remember it mov al,SIchar+40h ; assume going into unshifted state or ah,ah ; to unshifted state now? jz encod44 ; z = yes, go to unshifted state mov al,SOchar+40h ; say go to shifted state encod44:stosb ; put lock char into packet dec cx pop ax ; recover current character ; end of locking shift tests encod50:or dh,dh ; doing 8-bit quoting? jz encod60 ; z = no, forget this cmp trans.lshift,lock_disable ; locking shift disabled? je encod57 ; e = yes cmp ah,shiftstate ; different than current shift state? jne encod58 ; ne = yes, specials will be prefixed push ax ; save char (stripped of high bit) and al,7fh ; consider high bit controls too cmp al,SIchar ; SI (Control-O)? je encod53 ; e = yes cmp al,SOchar ; SO (Control-N)? je encod53 ; e = yes cmp al,DLE ; DLE (Control-P)? jne encod54 ; ne = no encod53:mov al,dl ; stuff a quote (#) stosb dec cx mov al,DLE + 40h ; then a DLE prefix (P) stosb dec cx ; account for it in buffer size encod54:pop ax ; exit with original char in AL jmp short encod60 ; no 8-bit prefixing needed here encod57:cmp ah,shiftstate ; different than current shift state? je encod60 ; e = no, don't send quoted form encod58:cmp rptct,1 ; doing repeats? jbe encod59 ; be = no cmp trans.rptq,0 ; disabled? je encod59 ; e = yes push ax ; do repeat prefixing - save data mov al,trans.rptq ; insert repeat prefix char stosb dec cx ; account for it in buffer size mov al,rptct ; get the repeat count add al,20h ; make it printable stosb ; insert into buffer dec cx pop ax ; get back the actual character encod59:mov bl,trans.ebquot ; get 8-bit quote char mov es:[di],bl ; put in packet inc di dec cx ; decrement # of chars left jmp short encod60b ; common prefix testing section encod60:cmp rptct,1 ; doing repeats? jbe encod60b ; be = no cmp trans.rptq,0 ; repeat quoting disabled? je encod60b ; e = yes, disabled push ax ; do repeat prefixing - save data mov al,trans.rptq ; insert repeat prefix char stosb dec cx ; account for it in buffer size mov al,rptct ; get the repeat count add al,20h ; make it printable stosb ; insert into buffer dec cx pop ax ; get back the actual character encod60b:and al,7fh ; turn off 8th bit in character cmp al,' ' ; compare to a space jae encod61 ; ae = not a control code push bx ; check for unprefixed selections mov bl,al ; as 1=7-bit, 80h=8-bit, 81h=both xor bh,bh mov bl,protlist[bx] ; get 8 and 7 bit encoding rules or bl,bl ; anything being excepted from prefix? jz encod60a ; z = no test bl,ah ; 8-bit unprefixed? jnz encod60a ; nz = yes cmp ah,80h ; is it a 7-bit char in reality? je encod60a ; e = no (prefix it) and bl,1 ; text 7 bit unprefixed encod60a:pop bx jz encod64 ; z = char needs quoting jmp short encod67 ; store char as-is encod61: cmp al,del ; delete? je encod64 ; e = yes, go quote it cmp al,dl ; quote char? je encod65 ; e = yes, go add it or dh,dh ; doing 8-bit quoting? jz encod62 ; z = no, don't translate it cmp al,trans.ebquot ; 8-bit quote char? je encod65 ; e = yes, just output with quote encod62:cmp trans.rptq,0 ; repeat prefixing disabled? je encod67 ; e = yes, don't check for quote char cmp al,trans.rptq ; repeat quote character? je encod65 ; e = yes, then quote it jmp short encod67 ; else don't quote it ; control code section encod64:xor al,40h ; control char, uncontrollify encod65:mov es:[di],dl ; insert control quote char inc di dec cx encod67:or al,ah ; restore high bit, if stripped or dh,dh ; doing eight bit quoting? jz encod68 ; z = no, retain high bit and al,not 80h ; strip high bit encod68:stosb dec cx ; decrement output buffer counter jmp encod10 ; get fresh input encode endp ; Fill encode source buffer, report KB and percentage done. ; Return carry clear for success ; modifies ax inbuf proc near cmp flags.eoflag,0 ; reached the end? je inbuf0 ; e = no stc ; return failure ret inbuf0: push dx push bx push cx mov bx,diskio.handle ; get file handle mov cx,buffsz ; record size mov dx,offset buff ; buffer mov ebufpnt,dx ; buffer pointer cmp trans.xtype,1 ; [HF3] File type binary? je inbuf0a ; [HF3] e = yes, no translation cmp trans.xchset,xfr_japanese ; Japanese-EUC? jne inbuf0a ; ne = no shr cx,1 ; allow for double char encoding mov dx,offset rdbuf ; use this as source buffer inbuf0a:mov ah,readf2 ; read a record int dos jnc inbuf7 ; nc = no error mov flags.cxzflg,'X' ; error, set ^X flag jmp short inbuf1 ; and truncate the file here inbuf7: or ax,ax ; any bytes read? jnz inbuf2 ; nz = yes (the number read) inbuf1: mov flags.eoflag,1 ; set End-of-File mov filflg,0 ; buffer empty mov echrcnt,0 ; zero bytes left in buffer pop cx pop bx pop dx stc ; failure ret inbuf2: cmp trans.xtype,1 ;[HF]941012 type binary ? je inbuf2a ;[HF]941012 e = yes cmp trans.xchset,xfr_japanese ; Japanese-EUC? jne inbuf2a ; ne = no call jpnread ; revise buffer for Japanese inbuf2a:add tfilsz,ax ; total the # bytes transferred so far adc tfilsz+2,0 ; it's a double word mov echrcnt,ax ; number of chars read from file add fsta.fsbyte,ax adc fsta.fsbyte+2,0 mov filflg,1 ; buffer not empty test flags.remflg,dserial ; serial display mode? jnz inbuf3 ; nz = yes, skip kbyte and % display push si push ax call kbpr ; show kilobytes sent call perpr ; show percent sent pop ax pop si ; Character set translation section inbuf3: cmp trans.xchset,xfr_xparent ; Transparent transfer char set? je inbuf6 ; e = yes, no translation cmp trans.xtype,1 ; File Type Binary? je inbuf6 ; e = yes, no translation cmp trans.xchset,xfr_japanese ; Japanese-EUC? je inbuf6 ; e = yes, processed already push ax ; save buffer count mov cx,ax ; loop counter push di push es PUSH DS call cplatin ; set DS:BX to CP to Xfr chr table call cpinvert ; check readable vs invertible set mov di,seg buff mov es,di mov di,offset buff ; scan this buffer cld inbuf4: mov al,es:[di] ; get a char, keep pointer fixed cmp bx,offset icp437L1 ; invertible CP 437 to Latin1? jne inbuf4b ; ne = no mov ah,al cmp ah,127 ; special case? jne inbuf4d ; ne = no mov al,26 ; 127 to 26 jmp short inbuf5 inbuf4d:cmp al,20 ; range for special cases? jb inbuf5 ; b = no cmp al,21 ja inbuf5 ; a = no mov al,167 je inbuf5 ; 21 to 167 mov al,182 jmp short inbuf5 ; 20 to 182 inbuf4b:cmp bx,offset icp850L1 ; invertible CP 850 to Latin1? jne inbuf4a ; ne = no cmp al,28 ; special case? jne inbuf4c ; ne = no mov al,127 ; 28 to 127 jmp short inbuf5 inbuf4c:cmp al,127 ; special case? jne inbuf4a mov al,26 ; 127 to 26 inbuf4a:test al,80h ; GRight? jz inbuf5 ; z = no and al,not 80h ; strip high bit xlatb ; translate via bx table inbuf5: stosb ; store char loop inbuf4 ; do all concerned POP DS pop es pop di pop ax inbuf6: pop cx pop bx pop dx clc ; success ret inbuf endp ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp) ; Read buffer rdbuf to convert from file character set Shift-JIS (Code Page ; 932) to transfer character set Japanese-EUC. Double char translation state ; is maintained across file buffers. Init dblbyte to 0 before each new file. ; Output is written to buff, with byte count in register AX. The output ; could be twice the size of the input. [rewritten by jrd] jpnread proc near ; [HF] read Japanese from file push si push di push es mov cx,ax ; number of chars in source buffer mov ax,ds mov es,ax mov dl,dblbyteflg ; get state info from previous call mov ah,dblbyte ; first byte too mov si,offset rdbuf ; read from here mov di,offset buff ; write to here (avoids overwrites) cld jpnrea1:lodsb ; get a byte or dl,dl ; doing first byte? jnz jpnread3 ; nz = no, second of a pair cmp al,81h ; is it Kanji? jb jpnrea5 ; b = no cmp al,0fch ja jpnrea5 ; a = no cmp al,9fh jbe jpnrea2 ; be = yes cmp al,0e0h jb jpnrea5 ; b = no jpnrea2:mov ah,al ; AL is first byte of Kanji, save it mov dl,1 ; say ready to do second byte next jmp short jpnrea8 ; continue loop jpnread3:cmp al,40h ; is second byte Kanji? jb jpnrea6 ; b = no cmp al,0fch ja jpnrea6 ; a = no cmp al,7eh jbe jpnrea4 ; be = yes cmp al,80h jb jpnrea6 ; b = no jpnrea4:call jpnftox ; convert to xfer char code jmp short jpnrea6 ; write the pair jpnrea5:cmp al,0a1h ; Katakana? jb jpnrea7 ; b = no cmp al,0dfh ja jpnrea7 ; a = no mov ah,8eh ; set Katakana prefix jpnrea6:xchg ah,al ; write two bytes stosb ; store first byte xchg ah,al ; get second byte into AL again jpnrea7:stosb ; store a byte xor dl,dl ; say all bytes have been written jpnrea8:loop jpnrea1 mov dblbyteflg,dl ; save state info mov dblbyte,ah ; and first char of a pair sub di,offset buff ; compute number of bytes written mov ax,di ; report new count in AX pop es pop di pop si ret jpnread endp ; File character code (Shift-JIS) to xfer character code (EUC) converter. ; From Shift-JIS to EUC ; if( code1 <= 0x9f ) ; code1 -= 0x71; ; else ; code1 -= 0xb1; ; code1 = code1 * 2 + 1; ; if( code2 > 0x7f ) code2 -= 1; ; if( code2 >= 0x9e ){ ; code2 -= 0x7d; ; code1 += 1; ; } else ; code2 -= 0x1f; ; EUC_code1 = (code1 | 0x80); ; EUC_code2 = (code2 | 0x80); ; [ fputc( EUC_code1, packet ); fputc( EUC_code2, packet ); ] ; jpnftox proc near cmp ah,9fh ja jpnftox1 sub ah,71h jmp short jpnftox2 jpnftox1:sub ah,0b1h jpnftox2:shl ah,1 inc ah cmp al,7fh jbe jpnftox3 dec al jpnftox3:cmp al,9eh jb jpnftox4 sub al,7dh inc ah jmp jpnftox5 jpnftox4:sub al,1fh jpnftox5:or ax,8080h ret jpnftox endp ; GETFIL, called only by send code ; Enter with raw filename pattern in diskio.string ; Returns carry clear if success, else carry set getfil proc near mov dblbyteflg,0 ; clear encoder state variable mov shiftstate,0 ; locking shift state mov DLEseen,0 ; escape state mov filflg,0 ; say nothing is in the buffer mov flags.eoflag,0 ; not the end of file cmp atflag,0 ; at sign file list? je getfil2 ; e = no ; get a filename to diskio.string from file atfile+2 call readatfile jnc getfil2 ; nc = success ret ; else return carry set for failure getfil2:mov dx,offset diskio.dta ; data transfer address mov ah,setdma ; set disk transfer address int dos xor cx,cx ; attributes: find only normal files mov dx,offset diskio.string ; filename string (may have wild cards) mov ah,first2 ; DOS 2.0 search for first int dos ; get file's characteristics pushf ; save c flag mov ah,setdma ; reset dta address mov dx,offset buff ; restore dta int dos popf ; restore status of search for first jnc getfi1 ; nc = ok so far ret ; else take error exit getfi1: jmp getfcom ; do common code getfil endp ; GTNFIL called by send code to get next file. ; Returns carry clear for success, carry set for failure. gtnfil proc near xor al,al mov dblbyteflg,al ; clear encoder state variable mov shiftstate,al ; locking shift state mov DLEseen,al ; escape state mov auxfile,al ; clear override name cmp flags.cxzflg,'Z' ; Did we have a ^Z? jne gtnfi1 ; ne = no, else done sending files stc ; carry set for failure ret ; take failure exit gtnfi1: mov filflg,al ; nothing in the DMA mov flags.eoflag,al ; not the end of file mov dx,offset diskio.dta ; point at dta mov ah,setdma ; set the dta address int dos mov ah,next2 ; DOS 2.0 search for next int dos pushf ; save carry flag mov ah,setdma ; restore dta mov dx,offset buff int dos popf ; recover carry flag jnc getfcom ; nc = success, do common code cmp atflag,0 ; at sign file list? jne getfil ; ne = yes stc ret ; carry set means no more files found gtnfil endp ; worker for getfil, gtnfil getfcom proc near push si push di mov dx,offset diskio.string ; original file spec (may be wild) mov di,offset templp ; place for path part mov si,offset templf ; place for filename part call fparse ; split them mov si,offset diskio.fname ; current filename from DOS call strcat ; (di)= local path + diskio.fname cmp sndpathflg,0 ; include SEND PATH? je getfco4 ; e = no cmp auxfile,0 ; already have an override name? jne getfco4 ; ne = yes mov si,di ; source is local path +diskio.fname cmp byte ptr [si+1],':' ; disk drive included? jne getfco4 ; ne = no add si,2 ; yes, skip drive: part getfco4:mov di,offset encbuf ; name to send to host (no path) call strcpy ; new string = old path + DOS's filename push bx push cx test flags.remflg,dquiet ; quiet display? jnz getfco1 ; e = yes, do not display filename call clrfln ; position cursor & blank out the line mov dx,offset encbuf ; name host sees call prtasz getfco1:call newfn ; update encbuf with "send as" name pop cx pop bx mov ah,open2 ; file open xor al,al ; 0 = open readonly cmp dosnum,300h ; at or above DOS 3? jb getfco2 ; b = no, so no shared access or al,40h ; open readonly, deny none getfco2:mov dx,offset templp ; filename string with path int dos jc getfco3 ; c = failed to open the file mov diskio.handle,ax ; save file handle xor ax,ax mov tfilsz,ax ; set bytes sent to zero mov tfilsz+2,ax mov ax,-1 ; get a minus one mov oldkbt,ax mov oldper,ax clc ; carry clear for success getfco3:pop si pop di ret getfcom endp ; Read line from file in atfile+2, return unpadded ASCIIZ string to ; diskio.string. ; Return carry clear if success, else carry set. readatfile proc near cmp word ptr atfile,0 ; file handle, open? jne reada3 ; ne = is open, do a read line mov dx,offset atfile+3 ; get filename, skip handle and @ mov di,dx mov cx,64 ; max length of a filename. reada1: cmp byte ptr [di],' ' ; whitespace or control code? jbe reada2 ; be = yes, found termination inc di ; else look at next char loop reada1 ; limit search reada2: mov byte ptr [di],0 ; make asciiz mov ah,open2 ; DOS 2 open file xor al,al ; open for reading int dos mov word ptr atfile,ax ; store file handle jnc reada3 ; nc = open ok, read from file mov word ptr atfile,0 ; say file is closed ret ; carry set for fail reada3: mov bx,word ptr atfile ; file handle mov cx,63 ; # of bytes to read mov di,offset diskio.string ; destination mov ah,ioctl ; ioctl, is this the console device? xor al,al ; get device info int dos and dl,81h ; ISDEV and ISCIN bits needed together cmp dl,81h ; Console input device? jne reada5 ; ne = no, use regular file i/o reada4: mov ah,coninq ; read console, no echo int dos cmp al,CR ; end of the line yet? je reada4b ; e = yes cmp al,' ' ; whitespace? je reada4 ; e = yes cmp al,TAB je reada4 cmp al,'C'-40h ; Control-C? jne reada4a ; ne = no stc ret ; return failure reada4a:mov [di],al inc di loop reada4 ; keep reading reada4b:mov byte ptr [di],0 ; insert terminator jmp short reada6 ; finish up reada5: mov dx,di ; destination ptr push cx push es mov cx,seg diskio mov es,cx mov cx,1 ; one byte mov byte ptr [di],0 ; insert null terminator, clears line mov ah,readf2 ; DOS 2 read from file int dos pop es pop cx or ax,ax ; bytes read, zero? je reada6 ; e = yes, exit reading mov al,[di] ; byte just read cmp al,' ' ; white space? je reada5 ; e = yes, skip cmp al,TAB ; white space? je reada5 ; e = yes, skip cmp al,',' ; comma separator? je reada5a ; e = yes cmp al,CR ; first part of line terminator? je reada5 ; e = yes, skip cmp al,LF ; end of the line yet? je reada5a ; e = yes inc di ; where to write next time loop reada5 ; keep reading reada5a:mov byte ptr [di],0 ; insert terminator cmp diskio.string,0 ; empty field? jne reada6 ; ne = no jmp readatfile ; start over reada6: cmp diskio.string,0 ; anything present? jne reada7 ; ne = yes mov bx,word ptr atfile ; file handle mov ah,close2 ; close file (wanted just one line) int dos mov word ptr atfile,0 ; clear handle mov atflag,0 stc ; say EOF ret reada7: clc ; say success ret readatfile endp ; Get the file name from the data portion of the F packet or from locally ; specified override filename (in auxfile), displays the filename, does any ; manipulation of the filename necessary, including changing the name to ; prevent collisions. Returns carry clear for success. Failures return ; carry set with dx pointing at error message text. ; Called by file receive module in mssrcv.asm. gofil proc near mov si,offset decbuf ; filename in packet mov di,offset diskio.string ; place where prtfn finds name call strcpy ; copy pkt filename to diskio.string mov di,offset fsta.xname ; statistics external filespec area call strcpy ; record external name cmp rcvpathflg,0 ; RECEIVE PATHNAMES enabled? jne gofil0c ; ne = ues cmp auxfile,0 ; in use already? jne gofil0c ; ne = yes mov auxfile,'.' ; dot+nul forces use of current dir mov auxfile+1,0 jmp short gofil0d gofil0c:cmp auxfile,0 ; have override name? jne gofil1 ; ne = yes gofil0d:cmp flags.xflg,0 ; receiving to screen? jne gofil0a ; ne = yes, filename becomes CON cmp flags.destflg,dest_disk ; destination is disk? je gofil1 ; e = yes mov di,offset printer ; assume PRN is local file name jb gofil0b ; b = yes gofil0a:mov di,offset screen ; use CON (screen) as local file name mov flags.xflg,1 ; say receiving to screen gofil0b:xchg di,si ; di --> decbuf, si --> file name call strcpy ; put local name (si) into decbuf mov nmoflg,1 ; say that we have a replacement name jmp gofil9 ; final filename is now in 'decbuf' gofil1: xor ax,ax mov nmoflg,al ; assume no override name cmp auxfile,al ; overriding name from other side? jne gofi1e ; ne = yes jmp gofil4 ; e = no, get the other end's filename gofi1e: mov nmoflg,1 ; say using an override name mov ax,offset auxfile ; get local override filename cmp word ptr auxfile+1,003ah; colon+null?(primative drive spec A:) je gofil3 ; e = yes, skip screwy DOS response (No Path) cmp word ptr auxfile,'..' ; parent directory? jne gofi1g ; ne = no cmp word ptr auxfile+1,002eh ; dot dot + null? je gofi1b ; e = yes, process as directory gofi1g: cmp word ptr auxfile,002eh ; dot + null (current dir)? je gofi1b ; e = yes, process as directory call isfile ; does it exist? jnc gofi1f ; nc = file exists test filtst.fstat,80h ; serious error? jz gofil3 ; z = no, just no such file jmp gofi18a ; else quit here gofi1f: test byte ptr filtst.dta+21,10H ; subdirectory name? jnz gofi1b ; nz = yes cmp filtst.fname,2eh ; directory name? je gofi1b ; e = yes, process as directory cmp auxfile+2,5ch ; a root directory like b:\? jne gofi1d ; ne = no. (DOS is not helpful with roots) cmp auxfile+3,0 ; and is it terminated in a null? je gofi1b ; e = yes, so it is a root spec gofi1d: test byte ptr filtst.dta+21,0fh ; r/o, hidden, system, vol label? jz gofil3 ; z = no jmp gofi18a ; yes. Complain and don't transfer file gofi1b: mov dx,offset auxfile ; auxfile is a (sub)directory name call strlen ; get its length w/o terminator jcxz gofil2 ; zero length dec cx ; examine last char push bx ; save bx mov bx,cx add bx,dx cmp byte ptr [bx],5ch ; ends in backslash? je gofil2 ; e = yes cmp byte ptr [bx],2fh ; maybe forward slash? je gofil2 ; e = yes mov byte ptr [bx + 1],5ch ; no slash yet. use backslash mov byte ptr [bx + 2],0 ; plant new terminator gofil2: pop bx gofil3: mov di,offset templp ; local path mov si,offset templf ; local filename mov dx,offset auxfile ; local string call fparse ; split local string mov di,offset temprp ; remote path mov si,offset temprf ; remote file mov dx,offset decbuf ; remote string mov decbuf+64,0 ; force filename to be <= 64 chars call fparse ; split remote string test flags.remflg,dserver ; running in Server mode? jz gofi3c ; z = no test denyflg,sndflg ; is Deny Send mode in operation? jz gofi3c ; z = no mov temprp,0 ; DENY, means remove remote path gofi3c: mov si,offset templp ; copy local path to mov di,offset decbuf ; final filename call strcpy ; do the copy mov si,offset templf ; assume using local file name cmp byte ptr templf,0 ; local file name given? jne gofi3b ; ne = yes mov si,offset temprf ; else use remote file name gofi3b: call strcat ; append path and filename again ; offset decbuf holds the new filename ; ; recheck legality of filename in 'decbuf' gofil4: mov decbuf+64,0 ; guard against long filenames mov di,offset temprp ; remote path mov si,offset temprf ; remote file mov dx,offset decbuf ; remote string call strlen ; get original size push cx ; remember it call fparse ; further massage filename push si ; put pieces back together call verfil ; verify each char in temprf string mov si,di ; get path part first mov di,dx ; set destination call strcpy ; copy in path part pop si ; recover (new) filename cmp byte ptr [si],'.' ; does filename part start with a dot? jne gofil5 ; ne = no push di ; save regs push si mov di,offset rdbuf ; a work area mov byte ptr [di],'X' ; start name with letter X inc di call strcpy ; copy rest of filename mov di,si mov si,offset rdbuf ; copy new name back to original location call strcpy pop si ; restore regs pop di gofil5: call strcat ; append it call strlen ; see if we chopped out something pop si ; get original length (from push cx above) cmp cx,si ; same size? je gofil9 ; e = yes mov nmoflg,1 ; say that we have a replacement name ; filename is now in 'decbuf', all converted gofil9: test flags.remflg,dquiet ; quiet display mode? jnz gofi10 ; nz = yes, don't print it test flags.remflg,dserial ; serial display mode? jz gofi9a ; z = no mov ah,prstr mov dx,offset crlf ; display cr/lf int dos gofi9a: call prtfn ; show packet filename cmp nmoflg,0 ; using local override name? je gofil9b ; e = no cmp flags.xflg,0 ; receiving to screen? (X versus F) jne gofil9b ; ne = yes mov ah,prstr mov dx,offset asmsg ; print " as " int dos mov dx,offset decbuf ; plus the local filename call prtasz ; print asciiz string gofil9b:mov ah,flags.remflg ; display a following cr/lf? and ah,dserial ; for serial display mode or ah,flags.xflg ; receiving to screen jz gofi10 ; z = neither, no cr/lf mov ah,prstr ; finish the line with cr/lf mov dx,offset crlf int dos gofi10: mov filtst.fstat2,0 ; 0 = assume is a disk file mov dx,offset decbuf ; point to name mov ah,open2 xor al,al ; open readonly cmp dosnum,300h ; above DOS 2? jb gofi10a ; b = no, so no shared access or al,40h ; open for reading, deny none gofi10a:mov dx,offset decbuf ; the filename int dos jc gofi16 ; c = cannot open so just proceed mov bx,ax ; file handle mov ah,ioctl xor al,al ; 0 = get info int dos mov ah,close2 ; close it int dos mov ax,offset decbuf ; point to filename again and dl,80h ; ISDEV bit mov filtst.fstat2,dl ; 0 = disk file, else device test dl,80h ; ISDEV bit set? jz gofi11 ; z = no, not a device jmp gofi16 ; device, use name as given gofi11: cmp flags.flwflg,filecol_discard ; no-supersede existing file? jne gofi12 ; ne = no (i.e., do a rename) cmp flags.flwflg,filecol_update ; updating? je gofi16 ; e = yes, delay opening cmp flags.flwflg,filecol_overwrite ; overwrite existing file? je gofi16 ; e = yes gofi11a:mov flags.cxzflg,'X' ; say stop this file mov word ptr decbuf,'UN' mov decbuf+2,'L' ; file name of NUL mov decbuf+3,0 ; asciiz jmp short gofi13 gofi12: cmp flags.flwflg,filecol_rename ; rename existing file? jne gofi16 ; ne = no mov ax,offset decbuf ; point to filename again call unique ; generate unique name jc gofi14 ; could not generate a unique name test flags.remflg,dquiet ; quiet display mode? jnz gofi13 ; nz = yes, skip printing push ax ; save unique name again call frpos ; position cursor mov ah,prstr ; say we are renaming the file mov dx,offset infms5 int dos pop ax ; get name back into ax again push ax ; save around these calls mov dx,ax ; print current filename call prtasz ; display filename pop ax ; pointer to name, again gofi13: jmp short gofi16 ; and go handle file gofi14: mov dx,offset ermes4 call ermsg stc ; failure, dx has msg pointer ret gofi16: mov si,offset decbuf ; pointer to (maybe new) name mov di,offset diskio.string ; filename, used in open call strcpy ; copy name to diskio.string xor ax,ax mov diskio.sizehi,ax ; original file size is unknown mov diskio.sizelo,ax ; double word mov tfilsz,ax ; set bytes received to zero mov tfilsz+2,ax mov ax,-1 ; get a minus one mov oldkbt,ax mov oldper,ax mov wrpmsg,al clc ; finished composing filename ret ; in diskio.string gofi18a:mov si,ax ; pointer to local override name mov di,offset diskio.string ; filename, used in open call strcpy ; copy name to diskio.string ; fall through to gofi18 gofi18: test flags.remflg,dquiet ; quiet display mode? jnz gofi19 ; nz = yes, don't try printing mov dx,offset erms12 ; unable to create file call ermsg push dx mov dx,offset diskio.string ; print offending name call prtasz ; display filename pop dx gofi19: stc ; failure, dx has msg pointer ret gofil endp ; Open file for writing with name in diskio.string goopen proc near xor ax,ax mov dblbyteflg,al ; clear decoder state variable mov shiftstate,al ; locking shift state mov DLEseen,al ; escape state mov tfilsz,ax ; set bytes received to zero mov tfilsz+2,ax mov ax,-1 ; get a minus one mov oldkbt,ax mov oldper,ax cmp diskio.handle,-1 ; is handle unused? je goopen5 ; e = yes mov dx,diskio.handle ; close the file now mov ah,close2 int dos mov diskio.handle,-1 ; clear handle of previous usage goopen5:mov ax,offset diskio.string ; filename, asciiz call isfile ; check for read-only/system/vol-label/dir jc goopen1 ; c = file does not exist test byte ptr filtst.dta+21,1fh ; the no-no file attributes jnz gofi18 ; nz = do not write over one of these jmp short goopen2 ; open existing goopen1:test filtst.fstat,80h ; access problem? jnz gofi18 ; nz = yes, quit here mov dx,offset diskio.string ; filename, asciiz mov ah,creat2 ; create file xor cx,cx ; 0 = attributes bits int dos jc goopen2 ; c = did not work, try regular open mov diskio.handle,ax ; save file handle here xor dx,dx ; file size, high word xor ax,ax ; low word clc ; carry clear for success ret goopen2:test byte ptr filtst.dta+21,1bh ; r/o, hidden, volume label? jnz gofi18 ; we won't touch these mov dx,offset diskio.string ; filename, asciiz mov ah,open2 ; open existing file (usually a device) mov al,1+1 ; open for writing int dos jc gofi18 ; carry set means can't open mov diskio.handle,ax ; file handle cmp flags.flwflg,filecol_update ; updating? jne goopen2c ; ne = no mov ah,fileattr ; get file date/time attributes xor al,al ; get, not set mov bx,diskio.handle ; file handle int dos ; dx=date, cx=time cmp dx,word ptr fdate ; date is earlier than our file? ja goopen2a ; a = yes, skip file jb goopen2c ; b = incoming date is later cmp cx,word ptr ftime ; same date, how about time jb goopen2c ; b = later time, get the file goopen2a:mov dx,diskio.handle ; file handle mov ah,close2 ; close it int dos mov flags.cxzflg,'X' ; say stop this file mov ah,open2 mov al,1 ; open for writing cmp dosnum,300h ; above DOS 2? jb goopen2b ; b = no, so no shared access or al,40h ; open for reading, deny none goopen2b:mov dx,offset vacuum ; NUL as a filename int dos mov diskio.handle,ax ; file handle stc ; carry set for failure ret goopen2c:cmp flags.flwflg,filecol_append ; append to existing file? je goopen3 ; e = yes clc ; carry clear for success ret goopen3:mov bx,diskio.handle ; file handle for seeking xor cx,cx ; high order displacement xor dx,dx ; low order part of displacement mov ah,lseek ; seek to EOF (to do appending) mov al,2 ; says to EOF int dos ret ; return DX:AX as new file pointer goopen endp ; Given incoming filename in 'decbuf'. Verify that each char is legal ; (if not change it to an "X"), force max of three chars after a period (dot) ; Source is at ds:si (si is changed here). VERFIL PROC NEAR push es ; verify each char in 'data' push cx push ds pop es mov havdot,0 ; say no dot found in name yet cld verfi1: lodsb ; get a byte of name from si and al,7fH ; strip any eighth bit jz verfi5 ; z = end of name cmp al,'.' ; a dot? jne verfi2 ; ne = no cmp havdot,0 ; have one dot already? jne verfi3 ; ne = yes, change to X mov byte ptr [si+3],0 ; forceably end filename after 3 char ext mov havdot,1 ; say have a dot now jmp short verfi4 ; continue verfi2: cmp al,3ah ; colon? je verfi4 cmp al,5ch ; backslash path separator? je verfi4 cmp al,2fh ; or forward slash? je verfi4 cmp al,'0' jb verfi3 ; see if it's a legal char < '0' cmp al,'9' jbe verfi4 ; it's between 0-9 so it's OK cmp al,'A' jb verfi3 ; check for a legal punctuation char cmp al,'Z' jbe verfi4 ; it's A-Z so it's OK cmp al,'a' jb verfi3 ; check for a legal punctuation char cmp al,'z' ja verfi3 and al,5FH ; it's a-z, capitalize jmp short verfi4 ; continue with no change verfi3: push di ; special char. Is it on the list? mov di,offset spchar2 ; list of acceptable special chars mov cx,spc2len cld repne scasb ; search string for input char pop di je verfi4 ; e = in table, return it mov al,'X' ; else illegal, replace with "X" mov nmoflg,1 ; say we have a replacement filename verfi4: mov [si-1],al ; update name jmp short verfi1 ; loop thru rest of name verfi5: mov byte ptr[si-1],0 ; make sure it's null terminated pop cx pop es ret VERFIL ENDP ; find a unique filename. ; Enter with a pointer to a (null-terminated) filename in ax ; Return with same pointer but with a new name (or old if failure) ; Success = carry clear; failure = carry set ; The idea is to pad out the main name part (8 chars) with ascii zeros and ; then change the last chars successively to a 1, 2, etc. until ; a unique name is found. All registers are preserved ; Make empty main name fields start with letter X, not digit 0 unique proc near push bx push cx push dx push si push di push es push ax ; save address of source string mov dx,ds ; make es use ds segment mov es,dx mov dx,ax ; point at original filename string mov di,offset templp ; place for path mov si,offset templf ; place for filename call fparse ; separate path (di) and filename (si) mov dx,di ; point at path part call strlen ; put length in cx mov si,ax ; point to original string add si,cx ; point to filename part mov di,offset templf ; destination is temporary location xor cx,cx ; a counter cld ; set direction to be forward uniq1: lodsb ; get a byte cmp al,'.' ; have a dot? je uniq2 ; e = yes or al,al ; maybe null at end? jnz uniq3 ; nz = no, continue loop uniq2: cmp cl,8 ; have we copied any chars before dot? jge uniq3 ; ge = all 8 mov byte ptr [di],'0' ; avoid clobbers; pad with 0's or cl,cl ; first char of filename? jnz uniq2a ; nz = no mov byte ptr [di],'X' ; start name with letter X, not 0 uniq2a: inc di ; and count the output chars inc cl ; and this counter too jmp short uniq2 ; continue until filled 8 slots uniq3: inc cl ; cl = # char in destination stosb ; store the char or al,al ; null at end? jnz uniq1 ; nz = no, continue copying mov templf+7,'1' ; put '1' in last name char mov unum,1 ; start with this generation digit uniq4: mov di,offset rdbuf ; build a temporary full filename mov si,offset templp ; path part call strcpy ; copy that much mov si,offset templf ; get rebuilt filename part call strcat ; paste that to the end mov ax,offset rdbuf ; point to full name call isfile ; does it exist? jc uniq6 ; c = no, succeed now inc unum ; move to next generation mov di,offset templf+7 ; point to last name char mov cx,7 ; max # of digits to play with mov bx,10 ; divisor (16 bits) mov ax,unum ; low order part of generation # uniq5: xor dx,dx ; high order part of generation # div bx ; compute digit (unum / 10) add dl,'0' ; make remainder part printable mov [di],dl ; put into right place or ax,ax ; any more to do? (quotient nonzero) jz uniq4 ; z = no, try this name dec di ; else decrement char position loop uniq5 ; and keep making a number stc ; failure: set carry, keep old name jmp short uniq7 ; and exit uniq6: pop di ; address of original filename push ax ; save for exit clean up mov si,offset rdbuf call strcpy ; copy new filename over old clc ; success: clear carry flag uniq7: pop ax pop es pop di pop si pop dx pop cx pop bx ret unique endp code ends code1 segment assume cs:code1 ; strlen -- computes the length, excluding the terminator, of an asciiz ; string. Input: ds:dx = address of the string ; Output: cx = the byte count ; All registers except cx are preserved ; STRLEN PROC FAR push di push es push ax mov ax,ds ; use proper segment address mov es,ax mov di,dx mov cx,0ffffh ; large byte count cld ; set direction to be forward xor al,al ; item sought is a null repne scasb ; search for it add cx,2 ; add for -1 and auto dec in scasb neg cx ; convert to count, excluding terminator pop ax pop es pop di ret STRLEN ENDP ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1 ; offset of string 1 is expected to be in ds:di. input & output ; offset of string 2 is expected to be in ds:si. input only (unchanged) ; Preserves all registers. No error returns, returns normally via ret ; STRCAT PROC FAR push di ; save work registers push si push es push dx push cx push ax mov ax,ds ; get data segment value mov es,ax ; set es to ds for implied es:di usage mov dx,di call strlen ; get length (w/o terminator) of dest string add di,cx ; address of first terminator mov dx,si ; start offset of source string call strlen ; find its length too (in cx) inc cx ; include its terminator in the count cld rep movsb ; copy source string to end of output string pop ax pop cx pop dx pop es pop si pop di ret STRCAT ENDP ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by ; ds:di. Returns via ret. All registers are preserved ; STRCPY PROC FAR cmp si,di ; same place? jne strcpy1 ; ne = no ret ; having done nothing strcpy1:mov byte ptr [di],0 ; clear destination string call strcat ; let strcat do the real work ret STRCPY ENDP ; fparse -- separate the drive:path part from the filename.ext part of an ; asciiz string. Characters separating parts are \ or / or : ; Inputs: asciiz input full filename string offset in ds:dx ; asciiz path offset in ds:di ; asciiz filename offset in ds:si ; Outputs: the above strings in the indicated spots ; Strategy is simple. Reverse scan input string until one of the ; three separators is encountered and then cleave at that point ; Simple filename construction restrictions added 30 Dec 1985; ; to wit: mainname limited to 8 chars or less, ; extension field limited to 3 chars or less and is found by searching ; for first occurence of a dot in the filename field. Thus the whole ; filename part is restricted to 12 (8+dot+3) chars plus a null ; All registers are preserved. Return is always via ret ; (Microsoft should have written this for DOS 2.x et seq.) FPARSE PROC FAR push cx ; local counter push ax ; local work area push es ; implied segment register for di push di ; offset of path part of output push si ; offset of file name part of output mov ax,ds ; get data segment value mov es,ax ; set es to ds for implied es:di usage mov byte ptr [si],0 ; clear outputs mov byte ptr [di],0 push si ; save original file name address mov si,dx ; get original string address call strcpy ; copy string to original di call strlen ; find length (w/o terminator), in cx mov si,di ; address of string start add si,cx dec si ; si = address of last non-null char jcxz fpars5 ; if null skip the path scan ; now find last path char, if any ; start at the end of input string std ; set direction to be backward fpars4: lodsb ; get a byte (dec's si afterward) cmp al,5ch ; is it a backslash ('\')? je fpars6 ; e = yes cmp al,2fh ; or forward slash ('/')? je fpars6 ; e = yes cmp al,3ah ; or even the drive terminator colon? je fpars6 ; e = yes loop fpars4 ; else keep looking until cx == 0 ; si is at beginning of file name fpars5: dec si ; dec for inc below fpars6: inc si inc si ; si now points at first filename char ; cx holds number of path chars ; get original file name address (si) pop di ; and make it place to copy filename cld ; reset direction to be forward mov ax,si ; ax holds filename address for awhile push dx mov dx,si ; strlen wants string pointer in dx call strlen ; get length of filename part into cx pop dx jcxz fpar7a ; any chars to look at? z = no fpars7: cmp byte ptr [si],'.' ; look for a dot in filename je fpars8 ; e = found one inc si ; look at next filename char loop fpars7 ; keep looking until cx = zero fpar7a: mov si,ax ; no dot. recover starting address mov byte ptr [si+8],0 ; forcably truncate mainname to 8 char call strcpy ; copy this part to filename field jmp short fparsx ; and exit fpars8: mov byte ptr [si+4],0 ; plant terminator after dot + 3 ext chars mov cx,si sub cx,ax ; cx now = number of chars in mainname field cmp cx,9 ; more than 8? jb fpars9 ; b = no, we're safe mov cx,8 ; limit ourselves to 8 chars in mainname fpars9: push si ; remember address of dot and extension mov si,ax ; point to start of input filename rep movsb ; copy cx chars from si to di (output) mov byte ptr [di],0 ; plant terminator where dot goes pop si ; source = dot and extension address call strcat ; append the dot & ext to the filename field fparsx: mov si,ax ; recover start of filename in input string mov byte ptr [si],0 ; terminate path field pop si pop di pop es pop ax pop cx ret FPARSE ENDP ; Print filename in offset diskio.string. PRTFN PROC FAR test flags.remflg,dquiet ; quiet display mode? jnz prtfn1 ; nz = yes, don't display filename push ax ; saves for messy clrfln routine push bx push dx call clrfln ; position cursor & blank out the line mov dx,offset diskio.string call prtasz pop dx pop bx pop ax prtfn1: ret PRTFN ENDP ; Print string to screen from offset ds:di for # bytes given in cx, ; regardless of $'s. All registers are preserved. PRTSCR PROC FAR jcxz prtscr4 ; cx = zero means nothing to show push ax push bx push dx mov dx,di ; source ptr for DOS cmp flags.eofcz,0 ; end on Control-Z? jne prtscr3 ; ne = yes, let DOS do it push cx ; else map Control-Z to space push di push es push ds pop es ; data to es mov al,ctlz ; look for Control-Z cld ; scan buffer es:di, cx chars worth prtscr1:repne scasb jne prtscr2 ; ne = found no Control-Z's mov byte ptr [di-1],' ' ; replace Control-Z with space jcxz prtscr2 ; z = examined all chars jmp short prtscr1 ; until examined everything prtscr2:pop es pop di pop cx prtscr3:mov bx,1 ; stdout file handle mov ah,write2 int dos pop dx pop bx pop ax prtscr4:ret PRTSCR ENDP ; Print to screen asciiz string given in ds:dx. Everything preserved. PRTASZ PROC FAR push cx push di call strlen ; get length of asciiz string mov di,dx ; where prtscr looks call prtscr ; print counted string pop di pop cx ret PRTASZ ENDP code1 ends end