subttl kmain/mac main parser and initialization routin cseg extrn oldstk,scrtch,high,cmdlin,stack,stjump,lab extrn rftab,rdtab,rtype,abort,parity,port,fcb,baud extrn wdlen,baudtb,parsetb,byte,initcm,init,state public mjump,rdjump,rfjump,sets,setr,setf,setb,setp,setc public setw,seter,setl extrn lrecl,filnam,paraml,work ; ; macros ; ; prmes to display a message stored by mssg ; call prmes lab ; prmes macro lab .xlist extrn m_&lab,l_&lab push hl push bc ld hl,m_&lab ld bc,(l_&lab) ld c,13 ld a,9 rst 8 pop bc pop hl .list endm ; ; jumptb jump according to a jump table ; call jumptb table,code ; where table is the address of the table ; and code is a one-byte code ; jumptb macro table,code .xlist local $1 ld hl,table ld bc,(code) ld b,c ld a,28 ;lookup call rst 8 ;dos jr z,$1 ;no error ld hl,table+1 ;get abort address (first entry) $1: jp (hl) .list endm ; ; main entry save usefull registers ; start: ld (oldstk),sp ;save stack ld (scrtch),bc ;first byte after pgm ld (high),de ;high memory ld (cmdlin),hl ;command line ld sp,stack ;new stack ; ; main parsing routine ; will respond to the following syntax : ; KERMIT {S,F=file,B=baud,P=par,W=word,C=channel} ; update {L=lrecl} 85.09.19 ; iparse: ld e,0 ;init for first call nxtfld ld hl,(cmdlin) ;get command line ld c,(hl) ;maximum length to parse inc hl ;points to first byte i0: ld a,(hl) ;get first byte cp ' ' ;white space ? jr z,i1 ;yes, now find { dec c ;decrement length to parse inc hl ;update pointer ld a,c ;length in a cp 0 ;is it null ? jr nz,i0 ;no, go on jp go ;yes, no parse to be done i1: dec c ;decrement length to parse inc hl ;update pointer ld a,c ;get length in a cp 0 ;is it null ? jp z,go ;nothing to parse ld a,(hl) ;get byte in a cp ' ' ;is it another null ? jp z,i1 ;yes, get one more cp '{' ;is it valid start ? jp nz,seter ;no good dec c ;decrement length inc hl ;update pointer ld a,c ;get length in a cp 0 ;is it null ? jp z,seter ;no good parse: call nxtfld ;get next field jp nz,go ;go ! ld a,b ;length of field cp 0 ;is it null ? jp z,seter ;disaster ... call handler ;work with this parameter ld a,c ;length left to parse or a ;is it null ? jp nz,parse ;no, do it again ld a,0FFH ;terminator ? cp d ;in register D jp z,seter ;yes and parse is incomplete jp go ;go ! handler: ld a,(hl) ;get first caracter of field ld (byte),a ;in byte push hl ;save push bc jumptb parsetb,byte ;jump accordingly sets: pop bc pop hl ld a,11 ;open pseudo-state ld (state),a ;set send state ld a,'R' ;read only ld (paraml+6),a ;put fcb in read state ld a,0 ;do not create ld (paraml+9),a ;and do not create ret setr: pop bc pop hl ld a,3 ld (state),a ;set receive state ret setf: pop bc pop hl call nxtfld ;get next field push hl ;save push de push bc push hl ;i will need it twice ld a,b ;get length in a cp 0 ;is it null ? jp z,f0 ;yes error cp 30 ;greater than 30 jp nc,f0 ;yes, error ld de,fcb ;where filaname should be ld c,b ;with length in BC ld b,0 ldir ;move from hl to de ex de,hl ;end of filnam in hl ld (hl),13 ;put in a CR ld (filnam),a ;get filename length in place ld de,filnam ;to filenam inc de ;plus one (first byte is len) pop hl ;from here ld c,a ;length in bc ld b,0 ldir ;move from param list to filnam ex de,hl ;hl points to end ld (hl),13 ;put in a CR pop bc ;restore pop de pop hl ret f0: prmes e4 ;not valid filename jp abort ;end in disaster setp: pop bc pop hl call nxtfld ;get next field ld a,(hl) ;get first byte in a cp 'O' ;is it odd jr nz,p0 ;no ... ld (parity),a ;set in comm buffer ld (init),a ;init flag ret p0: cp 'E' ;is it even ? jr nz,p1 ;no ... ld (parity),a ;set in comm buffer ld (init),a ;init flag ret p1: cp 'N' ;is it none ? jr nz,p2 ;no, error ld (parity),a ;set in comm buffer ld (init),a ;init flag ret p2: prmes e5 ;invalid parity jp abort ;end in disaster setb: pop bc pop hl call nxtfld ;get next field push hl ;save push de push bc ex de,hl ;de=compare string ld hl,baudtb ;baud rate table ld a,49 ;svc scan rst 8 ;dos jr nz,b0 ;not found inc hl ;increment to code inc hl inc hl inc hl ld a,(hl) ;get code in a ld (baud),a ;in comm buffer ld (init),a ;init flag pop bc ;restore pop de pop hl ret b0: prmes e6 ;unsupported baud rate jp abort ;in disaster setw: pop bc pop hl call nxtfld ;get next field ld a,(hl) ;first byte in a cp '7' ;is it 7 jr nz,w0 ;no, try 8 sub '0' ;convert to binary ld (wdlen),a ;in comm buffer ld (init),a ;set init flag ret w0: cp '8' ;is it 8 jr nz,w1 ;no, error ld (wdlen),a ;in comm buffer ld (init),a ;init flag ret w1: prmes e7 ;bad word length jp abort ;disaster setc: pop bc pop hl call nxtfld ;get next field ld a,(hl) ;first byte in a cp 'A' ;is it cnannel A ? jr nz,c0 ;no, try B ld (port),a ;in comm buffer ld (init),a ;init flag ret c0: cp 'B' ;is it B jr nz,c1 ;no, error ld (port),a ;in comm buffer ld (init),a ;init flag ret c1: prmes e8 ;invalid channel jp abort ;disaster seter: pop bc pop hl prmes e9 ;invalid parameter prmes u0 ;usage is... jp abort ;disaster setl: pop bc ;restore pop hl call nxtfld ;get record length push hl ;save push bc push de ld de,work ;to store value and padd ld a,b ;get length cp 6 ;maximum lebgth + 1 jp nc,seter ;no good ... bye l0: cp 5 ;maximum length jr z,l1 ;finished moving inc a ;increase length inc de ;and pointer jr l0 l1: ld c,b ;get length in bc ld b,0 ldir ;move to work+(5-bc) ld hl,work ;get hl to point correctly ld b,1 ;code to convert to bin ld a,21 ;BINDEC svc rst 8 ;dos ld a,e ;get binary value ld (lrecl),a ;save in fcb pop de ;restore pop bc pop hl ret nxtfld: ld d,0 ;initialize de to e add hl,de ;add to hl - where to start ld de,lab ;list address block ld a,46 ;parse svc rst 8 ;dos ret go: call initcm ;initialize comm channel prmes 00 ;now say hello ; here is the main jump, every routine ends here ; mjump: jumptb stjump,state ; ; ; ; and this is the main receive file jump ; rfjump: jumptb rftab,rtype ; ; and the main receive data jump ; rdjump: jumptb rdtab,rtype ; end start