$title ('MP/M 1.1 Command Line Interpreter') name cli cseg ;cli: ;do; ;/* ; Copyright (C) 1979,1980 ; Digital Research ; P.O. Box 579 ; Pacific Grove, CA 93950 ; ; Revised: ; 18 Jan 80 by Thomas Rolander ;*/ ;$include (common.lit) ;$nolist ;$include (proces.lit) ;$nolist ;$include (queue.lit) ;$nolist ;$include (fcb.lit) ;$nolist ;$include (xdos.lit) ;$nolist ;$include (memmgr.lit) ;$nolist ;$include (memmgr.ext) ;$nolist ;$include (xdos.ext) ;$nolist ;$include (bdos.ext) ;$nolist ;$include (bdosi.ext) ;$nolist ;$include (datapg.ext) ;$nolist ; declare stktbl (1) structure (loc (10) address) external; extrn stktbl ; declare pdtbl (1) structure (process$descriptor) external; extrn pdtbl ; declare console$attached (1) address external; extrn cnsatt ; declare rlr address external; extrn rlr ; declare rlrpd based rlr process$descriptor; ; assign: extrn assign ; procedure (nameadr) byte external; ; declare nameadr address; ; end assign; ; dispatch: extrn dispatch ; procedure external; ; end dispatch; ; parsefilename: extrn parsefilename ; procedure (pcb$address) address external; ; declare pcb$address address; ; end paresefilename; ; makeq: extrn makeq ; procedure (qcbadr) byte external; ; declare qcbadr address; ; end makeq; ; openq: extrn openq ; procedure (uqcbadr) byte external; ; declare uqcbadr address; ; end openq; ; readq: extrn readq ; procedure (uqcbadr) byte external; ; declare uqcbadr address; ; end readq; ; cwriteq: extrn cwriteq ; procedure (uqcbadr) byte external; ; declare uqcbadr address; ; end cwriteq; ; detach: extrn detach ; procedure external; ; end detach; ; xbdos: extrn xbdos ; procedure (func,info) address external; ; declare func byte; ; declare info address; ; end xbdos; ; xdos: extrn xdos ; procedure (func,info) address external; ; declare func byte; ; declare info address; ; end xdos; ; endp: extrn endp ; procedure external; ; end endp; ; absrq: extrn absrq ; procedure (mdadr) byte external; ; declare mdadr address; ; end absrq; ; relrq: extrn relrq ; procedure (mdadr) byte external; ; declare mdadr address; ; end relrq; ; memfr: extrn memfr ; procedure (mdadr) byte external; ; declare mdadr address; ; end memfr; ; printb: extrn printb ; procedure (msgadr); ; declare msgadr address; ; end printb; ; open: extrn open ; procedure (fcbadr) byte; ; declare fcbadr address; ; end open; ; readbf: extrn readbf ; procedure (fcbadr) byte; ; declare fcbadr address; ; end readbf; ; setdma: extrn setdma ; procedure (dmaadr) external; ; declare dmaadr address; ; end setdma; dseg ; declare reserved$for$disk (3) byte; ds 3 ; declare buffer (128) byte; buffer: ds 128 ; declare pname (10) byte initial ( ; 0,' ',0); pname: db 0 db ' ' db 0 ;/* ; CLI Process Data Segment ;*/ ; declare cli$pd process$descriptor public ; initial (0,rtr$status,199,.cli$entrypt, ; 'c'+80h,'li ',0,0ffh,0,0,.buffer,0); clipd: public clipd extrn attchpd dw attchpd ; pl db 0 ; status db 199 ; priority dw clientrypt ; stkptr db 'c'+80H,'li ' ; name db $-$ ; console db 0ffh ; memseg (system) dw $-$ ; b dw $-$ ; thread dw buffer ; disk set DMA db $-$ ; disk select / user code dw $-$ ; dcnt db $-$ ; searchl dw $-$ ; searcha ds 2 ; drvact ds 20 ; registers ds 2 ; scratch ; declare cli$stk (13) address ; initial (restarts,.cli); clistk: dw 0c7c7h,0c7c7h,0c7c7h dw 0c7c7h,0c7c7h,0c7c7h dw 0c7c7h,0c7c7h,0c7c7h dw 0c7c7h,0c7c7h,0c7c7h clientrypt: dw cli ; declare cli$lqcb ; structure (lqueue, ; buf (131) byte) public ; initial (0,'CliQ ',129,1); clilqcb: public clilqcb dw $-$ ; ql db 'CliQ ' ; name dw 129 ; msglen dw 1 ; nmbmsgs dw $-$ ; dqph dw $-$ ; nqph dw $-$ ; mh dw $-$ ; mt dw $-$ ; bh ds 131 ; buf (131) byte ; declare CLIQ userqcbhead ; initial (.cli$lqcb,.field); cliq: dw clilqcb ; pointer dw field ; msgadr ; declare pcb structure ( ; field$adr address, ; fcb$adr address ); pcb: ds 2 ; fieldadr ds 2 ; fcbadr ; declare field (129) byte; field: ds 129 ; declare disk$select byte at (.field); diskselect equ field ; declare console byte at (.field(1)); console equ field+1 ; declare command$tail (1) byte at (.field(2)); commandtail equ field+2 ; declare fcb fcb$descriptor; fcb: db $-$ ; et db ' ' ; fn db ' ' ; ft db $-$ ; ex dw $-$ ; nu db $-$ ; rc ds 16 ; dm db $-$ ; nr ; declare cusp$uqcb userqcb initial ( ; 0,.field,'$$$$$$$$'); cuspuqcb: dw $-$ ; pointer dw field ; msgadr db '$$$$$$$$' ; name ; declare nxt$chr$adr address; nxtchradr: ds 2 ; declare ret byte; ; declare md memory$descriptor; md: db $-$ ; base db $-$ ; size db $-$ ; attrib db $-$ ; bank ; declare pdadr address; pdadr: ds 2 ; declare pd based pdadr process$descriptor; ; declare (base,top) address; base: ds 2 top: ds 2 ; declare (i,j) address; i: ds 2 j: ds 2 ; declare (mask,prl,ok,notdone) byte; mask: ds 1 prl: ds 1 ok: ds 1 notdone: ds 1 ; declare sector$size literally '0080H'; ; declare user$priority literally '200'; ; declare segment$bottom address; segmentbottom: ds 2 ; declare offset address; offset: ds 2 ; declare data$size address; datasize: ds 2 ; declare mem$pointer address; mempointer: ds 2 ; declare instr based mem$pointer byte; ; declare location based mem$pointer address; ; declare array based mem$pointer (1) byte; ; declare loc3 byte at (0003H); loc3 equ 0003h ; declare bitmap$adr address; bitmapadr: ds 2 ; declare bitmap based bitmap$adr (1) byte; ; declare prl$code$adr address; prlcodeadr: ds 2 ; declare prl$code based prl$code$adr (1) byte; ; declare prlen address; prlen: ds 2 cseg ; declare tfcb$default (38) byte data ( tfcbdefault: db 0,' ',' ' db 0,0,0,0 db 0,' ',' ' db 0,0,0,0 db 0,0,0,0,0,0 ; /* setup tfcb: 005CH - 005CH = 0 ; 005DH - 0067H = ' ' ; 0068H - 006BH = 0 ; tfcb+16: 006CH - 006CH = 0 ; 006DH - 0077H = ' ' ; 0078H - 007BH = 0 ; 007CH - 007FH = 0 ; tbuff: 0080H - 0081H = 0 */ plderr: db 'Prg ld err' db '$' abstpana: db 'Abs TPA not free' db '$' insufrm: db 'Reloc seg not free' db '$' badprlhr: db 'Bad PRL hdr rec' db '$' prltype: db 'PRL' comtype: db 'COM' fltypblnk: db 'Blnk file type rqd' db '$' quefull: db 'Queue full' db '$' illegal: db 'Bad entry' db '$' ; pmove: pmove: ; BC = COUNT, DE = SOURCE ADR, HL = DEST ADR ; procedure (n,s$adr,d$adr); ; declare (n,s$adr,d$adr) address; ; declare s based s$adr byte; ; declare d based d$adr byte; ; n = n + 1; ; do while (n := n - 1) <> 0; @38: MOV A,B ORA C RZ ; if s >= 'a' and s <= 'z' LDAX D MOV M,A CPI 'a' JC @2 CPI 'z'+1 JNC @2 ; then d = s and 101$1111b; /* force upper case */ ANI 5FH MOV M,A ; else d = s; @2: ; s$adr = s$adr + 1; INX D ; d$adr = d$adr + 1; INX H ; end; DCX B JMP @38 ; end pmove; ; setup$base$page: setupbasepage: ; procedure; ; /* place a jump to xdos in the top three bytes ; of the memory segment */ ; base, ; mem$pointer = top - 3; LHLD TOP DCX H DCX H DCX H SHLD BASE ; instr = 0C3H; MVI M,0C3H ; mem$pointer = mem$pointer + 1; INX H ; location = .xbdos; ; /* place a jump to the termination procedure (ENDP) ; at the first three bytes of the memory segment */ LXI B,XBDOS MOV M,C INX H MOV M,B ; if (mem$pointer := segment$bottom) <> 0000H then LHLD SEGMENTBOTTOM MOV A,H ORA L JZ @3 ; do; ; instr = 0C3H; MVI M,0C3H ; mem$pointer = mem$pointer + 1; INX H ; location = .endp; LXI B,ENDP MOV M,C INX H MOV M,B ; end; ; /* place a jump to the mem segment top - 3 into @3: ; the normal bdos jump at mem segment 0005H */ ; mem$pointer = segment$bottom + 5; LXI D,5H LHLD SEGMENTBOTTOM DAD D ; instr = 0C3H; MVI M,0C3H ; mem$pointer = mem$pointer + 1; INX H ; location = base; XCHG LHLD BASE XCHG MOV M,E INX H MOV M,D ; end setup$base$page; RET ; parse$command$tail: parsecommandtail: ; procedure; ; call pmove (128-(nxt$chr$adr-.command$tail),nxt$chr$adr, LHLD NXTCHRADR XCHG MOV A,E SUI LOW(COMMANDTAIL) MOV B,A MVI A,80H SUB B LXI B,0014H LHLD PDADR DAD B MOV C,M INX H MOV H,M MOV L,C PUSH H INX H MOV C,A MVI B,0 CALL PMOVE POP H PUSH H ; (mem$pointer := pd.disk$set$dma+1)); ; j = 0; MVI B,0FFH ; do while instr <> 0; @40: INX H INR B MOV A,M ORA A JNZ @40 ; mem$pointer = mem$pointer + 1; ; j = j + 1; ; end; ; mem$pointer = pd.disk$set$dma; POP H ; instr = j; MOV M,B ; pcb.field$adr = nxt$chr$adr; LHLD NXTCHRADR SHLD PCB ; pcb.fcb$adr = segment$bottom + 5CH; LXI D,5CH LHLD SEGMENTBOTTOM DAD D SHLD PCB+2H ; if (nxt$chr$adr := xdos (parse$fname,.pcb)) <> 0FFFFH then LXI B,PCB CALL PARSEFILENAME SHLD NXTCHRADR INX H MOV A,H ORA L RZ ; /* valid first file name in command tail */ ; do; ; if nxt$chr$adr <> 0 then DCX H MOV A,H ORA L RZ ; /* parse second file name in command tail */ ; do; ; pcb.field$adr = nxt$chr$adr + 1; INX H SHLD PCB ; pcb.fcb$adr = segment$bottom + 6CH; LXI D,6CH LHLD SEGMENTBOTTOM DAD D SHLD PCB+2H ; nxt$chr$adr = xdos (parse$fname,.pcb); LXI B,PCB CALL PARSEFILENAME SHLD NXTCHRADR ; end; ; end; ; end parse$command$tail; RET ; relocate: relocate: ; procedure; ; /* offset by base of reloc memseg */ ; offset = md.base; ; /* bitmap directly follows last byte of code */ LDA MD MOV B,A ; bitmap$adr = .prl$code + prlen; LHLD PRLEN XCHG LHLD PRLCODEADR PUSH H DAD D ; prlen = prlen - 1; ; j = 0; ; mask = 80H; ; /* loop through entire bit map */ MVI C,80H ; do i = 0 to prlen; ; B = OFFSET, C = MASK, DE = PRLEN, HL = BITMAPADR ; TOS = PRLCODEADR @42: ; if (bitmap(j) and mask) <> 0 then MOV A,M ANA C XTHL JZ @6 ; /* offset the byte where a bitmap bit is on */ ; do; ; prl$code(i) = prl$code(i) + offset; MOV A,M ADD B MOV M,A ; end; @6: INX H XTHL ; /* move mask bit one position to the right */ ; if (mask := shr(mask,1)) = 0 then MOV A,C RAR MOV C,A JNC @7 ; /* re-initialize mask and get next bitmap byte */ ; do; ; mask = 80H; MVI C,80H ; j = j + 1; INX H ; end; @7: ; end; DCX D MOV A,D ORA E JNZ @42 ; end relocate; POP H RET ; pd$init: pdinit: ; procedure; ; pd.pl = 0; LHLD PDADR XRA A MOV M,A INX H MOV M,A ; pd.status = rtr$status; INX H MOV M,A ; pd.priority = user$priority; INX H MVI M,0C8H XCHG ; pd.stkptr = .stktbl(rlrpd.memseg).loc(18); LXI B,000FH LHLD RLR DAD B MOV A,M LXI B,0014H LXI H,STKTBL-4 INR A @MPM0: DAD B DCR A JNZ @MPM0 XCHG INX H MOV M,E INX H MOV M,D ; call pmove (8,.fcb.fn,.pd.name); LXI B,8H INX H LXI D,FCB+1H CALL PMOVE ; pd.console = rlrpd.console; XCHG LXI B,000EH LHLD RLR DAD B MOV A,M STAX D ; pd.memseg = rlrpd.memseg; INX D INX H MOV A,M STAX D ; segment$bottom = shl(double(md.base),8); LDA MD MOV H,A MVI L,0 SHLD SEGMENTBOTTOM ; pd.disk$set$dma = segment$bottom + 0080H; LXI D,0080H DAD D XCHG LXI B,0014H LHLD PDADR DAD B MOV M,E INX H MOV M,D ; pd.disk$slct = rlrpd.disk$slct; INX H XCHG LXI B,0016H LHLD RLR DAD B MOV A,M STAX D ; end pd$init; RET ; load: load: ; procedure; ; /* obtain proc dscrptr adr from memsegtbl index */ ; pdadr = .pdtbl(rlrpd.memseg); ; /* make dispatch call to force memory selection */ LXI B,0FH LHLD RLR DAD B MOV A,M LXI H,PDTBL-34H LXI B,0034H INR A @MPM1: DAD B DCR A JNZ @MPM1 SHLD PDADR ; ret = xdos (dispatch,0); CALL DISPATCH ; /* initialize process descriptor */ ; call pd$init; CALL PDINIT ; base = segment$bottom + 0100H; LXI D,100H LHLD SEGMENTBOTTOM DAD D SHLD BASE ; prl$code$adr = base; ; /* setup stack */ SHLD PRLCODEADR ; stktbl(pd.memseg).loc(19) = .endp; LXI B,0FH LHLD PDADR DAD B MOV A,M LXI B,0014H LXI H,STKTBL-2 INR A @MPM2: DAD B DCR A JNZ @MPM2 LXI B,ENDP MOV M,C INX H MOV M,B ; stktbl(pd.memseg).loc(18) = base; DCX H DCX H XCHG LHLD BASE XCHG MOV M,D DCX H MOV M,E ; do i = 0 to 8; MVI B,16 @44: ; stktbl(pd.memseg).loc(i) = 0C7C7H; DCX H MVI M,0C7H ; end; DCR B JNZ @44 ; top = segment$bottom + shl(double(md.size),8); LDA MD+1H MOV D,A MVI E,0 LHLD SEGMENTBOTTOM DAD D SHLD TOP ; ok = false; ; notdone = true; ; /* read COM or PRL+bitmap file into memory */ ; do while notdone; @46: ; if base = top then LHLD BASE XCHG LHLD TOP MOV A,E CMP L JNZ @8 MOV A,D CMP H JNZ @8 ; do; ; notdone = false; ; if prl then ok = true; LDA PRL RAR JC @47 ; else ; do; ; call set$dma (.buffer); LXI B,BUFFER CALL SETDMA ; if readbf (.fcb) = 1 then ok = true; LXI B,FCB CALL READBF DCR A JZ @47 JMP @15 ; end; ; end; @8: ; else ; do; ; call set$dma (base); LHLD BASE MOV B,H MOV C,L LXI D,80H DAD D SHLD BASE CALL SETDMA ; base = base + sector$size; ; if (ret := readbf (.fcb)) <> 0 then LXI B,FCB CALL READBF ORA A JZ @46 ; do; ; notdone = false; ; if ret = 1 then ok = true; DCR A JNZ @15 ; end; ; end; ; end; @47: ; /* free drives */ ; ret = xdos (39,0ffffh); mvi c,39 lxi d,0ffffh call xbdos ; if ok then ; /* file read with no errors */ ; do; ; if prl then LDA PRL RAR ; /* page relocatable, do the relocation */ ; do; ; call relocate; CC RELOCATE ; end; ; call pmove (38,.tfcb$default,segment$bottom+5CH); LXI B,26H LXI D,5CH LHLD SEGMENTBOTTOM DAD D LXI D,TFCBDEFAULT CALL PMOVE ; if nxt$chr$adr <> 0 then LHLD NXTCHRADR MOV A,H ORA L ; /* parse the command tail */ ; do; ; call parse$command$tail; CNZ PARSECOMMANDTAIL ; end; ; /* setup base page of memory segment */ ; call setup$base$page; CALL SETUPBASEPAGE ; /* attach the console to the process to be created */ ; console$attached(pd.console) = pdadr; ; /* create - start the process */ LHLD PDADR XCHG LXI H,000EH DAD D MOV C,M MVI B,0 LXI H,cnsatt ; CONSOLEATTACHED DAD B DAD B MOV M,E INX H MOV M,D ; rlrpd.memseg = 0ffh; /* set clipd.memseg back to system */ LXI B,0FH LHLD RLR DAD B MVI M,0FFH ; ret = xdos (create,pdadr); MVI C,90H JMP XDOS ; end; /* of successful file read */ @15: ; else ; /* file read errors */ ; do; ; /* free the allocated memory segment */ ; call mem$fr (.md); LXI B,MD CALL MEMFR ; rlrpd.memseg = 0ffh; /* set clipd.memseg back to system */ LXI B,0FH LHLD RLR DAD B MVI M,0FFH ; call print$b (.( LXI B,plderr JMP PRINTB ; 'Program load error.','$')); ; end; ; end load; ; load$COM: loadcom: ; procedure; ; md.base = 00H; ; /* make absolute memory request */ LXI B,MD XRA A STAX B ; if abs$rq (.md) = 0 then CALL ABSRQ ORA A ; /* successful memory request */ ; do; ; /* load and create process */ ; call load; JZ LOAD ; end; ; else ; /* unsuccessful memory request */ ; do; ; call print$b (.('Absolute ', LXI B,abstpana JMP PRINTB ; 'TPA is not currently available.','$')); ; end; ; end load$COM; ; load$PRL: loadprl: ; procedure; ; ok = false; ; /* read in first record, contains code size ; and data size information */ ; if readbf (.fcb) = 0 then LXI B,FCB CALL READBF ORA A JNZ @21 ; do; ; /* obtain code length */ ; mem$pointer = .buffer(1); LXI H,BUFFER+1H ; prlen = location; ; /* obtain data length */ MOV E,M INX H MOV D,M XCHG SHLD PRLEN ; mem$pointer = mem$pointer + 3; XCHG INX H INX H ; data$size = location; ; /* compute size of memory segment needed */ MOV E,M INX H MOV D,M ; md.size = high(prlen+0FFH) ; + high(data$size+0FFH) ; + shr(prlen,11) ; + 1; LXI B,0FFH LHLD PRLEN DAD B MOV A,H XCHG DAD B ADD H INR A MOV B,A LDA PRLEN+1 ANI 0F8H RRC RRC RRC ADD B STA MD+1H ; /* ignore next sector */ ; if readbf (.fcb) = 0 then LXI B,FCB CALL READBF ORA A JNZ @22 ; do; ; /* make relocatable memory request */ ; if rel$rq(.md) = 0 then LXI B,MD CALL RELRQ ORA A ; /* successful memory request */ ; do; ; /* load and create process */ ; call load; JZ LOAD ; return; ; end; ; else ; /* unsuccessful memory request */ ; do; ; call print$b (.( ; 'Insufficient relocatable memory to', LXI B,insufrm JMP PRINTB ; ' load program.','$')); ; return; ; end; @24: ; end; /* of successful ignore record read */ @22: ; end; /* of successful header record read */ @21: ; call print$b (.( LXI B,badprlhr JMP PRINTB ; 'Bad PRL header record.','$')); ; end load$PRL; ; file$load$execute: fileloadexecute: ; procedure; ; call set$dma (.buffer); LXI B,BUFFER CALL SETDMA ; prl = true; LXI H,PRL MVI M,0FFH ; if fcb.ft(0) = ' ' then LXI H,FCB+9H MOV A,M CPI 20H JNZ @25 ; /* type must be left blank */ ; do; ; call pmove (3,.('PRL'),.fcb.ft); MVI M,'P' INX H MVI M,'R' INX H MVI M,'L' ; /* first try for PRL file */ ; if open (.fcb) = 0FFH then LXI B,FCB CALL OPEN INR A JNZ LOADPRL ; /* PRL file not found, try COM file */ ; do; ; prl = false; LXI H,PRL MVI M,0H ; call pmove (3,.('COM'),.fcb.ft); LXI H,FCB+9H MVI M,'C' INX H MVI M,'O' INX H MVI M,'M' ; if open (.fcb) = 0FFH then LXI B,FCB CALL OPEN INR A JNZ LOADCOM ; /* unsuccessful file open */ ; do; ; call print$b (.( LXI H,FCB+9H @23: DCX H MOV A,M CPI ' ' JZ @23 INX H MVI M,'?' INX H MVI M,'$' LXI B,FCB+1H JMP PRINTB ; 'No such file.','$')); ; return; ; end; ; end; ; /* successful file open */ ; if prl then ; /* relocatable load */ ; do; ; call load$PRL; ; end; ; else ; /* COM file load */ ; do; ; call load$COM; ; end; ; end; /* of blank file type */ @25: ; else ; do; ; /* non-blank file type */ ; call print$b (.( LXI B,fltypblnk JMP PRINTB ; 'File type must not be specified.','$')); ; end; ; end file$load$execute; ; queue$message: queuemessage: ; procedure boolean; ; call pmove (8,.fcb.fn,.cusp$uqcb.name); LXI B,8H LXI H,CUSPUQCB+4H LXI D,FCB+1H CALL PMOVE ; if xdos (open$queue,.cusp$uqcb) = 0 then LXI B,CUSPUQCB CALL openq ORA A MVI A,0 RNZ ; /* queue exists */ ; do; ; call pmove (8,.fcb.fn,.pname(1)); LXI B,8H LXI H,PNAME+1H LXI D,FCB+1H CALL PMOVE ; /* assign the console to the process, if any, ; associated with the queue. a console is ; associated with a process if there is a ; process with the same name as the queue. */ ; ret = assign (.pname); LXI B,PNAME CALL ASSIGN ; if nxt$chr$adr <> 0 then LHLD NXTCHRADR MOV A,H ORA L JZ @32 ; /* copy the command tail */ ; do; ; call pmove (128-(nxt$chr$adr-.command$tail), LHLD NXTCHRADR XCHG MOV A,E INX D SUI LOW(COMMANDTAIL) MOV B,A MVI A,80H SUB B MOV C,A MVI B,0 LXI H,FIELD+2H CALL PMOVE ; nxt$chr$adr+1,.field(2)); ; end; JMP @33 @32: ; else ; /* put a in first field position */ ; do; ; field(2) = 0dh; LXI H,FIELD+2H MVI M,0DH ; end; @33: ; /* conditionally write the message to the queue */ ; if xdos (cond$write$queue,.cusp$uqcb) <> 0 then LXI B,CUSPUQCB CALL cwriteq ORA A ; /* write failed, buffer not available */ ; do; ; call print$b (.( LXI B,quefull CNZ PRINTB ; 'Queue full.','$')); ; end; @34: ; return true; MVI A,0FFH RET ; end; /* of successful queue open */ ; /* queue open failed */ ; return false; ; end queue$message; ;/* ; cli: ;*/ ; cli: cli: ; procedure; ; ret = xdos (make$queue,.cli$lqcb); LXI B,CLILQCB CALL makeq ; do forever; @48: ; ret = xdos (read$queue,.CLIQ); LXI B,CLIQ CALL readq ; pname(0), ; rlrpd.console = console; LDA CONSOLE STA PNAME LHLD RLR XCHG LXI H,000EH DAD D MOV M,A ; rlrpd.disk$slct = disk$select; LXI H,16H DAD D LDA DISKSELECT MOV M,A ; pcb.field$adr = .command$tail; LXI H,COMMANDTAIL SHLD PCB ; pcb.fcb$adr = .fcb; LXI H,FCB SHLD PCB+2H ; if (nxt$chr$adr := xdos (parse$fname,.pcb)) <> 0FFFFH then LXI B,PCB CALL parsefilename SHLD NXTCHRADR INX H MOV A,H ORA L JZ @35 ; /* legitimate queue or file name entered */ ; do; ; fcb.nr = 0; ; /* test for message to be queued */ LXI H,FCB+20H MVI M,0H ; if not queue$message CALL QUEUEMESSAGE RAR JC @37 ; then ; /* file is to be loaded and executed */ ; do; ; call file$load$execute; CALL FILELOADEXECUTE ; end; ; end; JMP @37 @35: ; else ; /* illegitimate queue or file name */ ; do; ; call print$b (.( LXI B,illegal CALL PRINTB ; 'Illegal entry.','$')); ; end; @37: ; /* detach the console from CLI, if still attached */ ; ret = xdos (detach,0); LXI B,CLIPD CALL DETACH ; /* free drives, if still accessed */ ; ret = xdos (39,0ffffh); mvi c,39 lxi d,0ffffh call xbdos ; end; /* of forever */ JMP @48 ; end cli; /* procedure */ ;end cli; END