From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/MACRO.ASM | 445 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 v4.0/src/DOS/MACRO.ASM (limited to 'v4.0/src/DOS/MACRO.ASM') diff --git a/v4.0/src/DOS/MACRO.ASM b/v4.0/src/DOS/MACRO.ASM new file mode 100644 index 0000000..dea0771 --- /dev/null +++ b/v4.0/src/DOS/MACRO.ASM @@ -0,0 +1,445 @@ +; SCCSID = @(#)macro.asm 1.2 85/07/11 +TITLE MACRO - Pathname and macro related internal routines +NAME MACRO +; +; $AssignOper written +; FIND_DPB written +; InitCDS written +; $UserOper written +; GetVisDrv written +; GetThisDrv written +; GetCDSFromDrv written +; +; Revision history: +; +; Created: MZ 4 April 1983 +; MZ 18 April 1983 Make TransFCB handle extended FCBs +; AR 2 June 1983 Define/Delete macro for NET redir. +; MZ 3 Nov 83 Fix InitCDS to reset length to 2 +; MZ 4 Nov 83 Fix NetAssign to use STRLEN only +; MZ 18 Nov 83 Rewrite string processing for subtree +; aliasing. +; +; MSDOS performs several types of name translation. First, we maintain for +; each valid drive letter the text of the current directory on that drive. +; For invalid drive letters, there is no current directory so we pretend to +; be at the root. A current directory is either the raw local directory +; (consisting of drive:\path) or a local network directory (consisting of +; \\machine\path. There is a limit on the point to which a .. is allowed. +; +; Given a path, MSDOS will transform this into a real from-the-root path +; without . or .. entries. Any component that is > 8.3 is truncated to +; this and all * are expanded into ?'s. +; +; The second part of name translation involves subtree aliasing. A list of +; subtree pairs is maintained by the external utility SUBST. The results of +; the previous 'canonicalization' are then examined to see if any of the +; subtree pairs is a prefix of the user path. If so, then this prefix is +; replaced with the other subtree in the pair. +; +; A third part involves mapping this "real" path into a "physical" path. A +; list of drive/subtree pairs are maintained by the external utility JOIN. +; The output of the previous translation is examined to see if any of the +; subtrees in this list are a prefix of the string. If so, then the prefix +; is replaced by the appropriate drive letter. In this manner, we can +; 'mount' one device under another. +; +; The final form of name translation involves the mapping of a user's +; logical drive number into the internal physical drive. This is +; accomplished by converting the drive number into letter:CON, performing +; the above translation and then converting the character back into a drive +; number. +; +; curdir_list STRUC +; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir +; curdir_flags DW ? ; various flags +; curdir_devptr DD ? ; local pointer to DPB or net device +; curdir_ID DW ? ; cluster of current dir (net ID) +; DW ? +; curdir_end DW ? ; end of assignment +; curdir_list ENDS +; curdir_netID EQU DWORD PTR curdir_ID +; ;Flag word masks +; curdir_isnet EQU 1000000000000000B +; curdir_inuse EQU 0100000000000000B +; +; There are two main entry points: TransPath and TransFCB. TransPath will +; take a path and form the real text of the pathname with all . and .. +; removed. TransFCB will translate an FCB into a path and then invoke +; TransPath. +; +; Implementation note: CURDIR_End field points to the point in the text +; string where the user may back up to via .. It is the location of a +; separator character. For the root, it points at the leading /. For net +; assignments it points at the end (nul) of the initial assignment: +; A:/ \\foo\bar \\foo\bar\blech\bozo +; ^ ^ ^ +; A: -> d: /path/ path/ text +; +; A000 version 4.00 Jan. 1988 + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + +Installed = TRUE + + I_need ThisCDS,DWORD ; pointer to CDS used + I_need CDSAddr,DWORD ; pointer to CDS table + I_need CDSCount,BYTE ; number of CDS entries + I_need CurDrv,BYTE ; current macro assignment (old + ; current drive) + I_need NUMIO,BYTE ; Number of physical drives + I_need fSharing,BYTE ; TRUE => no redirection allowed + I_need DummyCDS,80h ; buffer for dummy cds + I_need DIFFNAM,BYTE ; flag for MyName being set + I_need MYNAME,16 ; machine name + I_need MYNUM,WORD ; machine number + I_need DPBHEAD,DWORD ; beginning of DPB chain + I_need EXTERR_LOCUS,BYTE ; Extended Error Locus + I_need DrvErr,BYTE ; drive error + +BREAK <$AssignOper -- Set up a Macro> + +; Inputs: +; AL = 00 get assign mode (ReturnMode) +; AL = 01 set assign mode (SetMode) +; AL = 02 get attach list entry (GetAsgList) +; AL = 03 Define Macro (attch start) +; BL = Macro type +; = 0 alias +; = 1 file/device +; = 2 drive +; = 3 Char device -> network +; = 4 File device -> network +; DS:SI -> ASCIZ source name +; ES:DI -> ASCIZ destination name +; AL = 04 Cancel Macro +; DS:SI -> ASCIZ source name +; AL = 05 Modified get attach list entry +; AL = 06 Get ifsfunc item +; AL = 07 set in_use of a drive's CDS +; DL = drive number, 0=default 0=A,, +; AL = 08 reset in_use of a drive's CDS +; DL = drive number, 0=A, 1=B,,, +; Function: +; Do macro stuff +; Returns: +; Std Xenix style error return + + procedure $AssignOper,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + CMP AL,7 ; set in_use ? ;AN000; + JNZ chk08 ; no ;AN000; +srinuse: ;AN000; + PUSH AX ; save al ;AN000; + MOV AL,DL ; AL= drive id ;AN000; + CALL GetCDSFromDrv ; ds:si -> cds ;AN000; + POP AX ; ;AN000; + JC baddrv ; bad drive ;AN000; + CMP WORD PTR [SI.curdir_devptr],0 ; dpb ptr =0 ? ;AN000; + JZ baddrv ; no ;AN000; + CMP AL,7 ; set ? ;AN000; + JNZ resetdrv ; no ;AN000; + OR [SI.curdir_flags],curdir_inuse ; set in_use ;AN000; + JMP SHORT okdone ; ;AN000; +resetdrv: ;AN000; + AND [SI.curdir_flags],NOT curdir_inuse ; reset in_use ;AN000; + JMP SHORT okdone ; ;AN000; +baddrv: ;AN000; + MOV AX,error_invalid_drive ; error ;AN000; + JMP SHORT ASS_ERR ; ;AN000; +chk08: ;AN000; + CMP AL,8 ; reset inuse ? ;AN000; + JZ srinuse ; yes ;AN000; + + IF NOT INSTALLED + transfer NET_ASSOPER + ELSE + PUSH AX + MOV AX,(multnet SHL 8) OR 30 + INT 2FH + POP BX ; Don't zap error code in AX + JC ASS_ERR +okdone: + transfer SYS_RET_OK + +ASS_ERR: + transfer SYS_RET_ERR + ENDIF + +EndProc $AssignOper + +Break + +; Inputs: AL has drive number A = 0 +; Outputs: Carry Set +; No DPB for this drive number +; Carry Clear +; DS:SI points to DPB for drive +; registers modified: DS,SI +Procedure FIND_DPB,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + LDS SI,[DPBHEAD] +DPB_LOOP: + CMP SI,-1 + JZ NO_DPB + CMP AL,[SI.dpb_drive] + retz ; Carry clear + LDS SI,[SI.dpb_next_dpb] + JMP DPB_LOOP + +NO_DPB: + STC + return +EndProc FIND_DPB + +Break + +; Inputs: ThisCDS points to CDS +; AL has uppercase drive letter +; Outputs: ThisCDS is now empty +; ES:DI point to CDS +; Carry set if no DPB associated with drive +; registers modified: AH,ES,DI +Procedure InitCDS,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AH,':' + PUSH AX + SUB AL,"A"-1 ; A = 1 + CMP [NUMIO],AL + POP AX + LES DI,[THISCDS] + MOV ES:[DI.curdir_flags],0 ; "free" CDS + JB RET_OK ; Drive does not map a physical drive + MOV WORD PTR ES:[DI.curdir_text],AX + PUSH AX + MOV AX,"\" + MOV WORD PTR ES:[DI.curdir_text+2],AX ; NUL terminate + POP AX + OR ES:[DI.curdir_flags],curdir_inuse + MOV ES:[DI.curdir_END],2 ; MZ 3 Nov 83 + MOV ES:[DI.curdir_ID],0 + MOV ES:[DI.curdir_ID+2],0 + PUSH AX + PUSH DS + PUSH SI + SUB AL,"A" ; A = 0 + invoke FIND_DPB + JC PRET ; OOOOPPPPPSSSS!!!! + MOV WORD PTR ES:[DI.curdir_devptr],SI + MOV WORD PTR ES:[DI.curdir_devptr+2],DS +PRET: + POP SI + POP DS + POP AX +RET_OK: return +EndProc InitCDS + +Break <$UserOper - get/set current user ID (for net)> + +; +; $UserOper - retrieve or initiate a user id string. MSDOS will only +; maintain this string and do no verifications. +; +; Inputs: AL has function type (0-get 1-set 2-printer-set 3-printer-get +; 4-printer-set-flags,5-printer-get-flags) +; DS:DX is user string pointer (calls 1,2) +; ES:DI is user buffer (call 3) +; BX is assign index (calls 2,3,4,5) +; CX is user number (call 1) +; DX is flag word (call 4) +; Outputs: If AL = 0 then the current user string is written to DS:DX +; and user CX is set to the user number +; If AL = 3 then CX bytes have been put at input ES:DI +; If AL = 5 then DX is flag word + +Procedure $UserOper,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + PUSH AX + SUB AL,1 ; quick dispatch on 0,1 + POP AX + JB UserGet ; return to user the string + JZ UserSet ; set the current user + CMP AL,5 ; test for 2,3,4 or 5 + JBE UserPrint ; yep + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_Invalid_Function ; not 0,1,2,3 + +UserGet: +; Transfer MYNAME to DS:DX +; Set Return CX to MYNUM + PUSH DS ; switch registers + POP ES + MOV DI,DX ; destination + MOV CX,[MYNUM] ; Get number + invoke get_user_stack + MOV [SI.User_CX],CX ; Set number return + Context DS ; point to DOSGroup +ASSUME DS:DOSGROUP + MOV SI,OFFSET DOSGroup:MyName ; point source to user string +UserMove: +ASSUME DS:NOTHING + MOV CX,15 + REP MOVSB ; blam. + XOR AX,AX ; 16th byte is 0 + STOSB +UserBye: + transfer sys_ret_ok ; no errors here + +UserSet: +ASSUME DS:NOTHING +; Transfer DS:DX to MYNAME +; CX to MYNUM + MOV [MYNUM],CX + MOV SI,DX ; user space has source + Context ES + MOV DI,OFFSET DOSGroup:MyName ; point dest to user string + INC [DiffNam] ; signal change + JMP UserMove + +UserPrint: + ASSUME ES:NOTHING +IF NOT Installed + transfer PRINTER_GETSET_STRING +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 31 + INT 2FH + POP DX ; Clean stack + JNC OKPA + transfer SYS_RET_ERR + +OKPA: + transfer SYS_RET_OK +ENDIF + +EndProc $UserOper + +Break + +; +; GetVisDrv - correctly map non-spliced inuse drives +; +; Inputs: AL has drive identifier (0=default) +; Outputs: Carry Set - invalid drive/macro +; Carry Clear - AL has physical drive (0=A) +; ThisCDS points to CDS +; Registers modified: AL + +Procedure GetVisDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + CALL GetThisDrv ; get inuse drive + retc + SaveReg + LDS SI,ThisCDS + TEST [SI].curdir_flags,curdir_splice + RestoreReg + retz ; if not spliced, return OK + MOV [DrvErr],error_invalid_drive ;IFS. ;AN000; + STC ; signal error + return +EndProc GetVisDrv + +Break + +; +; GetThisDrv - look through a set of macros and return the current drive and +; macro pointer +; +; Inputs: AL has drive identifier (1=A, 0=default) +; Outputs: +; Carry Set - invalid drive/macro +; Carry Clear - AL has physical drive (0=A) +; ThisCDS points to macro +; Registers modified: AL + +Procedure GetThisDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + OR AL,AL ; are we using default drive? + JNZ GetMap ; no, go get the CDS pointers + MOV AL,[CurDrv] ; get the current drive + INC AL ; Counteract next instruction +GetMap: + DEC AL ; 0 = A + SaveReg ; save world + mov [EXTERR_LOCUS],errLOC_Disk + TEST fSharing,-1 ; Logical or Physical? + JZ Not_SRVC ; Logical + SaveReg + MOV WORD PTR ThisCDS,OFFSET DOSGroup:DummyCDS + MOV WORD PTR ThisCDS+2,CS ; ThisCDS = &DummyCDS; + ADD AL,'A' + CALL InitCDS ; InitCDS(c); + TEST ES:[DI.curdir_flags],curdir_inuse ; Clears carry + RestoreReg + JZ GetBerr ; Not a physical drive. + JMP SHORT GetBye ; carry clear + +Not_SRVC: + invoke GetCDSFromDrv + JC GetBerr2 ; Unassigned CDS -> return error already set + TEST [SI.curdir_flags],curdir_inuse ; Clears Carry + JNZ GetBye ; carry clear +GetBerr: + MOV AL,error_not_DOS_disk ;AN000;IFS. Formatted IFS drive + CMP WORD PTR [SI.curdir_devptr],0 ;AN000;IFS. dpb ptr =0 ? + JNZ notfat ;AN000;IFS. no +GetBerr2: + MOV AL,error_invalid_drive ;AN000;;IFS. invalid FAT drive +notfat: ;AN000; + MOV [DrvErr],AL ;AN000;;IFS. save this for IOCTL + mov [EXTERR_LOCUS],errLOC_UNK + STC +GetBye: RestoreReg ; restore world + return +EndProc GetThisDrv + +Break + +; +; GetCDSFromDrv - given a physical drive number, convert it to a CDS +; pointer, returning an error if the drive number is greater than the +; number of CDS's +; +; Inputs: AL is physical unit # A=0... +; Outputs: Carry Set if Bad Drive +; Carry Clear +; DS:SI -> CDS +; [THISCDS] = DS:SI +; Registers modified: DS,SI + +Procedure GetCDSFromDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + CMP AL,[CDSCount] ; is this a valid designator + JB GetCDS ; yes, go get the macro + STC ; signal error + return ; bye +GetCDS: + SaveReg + LDS SI,[CDSAddr] ; get pointer to table + MOV BL,SIZE CurDir_list ; size in convenient spot + MUL BL ; get net offset + ADD SI,AX ; convert to true pointer + MOV WORD PTR [ThisCDS],SI ; store convenient offset + MOV WORD PTR [ThisCDS+2],DS ; store convenient segment + RestoreReg + CLC ; no error + return ; bye! +EndProc GetCDSFromDrv + +CODE ends +END -- cgit v1.2.3