title Converter for SYM files to DASM readable files name ('SYMDASM') maclib base80 ; Program SYMDASM ; Copyright (C) Werner Cirsovius ; Hohe Weide 44 ; D-2000 Hamburg 20 ; Tel.:+49/040 4223247 ; Version 1.0, January 1988 ; Convert symbol files. How to call: ; SYMDASM file{.ext} {/opt} ; /M requests .MAP file ; /F requests alternative format ; /V requests verbose mode ; A program converting symbol files as generated by the linker L80 eg. ; readable for the disassembler DASM. ; There did exist a PD Z80-assembler with linker. The linker ; created .MAP files which are also handled here. ; Why? Sometimes library files may be disassembled. Libraries may be linked ; and generate .COM files including .SYM files. After linking the created ; .COM file it may be disassembled and improved :-) ; The format of a .SYM file is as follows: ; item ; 'item' is defined as ; xxxx name - where xxxx is a 4 byte address and ; name is the label name string ; The format of a .MAP file is as follows: ; item1 item2 ; 'itemi' is defined as ; llll xxxx - where llll is a 15 byte label name string ; xxxx is the 15 byte address entry $memry extrn conino,uppin,conout,strcn0,crlf,filnam,clrscr extrn uppcon,decout,comp3,delay,@asstr,@leng,@parst extrn open,closef,creatd,close,delete,getlnf,emplin extrn rename,rdbuf,rdbfp,rdfcb,wrbuf,wrbfp,wrfcb LINLEN equ 80 NIL equ 0 ASCitm equ 95 ; ASCII range MAXOPT equ 3 SYMMIN equ 6 HEXLEN equ 4 FN equ 32 _S equ 0 _M equ 1 ; ; Dynamic structure ; Bytes 0 -5: ASCII address ; Bytes 6-20: Symbol name ; Bytes 20,21: Link to next dynamic block ; ADRlen equ HEXLEN+1 SYMlen equ 14 ITEMlen equ ADRlen+SYMlen+2 MAPadr equ 17 ; Position of address in MAP file line MAP2lab equ 29 ; Position of 2nd label in MAP file line ; ; Process invalid symbol file ; InvSYM: call crlf ; Give new line ld de,$ILLGENSYM ld a,(ChgFlag) ; Get special change flag cp FALSE jr z,OrigSYM ; Not changed ld de,$ILLFIXSYM OrigSYM: call strcn0 ; Tell error type ld de,$RECALL call strcn0 ld de,Fout call close ; Close file call delete ; Delete file jp OS ; ; Parse command line and prepare files ; PrepEnv: ld a,(CCPbuf) ; Get input or a ; Test any in line jr nz,CCP.ok ; Yeap ld de,$HELP call strcn0 ; Give help if not jp OS ; And exit CCP.ok: ld de,FCB+.fdrv+DIRlen ld a,(de) cp '/' ; Test option jr nz,CCP.noOpt ; Nope inc de ; Skip indicator ld b,MAXOPT ; Set max options ld c,0 call VrfyOpt ; Verify option follows ex de,hl ld (hl),null ; Set end of command ex de,hl ld b,c inc b ; Test any option found dec b jr z,CCP.noOpt ; Nope ld e,00000000b ; Clear option result ld hl,M.EXE ld a,'M' call ExecOpt ; Process options ld hl,F.EXE ld a,'F' call ExecOpt ld hl,V.EXE ld a,'V' call ExecOpt call ValidEnd ; Verify valid end of options CCP.noOpt: ld a,(M.opt) ; Get option (1 is M) call SelectEXT ; Select extension of source file ld b,1 ld de,CCPbuf+FN call @parst ; Select name of file ld hl,CCPbuf+FN call @leng ; Get length of name ld c,a ; Unpack it ld b,0 ld a,'.' cpir ; Find extension delimiter jr z,GotEXT ; Got it ld hl,$EXT ld de,FCB+.fdrv+.fname ld bc,.fext ldir ; Unpack extension jr PrepInfile GotEXT: ld hl,FCB+.fdrv+.fname ld de,$EXT ld bc,.fext ldir ; Save extension ld hl,$$SYM ld a,_S call SelEXT ; Try .SYM ld hl,$$MAP ld a,_M call nz,SelEXT ; Try .MAP otherwise jr z,PrepInfile ; Should be either ld de,$ILLEXT call strcn0 ; Tell invalid extension jp OS ; ; Prepare input file ; PrepInfile: call OpenSource ; Open source file jr nc,FileFound ; Got it ld de,$FILE call strcn0 ; Tell file does not exist ld de,FCB+.fdrv call filnam ; Print name of file ld de,$NOTFOUND call strcn0 jp OS FileFound: ld hl,FCB ld de,Fout ld bc,.fdrv+.fname ldir ; Unpack name ld hl,$$SSY ld bc,.fext ldir ; Unpack extension ; ; Prepare output file ; PrepOutfile: ld hl,WrDMA ld (wrbuf),hl ; Set write buffer ld de,Fout ld (wrfcb),de ; Set file xor a ld (wrbfp),a ; Prepare write call creatd ; Create new file ret ; ; Select option in Accu by extension ^HL ; SelEXT: ld de,$EXT ; Point to extension ld b,a ; Save selection ld c,.fext call comp3 ; Find extension ret nz ; Nope ld a,b ld (M.opt),a ; Set option (1 is M) ret ; ; Verify option at ^DE follows ; VrfyOpt: ld a,(de) ; Get character cp ' '+1 ; Test end of option ret c ; Yeap inc de inc c ; Count option djnz VrfyOpt ex de,hl ld (hl),null ; Set end of option IllOpt: ld de,$ILLOPT call strcn0 ; Tell invalid option ld de,FCB+.fdrv+DIRlen call strcn0 ; Tell option itself jp OS ; ; Verify valid end of options ; ValidEnd: inc b ; Verify it dec b jr nz,IllOpt ; Error ret ; ; Find option in Accu and execute ^HL if found ; ExecOpt: inc b ; Test more to find dec b ret z ; Nope push hl push bc ld hl,FCB+.fdrv+DIRlen+1 ld bc,MAXOPT cpir ; Find option pop bc pop hl ret nz ; Nope jp (hl) ; Execute it ; ; Process option 'M' ; M.EXE: bit 0,e ; Test already selected ret nz ; Yeap, ignore set 0,e ; Set selected dec b ; Fix remainder ld a,_M ld (M.opt),a ; Select option ret ; ; Process option 'F' ; F.EXE: bit 1,e ; Test already selected ret nz ; Yeap, ignore set 1,e ; Set selected dec b ; Fix remainder ld hl,F.Format ld (Format),hl ; Change format routine ld a,TRUE ld (F.opt),a ; Select option ret ; ; Process option 'V' ; V.EXE: bit 2,e ; Test already selected ret nz ; Yeap, ignore set 2,e ; Set selected dec b ; Fix remainder ld a,TRUE ld (V.opt),a ; Select option ret ; ; Select extension of source file selected vy Accu ; SelectEXT: ld hl,$$MAP cp _M ; Test .MAP file jr z,SelectMAP ld hl,$$SYM SelectMAP: ld de,$EXT ld bc,.fext ldir ; Unpack into error message ret ; ; Insert label into dynamic field ; InsertLabel: ld hl,DynPtr ; Init pointer InsertLoop: push hl pop ix ld l,(ix+0) ; Get address ld h,(ix+1) ld a,l ; Test NIL or h jr nz,MoreLabels ; Nope, not the first entry call malloc ; Allocate memory ld (ix+0),e ; Store root ld (ix+1),d ld bc,NIL ; Indicate last in list push bc jr InsertValues MoreLabels: call FindLabel ; Find label jp z,InvSYM ; Got it, error jr nc,LabelNotOnTop; Not at top push hl call malloc ; Allocate memory pop hl push de push hl ld bc,ITEMlen ldir ; Unpack data pop de InsertValues: ld hl,$HEXbuf ld bc,ADRlen ldir ; Unpack address ld hl,SYMitem ld bc,SYMlen ldir ; Unpack name ex de,hl pop de ld (hl),e ; Set link inc hl ld (hl),d ret LabelNotOnTop: ld de,ADRlen+SYMlen add hl,de ; Advance to next jr InsertLoop ; Try next ; ; Find label - Z set says found ; FindLabel: push hl ld de,ADRlen add hl,de ld de,SYMitem call CmpLabel ; Find label pop hl ret z ; Got it push af ld a,(F.opt) ; Test option F (TRUE is) cp TRUE jr z,FinAddr pop af ret FinAddr: pop de push hl ld de,$HEXbuf call CmpLabel ; Find address pop hl ret nz ld a,1 or a ret ; ; Write labels to file ; WrtLabels: ld hl,DynPtr ; Init pointer WrtLoop: push hl pop ix ld l,(ix+0) ; Get link ld h,(ix+1) ld a,l ; Test done or h ret z ; Yeap push hl ld de,FileLine+1 Format equ $+1 call S.Format ; Format output ex de,hl ld (hl),cr ; Close line inc hl ld (hl),lf inc hl ld (hl),b ld de,FileLine+1 call emplin ; Write line to disk ld hl,(SymCount) inc hl ; Advance symbol count ld (SymCount),hl pop hl ld de,ADRlen+SYMlen add hl,de ; Advance to next entry jr WrtLoop ; ; Standard format routine ; S.Format: ld bc,HEXLEN ldir ; Unpack address inc hl ld a,' ' ld (de),a ; Set delimiter inc de call @asstr ; Unpack symbol dec de ret ; ; Format routine if option 'F' seleted ; F.Format: push hl ld bc,ADRlen add hl,bc call @asstr ; Unpack symbol dec de ld hl,$LAB.F call @asstr ; Set delimiter dec de pop hl ld bc,HEXLEN ldir ; Unpack address ret ; ; Position ^HL to printable character ; Skp2Prn: ld a,(hl) cp ' '+1 ; Test range ret nc inc hl jr Skp2Prn ; ; Process symbol file ; Proc$SYM: ld a,FALSE ld (ChgFlag),a ; Clear change flag ProcSync: ld de,FileLine+1 call RdSFline ; Get line from disk ret c ; End of file ex de,hl NextLabel: call @leng ; Get length cp SYMMIN ; Test possible label jr c,ProcSync ; Nope call Skp2Prn ; Position to printable character ld a,(M.opt) ; Get option (1 is M) cp _M jr z,DoMAP ; Process MAP file ld de,$HEXbuf ld bc,HEXLEN ldir ; Unpack address call Skp2Prn ; Position to printable character jr MAPlabel DoMAP: push hl ld de,MAPadr add hl,de ; Point to hex address ld de,$HEXbuf ld bc,HEXLEN ldir ; Unpack it ld de,$HEXbuf ld hl,$$UNKNOWN ld c,HEXLEN call comp3 ; Test unknown label found pop hl jr nz,MAPlabel ; Not found ld de,$UNKNOWN call strcn0 ; Tell unknown label ld de,FCB+.fdrv call filnam ; Print name of file call crlf ; Give new line jp OS MAPlabel: ld de,$HEXbuf ; Point to address ld b,HEXLEN ; Get length chkHEX: ld a,(de) call isHEX ; Test hex character jr c,illHEX ; Nope inc de djnz chkHEX jr SampLabel illHEX: ld de,$ILLFORM call strcn0 ; Tell illegal file format ld de,FCB+.fdrv call filnam ; Print name of file ld de,$ILLPC call strcn0 jp OS SampLabel: push hl ld b,0 ; Clear counter ld de,SYMitem ; Init label address SampLabelLoop: ld a,(hl) ; Get character cp ' '+1 ; Test printable jr c,EndLabel ; Nope ld (de),a ; Unpack inc de inc hl inc b ; Count up jr SampLabelLoop EndLabel: xor a ld (de),a ; Close option ld a,(V.opt) ; Get option V (TRUE is) cp TRUE call z,TellLabel ; Print label working on pop de ld a,(M.opt) ; Get option (1 is M) cp _S jr z,S.Label ld hl,MAP2lab add hl,de ; Point to second label in line ld a,(hl) cp ' '+1 ; Test valid character jr nc,S.Label ; Yeap ld (hl),0 S.Label: push hl ld de,SYMitem ld b,0 LabelOk: ld a,(de) ; Get character or a ; Test end jr z,GoInsert ; Yeap inc de call TestValid ; Test valid character jr nc,LabelOk ; Yeap sub ' '+1 ; Strip off offset ld c,a ld hl,ASCarray add hl,bc ; Build index ld a,TRUE ld (Access),a ; Indicate global access ld (hl),a ; Indicate character access jr LabelOk GoInsert: call InsertLabel ; Insert label pop hl jp NextLabel ; ; Be verbose - print current label ; TellLabel: push hl ld hl,100 call delay ; Delay 100 ms pop hl ld de,SYMitem call strcn0 ; Print label ld de,$CR call strcn0 ; Set cursor to beginning ret ; ; Process file ; ProcFile: ld hl,NIL ld (DynPtr),hl ; Clear dynamic pointer call Proc$SYM ; Process symbol file call WrtLabels ; Write labels to file ret ; ; Init ASCII field ; IniASC: ld a,FALSE ld (Access),a ; Clear access ld hl,ASCarray ; Init array ld b,ASCitm ; Get length ..iniASC: ld (hl),a ; Clear field inc hl djnz ..iniASC ret ; ; Test valid character - C reset says yes ; TestValid: push bc push hl call IsValid ; Test it pop hl pop bc ret ; ; Test valid character - C reset says yes ; IsValid: call toupper ; Convert to upper case on request ld b,ValLen/2 ; Init count ld hl,ValTab ; Point to table Validate: cp (hl) ; Test lower limit ccf ret nc ; Out of range inc hl cp (hl) ; Test upper limit ret c ; Within range inc hl djnz Validate or a ; Not in table, invalid ret ; ; Convert character in Accu to upper case on request ; toupper: ld b,a ; Save character ld a,(F.opt) ; Test option F (TRUE is) cp TRUE ld a,b call z,uppcon ; Convert to upper case if so ret ; ; Test character already in list - C set says yes ; isinlist: push bc push hl ld hl,ListArray-1 ; Init list pointer jr trylist cmplist: cp (hl) ; Compare jr z,listmatch ; Invalid if known trylist: dec c ; Test done jr z,listfound ; Yeap inc hl ; Advance to next new one inc hl jr cmplist listmatch: push af call conout ; Put to console ld de,$INLIST call strcn0 ; Tell already in list pop af scf ; Set invalid listfound: pop hl pop bc ret ; ; Exchange special character(s) ; ExSpChar: ld a,(SpcChrCnt) ; Get special character count ld b,a ld c,1 ; Init count ld hl,ListArray ; Init list pointer SpCharIn: ld de,$OLD call strcn0 ; Tell old ld a,(hl) call conout ; Put old to console ld de,$NEW call strcn0 ; Tell new call uppin ; Get character push af call crlf ; Give new line pop af call TestValid ; Test valid character jr nc,SpCharVal ; Yeap ld de,$ILLEGAL call strcn0 ; Tell illegal jr SpCharIn ; Retry SpCharVal: call isinlist ; Test character already in list jr c,SpCharIn ; Yeap inc hl ld (hl),a ; Store new character inc hl ; Update pointer inc c ; Update count djnz SpCharIn ; Go thru ret ; ; Change special character ; DoChange: push hl ld a,(SpcChrCnt) ; Get special character count ld b,a ld a,(hl) ; Get old character ld hl,ListArray ; Init list pointer ChangeLoop: cp (hl) ; Find characater inc hl jr z,RealChange ; Got it inc hl djnz ChangeLoop pop hl ret RealChange: ld a,(hl) ; Get new character pop hl ld (hl),a ; Overwrite old one ret ; ; Re-read symbol file swapping invalid characters ; ReadSwap: ld de,$REREAD call strcn0 ; Tell re-reading file ld de,Fout+.fdrv call filnam ; Print name of file call crlf ; Give new lines call crlf ld de,FCB ld hl,Fout ld bc,.fdrv+.fname+.fext ldir ; Save source file ld de,Fout+.fdrv+.fname ld hl,$$BAK ld bc,.fext ldir ; Set extension .BAK call PrepOutfile ; Prepare output file call OpenSource ; Re-open source file ld hl,NIL ld (DynPtr),hl ; Clear dynamic pointer ld hl,0 ld (SymCount),hl ; Clear symbol count ld a,TRUE ld (ChgFlag),a ; Indicate special changed NextInFile: ld de,FileLine+1 call RdSFline ; Get line from disk jr c,EndOfFile ; End of file ex de,hl ld de,$HEXbuf ld bc,HEXLEN ldir ; Unpack address inc hl ld de,SYMitem call @asstr ; Unpack remainder of line ld hl,SYMitem NextInLine: ld a,(hl) ; Get from line or a jr z,EndOfLine call TestValid ; Test valid character call c,DoChange ; Nope, swap it inc hl jr NextInLine EndOfLine: call InsertLabel ; Insert label jr NextInFile EndOfFile: call WrtLabels ; Write labels to file call closef ; Close file ld de,FCB call delete ; Delete file ex de,hl ld de,Fout+DIRlen call UnpackFile ; Unpack file ld de,Fout call rename ; Rename file ld hl,FCB UnpackFile: ld bc,DIRlen ldir ; Unpack file ret ; ; Process invalid characters ; ProcInvalid: call InitMem ; Init heap ld de,0 ; Reset index/count ld hl,ASCarray ; Set pointer ld b,ASCitm ; Set length ld c,'!' ; Init first character InvalidLoop: ld a,(hl) ; Get table state cp TRUE ; Test access jr nz,InvNotActive ; Nope push hl ld hl,ListArray ; Init list pointer add hl,de ; Build address into table add hl,de ld (hl),c ; Store character pop hl inc de InvNotActive: inc c ; Advance character inc hl ; Advance pointer djnz InvalidLoop ; Go thru the list ld a,e ; Get count ld (SpcChrCnt),a ; Save dec a ld de,$WARN.ONE jr z,TellInvalid ; Only one special character ld de,$WARN.MORE.1 call strcn0 ; Tell warning ld hl,(SpcChrCnt) ; Get special character count ld h,0 call PrDec ; Print count ld de,$WARN.MORE.2 TellInvalid: call strcn0 ; Tell invalid for DASM ld de,$DETAIL call strcn0 ; Tell detail ld a,(SpcChrCnt) ; Get special character count ld b,a ld hl,ListArray ; Init list pointer ld de,$ILLCHAR TellInvLoop: call strcn0 ; Tell character ld a,(hl) ; Get it call conout ; Put to console call crlf ; Give new line inc hl ; Advance list pointer inc hl djnz TellInvLoop ld de,$XCHG call strcn0 ; Ask for exchange WtExchange: call conino ; Get input call uppcon ; Convert to upper case cp 'N' jr z,NoExchange cp 'Y' jr nz,WtExchange NoExchange: push af call conout ; Put to console call crlf ; Give new line pop af cp 'Y' ; Test to be exchanged jr nz,EndExchange ; Nope call ExSpChar ; Exchange character(s) call ReadSwap EndExchange: call crlf ; Give new line ret ; ; %%%%%%%%%%%%%%%%%%%%%%%%% ; %%% Start the program %%% ; %%%%%%%%%%%%%%%%%%%%%%%%% ; SYMDASM: ld sp,(TPAtop) ; Load stack call InitMem ; Init heap call PrepEnv ; Parse command line and prepare files call IniASC ; Init ASCII field call clrscr ; Clear screen ld de,$START call strfile ; Tell starting ld hl,0 ld (SymCount),hl ; Clear symbol count call ProcFile ; Process file ld hl,(SymCount) ; Get symbol count call PrDec ; Print number ld de,$SYMFND call strfile ; Tell symbols in file call closef ; Close file ld hl,(SymCount) ; Get symbol count ld a,l ; Test any or h jr nz,Success ; Yeap call delete ; Delete file ld de,$NOCREC call strcn0 ; Tell no file generated jp OS Success: ld a,(Access) cp TRUE ; Test access call z,ProcInvalid ; Yeap, process it ld de,$DONE call strcn0 ; Tell ready ld de,Fout+.fdrv call filnam ; Print name of file call crlf ; Give new line jp OS ; ; Give message and print name of file ; strfile: call strcn0 ; Give message ld de,FCB+.fdrv call filnam ; Print name of file call crlf ; Give new lines call crlf ret ; ; Print 16 bit value as decimal number ; PrDec: ld de,$DECNUM ld b,null call decout ; Convert hex to decimal ld de,$DECNUM call strcn0 ; Tell number ret ; ; Get line from disk, preserving registers ; RdSFline: push bc push de push hl dec de ; Fix for length position call RdFline ; Get line from disk pop hl pop de pop bc ret ; ; Get line from disk ; RdFline: ld b,null ; Set end character call getlnf ; Get line from disk ret c ; End of file sub 1 ; Fix length ld l,a ld h,0 add hl,de ; Point to end of buffer ld (hl),null ; Close line ret ; ; Test character hex - C set says no ; isHEX: call uppcon ; Convert to upper case cp '0' ; Test range ret c cp 'F'+1 ccf ret c cp 'A' ret nc cp '9'+1 ccf ret ; ; Init heap ; InitMem: ld hl,($memry) ; Get start of heap ld (Heap),hl ; Store it ret ; ; Allocate new memory into ^DE ; malloc: ld de,(Heap) ; Get current heap ld hl,ITEMlen add hl,de ; Build new top ld (Heap),hl ld bc,(TPAtop) dec b dec b or a sbc hl,bc ; Verify enough memory ret c ld de,$MEMOVL call strcn0 ; Tell not enough memory jp OS ; ; Compare items ^HL:^DE - Z set says match ; CmpLabel: push hl push de CompNxt: ld a,(de) ; Get character or a ; Test end jr z,End1st ; Yeap, verify real end ld a,(hl) ; Get character from other or a jr z,EndOf2nd ; If end, no match ld a,(de) cp (hl) ; Compare inc hl inc de jr z,CompNxt ; Go on if match pop de pop hl ret EndOf2nd: pop de pop hl ld a,1 or a ; Set no match ret End1st: ld a,(hl) ; Verify end of other string or a pop de pop hl ret z ; Ok ld a,1 or a ; Set no match ret ; ; Open source file ; OpenSource: ld hl,DMA ld (rdbuf),hl ; Set buffer ld a,reclng ld (rdbfp),a ; Force read ld de,FCB ld (rdfcb),de ; Set FCB call open ; Open file ret dseg ; ; Valid character range table ; ValTab: db ' '+1,'0' db '9'+1,'A' db 'Z'+1,'~'+1 ValLen equ $-ValTab $HELP: db cr,lf db 'Convert symbol table file generated by L80 compatible linker' db cr,lf db 'into a sorted form readable by DASM' db cr,lf,lf db 'Requires file name - Recall it' db cr,lf db 'May enter filename without extension, defaults to .SYM' db cr,lf db 'Extension decides whether a .SYM or .MAP file is requested' db cr,lf db 'Type SYMDASM file{.ext} {/opt}',tab,'/M requests .MAP file' db cr,lf db tab,tab,tab,tab,'/F requests alternative format' db cr,lf db tab,tab,tab,tab,'/V requests verbose mode' db cr,lf,null $ILLOPT: db cr,lf db 'Illegal option - Select M, F or V :' db null $ILLEXT: db cr,lf,'Illegal extension ' $EXT: db ' - must be either ' $$MAP: db 'MAP or ' $$SYM: db 'SYM - Recall' db cr,lf,null $MEMOVL: db 'ERROR: Memory overflow' db cr,lf,null $DECNUM: db '65535',null $LAB.F: db ':',tab,tab,';@ ',null $START: db 'Start sorting from file ',null $SYMFND: db ' symbols found in file ',null $NOCREC: db 'No output file generated' db cr,lf,null $DONE: db '... done, result in file ',null $FILE: db cr,lf,'File ',null $NOTFOUND: db ' does not exist - Recall it' db cr,lf,null $UNKNOWN: db 'Found unknown label (' $$UNKNOWN: db '????) in file ',null $ILLFORM: db 'Illegal file format of ',null $ILLPC: db cr,lf db '(Found in PC, it''s not HEX)' db cr,lf,null $memry: dw 0 Heap: dw 0 $ILLGENSYM: db 'Illegal generic symbol table' db cr,lf db 'Symbol multiple defined in original file' db cr,lf,null $ILLFIXSYM: db 'Illegal fixed symbol table' db cr,lf db 'Symbol multiple defined after substitution' db cr,lf,null $RECALL: db 'Check condition - Recall' db cr,lf,null $WARN.ONE: db 'WARNING: Found 1 character which is illegal for DASM' db cr,lf,null $WARN.MORE.1: db 'WARNING: Found ',null $WARN.MORE.2: db ' characters which are illegal for DASM' db cr,lf,null $DETAIL: db 'In detail:' db cr,lf,null $ILLCHAR: db 'Illegal character -> ',null $XCHG: db cr,lf db 'Should character(s) be exchanged [Y/N] ',null $ILLEGAL: db 'Illegal' db cr,lf,null $OLD: db 'Old -> ',null $NEW: db ' -> new ',null $INLIST: db ' already in list' db cr,lf,null $REREAD: db cr,lf db 'Re-reading file ',null $CR: db cr,null SpcChrCnt: ; Special character count db 0 SYMitem: ; Symbol item ds SYMlen ChgFlag: ; Special character change flag db FALSE FileLine: db LINLEN ds LINLEN+1 $HEXbuf: db '09AF',null ASCarray: ds ASCitm ListArray: ; List pointer ds 2*ASCitm $$SSY: db 'SSY' $$BAK: db 'BAK' M.opt: ; Type option (1 is M) db _S Fout: ds .fdrv+.fname+.fext ds 24 WrDMA: ; Output buffer ds reclng SymCount: ; Symbol count dw 0 V.opt: ; Option V (TRUE is) db FALSE F.opt: ; Option F (TRUE is) db FALSE Access: ; ASCII flag db FALSE DynPtr: ; Dynamic pointer dw NIL end SYMDASM