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/CMD/COMMAND/INIT.ASM | 1685 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1685 insertions(+) create mode 100644 v4.0/src/CMD/COMMAND/INIT.ASM (limited to 'v4.0/src/CMD/COMMAND/INIT.ASM') diff --git a/v4.0/src/CMD/COMMAND/INIT.ASM b/v4.0/src/CMD/COMMAND/INIT.ASM new file mode 100644 index 0000000..3ac84b6 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/INIT.ASM @@ -0,0 +1,1685 @@ + page 80,132 +; SCCSID = @(#)init.asm 4.13 85/11/03 +; SCCSID = @(#)init.asm 4.13 85/11/03 +TITLE COMMAND Initialization + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + include doscntry.inc ;AC000; + INCLUDE comseg.asm + INCLUDE comequ.asm + include resmsg.equ ;AN000; +.list +.cref + + +ENVIRONSIZ EQU 0A0H ;Must agree with values in EVIRONMENT segment +ENVIRONSIZ2 EQU 092H + +ENVBIG EQU 32768 +ENVSML EQU 160 +KOREA_COUNTRY_CODE EQU 82 + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN CONTC:NEAR + EXTRN DskErr:NEAR + EXTRN endinit:near + EXTRN INT_2E:NEAR + EXTRN LODCOM:NEAR + EXTRN RSTACK:WORD +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN abort_char:byte ;AN000; + EXTRN append_state:word ;AN042; + EXTRN BADFAT_OP_SEG:WORD ;AN000; + EXTRN BATCH:WORD + EXTRN COM_FCB1:DWORD + EXTRN COM_FCB2:DWORD + EXTRN COM_PTR:DWORD + EXTRN com_xlat_addr:word + EXTRN COMDRV:BYTE + EXTRN COMPRMT1_SEG:WORD ;AN000; + EXTRN COMPRMT1_SEG2:WORD ;AN000; + EXTRN COMSPEC:BYTE + EXTRN comspec_print:word + EXTRN comspec_end:word + EXTRN cpdrv:byte + EXTRN crit_msg_off:word ;AN000; + EXTRN crit_msg_seg:word ;AN000; + EXTRN critical_msg_start:byte ;AN000; + EXTRN DATARESEND:BYTE ;AC000; + EXTRN dbcs_vector_addr:word ;AN000; + EXTRN DEVE_OP_SEG:WORD ;AN000; + EXTRN DEVE_OP_SEG2:WORD ;AN000; + EXTRN disp_class:byte ;AN000; + EXTRN DRVNUM_OP_SEG:WORD ;AN000; + EXTRN DRVNUM_OP_SEG2:WORD ;AN000; + EXTRN EchoFlag:BYTE + EXTRN ENVIRSEG:WORD + EXTRN ERR15_OP_SEG:WORD ;AN000; + EXTRN ERR15_OP_SEG2:WORD ;AN000; + EXTRN ERR15_OP_SEG3:WORD ;AN000; + EXTRN extended_msg_start:byte ;AN000; + EXTRN extmsgend:byte ;AN000; + EXTRN fFail:BYTE + EXTRN fucase_addr:word ;AN000; + EXTRN InitFlag:BYTE + EXTRN IO_SAVE:WORD + EXTRN LTPA:WORD ;AC000; + EXTRN MEMSIZ:WORD + EXTRN MYSEG:WORD ;AC000; + EXTRN MYSEG1:WORD + EXTRN MYSEG2:WORD + EXTRN nest:word + EXTRN number_subst:byte ;AN000; + EXTRN OldTerm:DWORD + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AN000; +;AD060; EXTRN pars_msg_seg:word ;AN000; + EXTRN parse_msg_start:byte ;AN000; + EXTRN parsemes_ptr:word ;AN000; + EXTRN PERMCOM:BYTE + EXTRN RES_TPA:WORD + EXTRN resmsgend:word ;AN000; + EXTRN RSWITCHAR:BYTE + EXTRN SINGLECOM:WORD + EXTRN SUM:WORD + EXTRN TRNSEG:WORD + EXTRN TrnMvFlg:BYTE +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment + EXTRN ECOMSPEC:BYTE + EXTRN ENVIREND:BYTE + EXTRN PATHSTRING:BYTE +ENVIRONMENT ENDS + +TAIL SEGMENT PUBLIC PARA + EXTRN TRANSTART:WORD +TAIL ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN DATINIT:FAR + EXTRN printf_init:far +TRANCODE ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN TRANSPACEEND:BYTE +TRANSPACE ENDS + +; This is the area used for the autoexec.bat file. BATARENA is a pad for the +; the address mark placed by DOS. + +BATARENA SEGMENT PUBLIC PARA + + ORG 0 + DB 10h DUP (?) ;Pad for memory allocation addr mark + +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;Autoexec.bat segment + + ORG 0 + initbat batchsegment <> ;batch segment + DB 31 DUP (0) ;reserve area for batch file name & pad + +BATSEG ENDS + +; ******************************************************************* +; START OF INIT PORTION +; This code is overlayed the first time the TPA is used. + +INIT SEGMENT PUBLIC PARA + + EXTRN AUTOBAT:byte + EXTRN BADCSPFL:byte + EXTRN bslash:byte + EXTRN CHUCKENV:byte + EXTRN command_c_syn:byte ;AN000; + EXTRN command_d_syn:byte ;AN000; + EXTRN command_e_syn:byte ;AN000; + EXTRN command_f_syn:byte ;AN000; + EXTRN command_m_syn:byte ;AN000; + EXTRN command_p_syn:byte ;AN000; + EXTRN comnd1_syn:word ;AN000; + EXTRN comnd1_addr:dword ;AN000; + EXTRN COMSPECT:byte + EXTRN comspstring:byte + EXTRN dswitch:byte ;AN018; + EXTRN ECOMLOC:word + EXTRN EnvMax:WORD + EXTRN EnvSiz:WORD + EXTRN equalsign:byte + EXTRN eswitch:byte ;AN018; + EXTRN ext_msg:byte ;AN000; + EXTRN fslash:byte + EXTRN INITADD:dword + EXTRN initend:word + EXTRN init_parse:dword ;AN054; + EXTRN INTERNAT_INFO:BYTE ;AN000; 3/3/KK + EXTRN KAUTOBAT:byte ;AN000; 3/3/KK + EXTRN lcasea:byte + EXTRN lcasez:byte + EXTRN num_positionals:word ;AN000; + EXTRN oldenv:word + EXTRN old_parse_ptr:word ;AN057; + EXTRN parse_command:byte ;AN000; + EXTRN pars_msg_off:word ;AN060; + EXTRN pars_msg_seg:word ;AN060; + EXTRN PRDATTM:byte + EXTRN resetenv:word ;AC000; + EXTRN scswitch:byte + EXTRN space:byte + EXTRN triage_add:dword ;AC000; + EXTRN trnsize:word + EXTRN ucasea:byte + EXTRN usedenv:word + + +;AD054; EXTRN SYSPARSE:NEAR + + PUBLIC CONPROC + PUBLIC init_contc_specialcase + +ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP + + ORG 0 +ZERO = $ + + +CONPROC: + MOV SP,OFFSET RESGROUP:RSTACK ; MUST be first instruction + + CALL SYSLOADMSG ;AN000; check dos version + JNC OKDOS ;AN000; if no problem - continue + + mov ax,badver ;AN000; set DOS version + invoke sysdispmsg ;AN000; must be incorrect version + mov ax,es + cmp es:[PDB_Parent_PID],AX ; If command is its own parent, +here: ; loop forever. + Jz here + int 20h ; Otherwise, exit. + +; +; Turn APPEND off during initialization processing +; +okdos: + mov ax,AppendInstall ;AN042; see if append installed + int 2fh ;AN042; + cmp al,0 ;AN042; append installed? + je set_msg_addr ;AN042; no - continue + mov ax,AppendDOS ;AN042; see if append DOS version right + int 2fh ;AN042; + cmp ax,-1 ;AN042; append version correct? + jne set_msg_addr ;AN042; no - continue + mov ax,AppendGetState ;AN042; Get the state of Append + int 2fh ;AN042; + mov append_state,bx ;AN042; save append state + xor bx,bx ;AN042; clear out state + mov ax,AppendSetState ;AN042; Set the state of Append + int 2fh ;AN042; set everything off + +set_msg_addr: +; +; Get addresses of old critical and parse errors and save so they can +; be reset if COMMAND needs to exit +; + + push es ;AN000; SAVE ES DESTROYED BY INT 2FH +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_parse_msg ;AN000; get parse message address + int 2fh ;AN000; + mov cs:pars_msg_seg,es ;AN000; save returned segment + mov cs:pars_msg_off,di ;AN000; save returned offset + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_critical_msg ;AN000; get critical error message address + int 2fh ;AN000; + mov cs:crit_msg_seg,es ;AN000; save returned segment + mov cs:crit_msg_off,di ;AN000; save returned offset + pop es ;AN000; RESTORE ES DESTROYED BY INT 2FH + +; +; Set addresses of critical and parse errors in this level of COMMAND +; + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address + mov di,offset resgroup:parse_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; + call set_parse_2f ;AN060; set parse error address + + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,offset resgroup:critical_msg_start ;AN000; start address + int 2fh ;AN000; + + mov di,offset resgroup:dataresend+15 ;AN000; get address of resident end + mov [resmsgend],di ;AN000; save it + call sysloadmsg ;AN000; load message addresses + call get_msg_ptr ;AN000; set up pointers to some translated chars + mov ah,GetExtCntry ;g get extended country information + mov al,2 ;g minor function - ucase table + mov dx,-1 ;g + mov bx,-1 ;g + mov cx,5 ;g number of bytes we want + mov di,offset resgroup:com_xlat_addr ;g buffer to put address in + int int_command ;g + + mov ah,GetExtCntry ;AN000; get extended country info + mov al,4 ;AN000; get file ucase table + mov dx,-1 ;AN000; + mov bx,-1 ;AN000; + mov cx,5 ;AN000; number of bytes we want + mov di,offset resgroup:fucase_addr ;AN000; buffer for address + int int_command ;AN000; + + mov dx,offset resgroup:transtart+15 ;eg get end of init code + mov cl,4 ;eg change to paragraphs + shr dx,cl ;eg + mov ax,cs ;eg get current segment + add ax,dx ;eg calculate segment of end of init + mov [initend],ax ;eg save this + + push ds ;AN000; + mov ax, (ECS_call SHL 8) OR GetLeadBTbl ;AN000; get dbcs vector + int int_command ;AN000; + mov bx,ds ;AN000; get segment to bx + pop ds ;AN000; + mov dbcs_vector_addr,si ;AN000; save address of + mov dbcs_vector_addr+2,bx ;AN000; dbcs vector + + + mov ax,word ptr ds:[PDB_Parent_PID] ; Init PARENT so we can exit + mov [PARENT],ax ; correctly. + MOV AX,WORD PTR DS:[PDB_Exit] + MOV WORD PTR OldTerm,AX + MOV AX,WORD PTR DS:[PDB_Exit+2] + MOV WORD PTR OldTerm+2,AX + + MOV AX,OFFSET RESGROUP:ENVIREND + 15 + MOV CL,4 ; ax = size of resident part of + SHR AX,CL ; command in paragraphs. Add + MOV CX,CS ; this to CS and you get the + ADD AX,CX ; segment of the TPA. + + MOV [RES_TPA], AX ; Temporarily save the TPA segment + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JNC TPASET ; Memory wrap if carry set + MOV AX, [RES_TPA] +TPASET: + MOV [LTPA],AX ; Good enough for the moment + MOV AX,WORD PTR DS:[PDB_block_len] ; ax = # of paras given to command + + MOV [MYSEG1],DS ; These 3 variables are used as part of + MOV [MYSEG2],DS ; 3 long ptrs that the transient will + MOV [MYSEG],DS ; use to call resident routines. + MOV [MEMSIZ],AX ; Needed for execing other programs +; +; Compute maximum size of environment +; + MOV EnvMax,(Environsiz + 15) / 16 + (EnvMaximum-zero + 15)/16 - 1 +; +; Compute minimum size of environment +; + + MOV EnvSiz, ENVSML / 16 + + MOV DX,OFFSET TRANGROUP:TRANSPACEEND + 15 ; dx = size of transient + MOV CL,4 ; in paragraphs. + SHR DX,CL + mov [trnsize],dx ;eg save size of transient in paragraphs + + SUB AX,DX ; max seg addr - # para's needed for transient + MOV [TRNSEG],AX ; = seg addr to load the transient at. + MOV AX,DS:[PDB_environ] ; ax = environment segment + OR AX,AX ; If there is no environment segment, + JZ BUILDENV ; go compute one. + INC BYTE PTR [CHUCKENV] ; Flag no new ENVIRONSEG to set up + JMP SHORT ENVIRONPASSED ; Otherwise one was passed to us. + +BUILDENV: ; (this label isn't very accurate) + MOV AX,OFFSET RESGROUP:PATHSTRING ; Compute the segment of the + MOV CL,4 ; environment and put it in + SHR AX,CL ; ax. + MOV DX,DS + ADD AX,DX + +ENVIRONPASSED: + MOV [ENVIRSEG],AX ; Save the environment's segment and + MOV ES,AX ; load into es. +ASSUME ES:ENVIRONMENT + +GOTTHEENVIR: + MOV AX,CHAR_OPER SHL 8 ; Get the switch character and store it + INT int_command ; in RSWITCHAR. + MOV [RSWITCHAR],DL + + CMP DL,fslash ; If backslashes are being used as the + JNZ IUSESLASH ; path separator, change the forward + mov al,bslash ; slash in COMSPECT and ECOMSPEC (if + MOV [COMSPECT],al ; there is a new ENVIRONSEG) to + CMP BYTE PTR [CHUCKENV],0 ; backslash. + JNZ IUSESLASH + MOV ES:[ECOMSPEC],al ;eg + +IUSESLASH: +; +; Initialize the command drive +; + MOV AH,Get_Default_Drive + INT 21h + INC AL + MOV ComDrv,AL + + MOV AL,BYTE PTR DS:[FCB] ; al = default drive number for command + OR AL,AL + JZ NoComDrv ; no drive specified + + MOV AH,':' + MOV [COMDRV],AL + ADD AL,40H ; Convert number to uppercase character + + STD + CMP BYTE PTR [CHUCKENV],0 ; If a new environment is being built, + JNZ NOTWIDENV ; move the default comspec string in it + PUSH DS ; 2 bytes to make room for a drivespec. + PUSH ES ; The drivespec is in ax and is copied + POP DS ; on to the front of the string. + MOV DI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 1 ;eg + MOV SI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 3 ;eg + + MOV CX,ENVIRONSIZ2 - 2 + REP MOVSB + POP DS + MOV WORD PTR ES:[ECOMSPEC],AX + +NOTWIDENV: + CLD ; Add the drivespec to the string + MOV WORD PTR [AUTOBAT],AX ; used to reference autoexec.bat + MOV WORD PTR [KAUTOBAT],AX ;AN000; used to reference kautoexe.bat 3/3/KK + +NOCOMDRV: + INVOKE SETVECT ; Set interrupt vectors 22h, 23h, & 24h + +;********************************* +; PARSING STARTS HERE +;********************************* + + push cs ;AN000; get local segment + push cs ;AN000; into DS,ES + pop ds ;AN000; + pop es ;AN000; + +ASSUME DS:RESGROUP,ES:RESGROUP ;AN000; + + MOV SI,80H ;AC000; get command line + LODSB ;AC000; get length of line + MOV DI,SI ;AN000; get line position in DI + XOR AH,AH ;AC000; ax = length of command line +; +; Insure that the command line correctly ends with a CR +; + ADD DI,AX ;AC000; go to end of command line + MOV BYTE PTR [DI],0Dh ;AC000; insert a carriage return + xor cx,cx ;AC000; clear cx + mov num_positionals,cx ;AC000; initialize positionals +; +; Scan the command line looking for the parameters +; + +parse_command_line: + mov di,offset resgroup:parse_command;AN000; Get address of parse_command + mov cx,num_positionals ;AN000; Get number of positionals + xor dx,dx ;AN000; clear dx + mov old_parse_ptr,si ;AN057; save position before calling parser + call init_parse ;AN054; call parser + mov num_positionals,cx ;AN000; Save number of positionals + cmp ax,end_of_line ;AC000; are we at end of line? + jz ArgsDoneJ3 ;AC000; yes - exit + cmp ax,result_no_error ;AN000; did an error occur + jz parse_cont ;AN000; no - continue + +; +; Before issuing error message - make sure switch is not /C +; + +parse_line_error: + push si ;AN057; save line position + push ax ;AN057; save error number + cmp ax,BadSwt_Ptr ;AN057; Was error invalid switch? + jnz parse_line_error_disp ;AN057; No - just issue message + mov di,si ;AN057; Get terminating pointer in DI + mov si,old_parse_ptr ;AN057; Get starting pointer in SI + +init_chk_delim: + cmp si,di ;AN057; at end of parsed parameter? + jz parse_line_error_disp ;AN057; Yes - just display message + lodsb ;AN057; + cmp al,space ;AN057; Skip blank spaces + jz init_chk_delim ;AN057; + cmp al,tab_chr ;AN057; Skip tab characters + jz init_chk_delim ;AN057; + + cmp al,[rswitchar] ;AN057; Switch? + jnz parse_line_error_disp ;AN057; No - just issue message + lodsb ;AN057; Get the char after the switch + invoke itestkanj ;AN057; Is it DBCS? + jnz parse_line_error_disp ;AN057; Yes - can't be /C + invoke iupconv ;AN057; upper case it + cmp al,scswitch ;AN057; it is /C? + jnz parse_line_error_disp ;AN057; + pop dx ;AN057; even up stack + pop dx ;AN057; even up stack + jmp setSSwitch ;AN057; Yes - go set COMMAND /C + +parse_line_error_disp: + pop ax ;AN057; restore error number + pop si ;AN057; restore line position + mov disp_class,parse_msg_class ;AN000; set up parse error msg class + mov dx,ax ;AN000; get message number + call print_message ;AN000; issue error message + jmp short parse_command_line ;AN000; continue parsing + +parse_cont: +; +; See if a switch was entered +; + + cmp comnd1_syn,offset resgroup:command_f_syn ;AC000; was /F entered? + jz SetFSwitch ;AC000; yes go set fail switch + cmp comnd1_syn,offset resgroup:command_p_syn ;AC000; was /P entered? + Jz SetPSwitch ;AC000; yes go set up PERMCOM + cmp comnd1_syn,offset resgroup:command_d_syn ;AC000; was /D entered? + jz SetDSwitch ;AC000; yes go set date switch + cmp comnd1_syn,offset resgroup:command_c_syn ;AC000; was /C entered? + jz SetSSwitch ;AC000; yes go set up SINGLECOM + cmp comnd1_syn,offset resgroup:command_e_syn ;AC000; was /E entered? + jz SetESwitch ;AC000; yes go set up environment + cmp comnd1_syn,offset resgroup:command_m_syn ;AN000; was /MSG entered? + jz SetMSwitchjmp ;AN000; yes go set up message flag + jmp chkotherargs ;AC000; Must be something else + +SetMSwitchjmp: ;AN018; long jump needed + jmp SetMswitch ;AN018; + +ArgsdoneJ3: ;AN018; long jump needed + jmp ArgsDone ;AN018; + +SetFSwitch: + cmp fFail,-1 ;AN018; has fail switch been set? + jnz failok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +failok: + MOV fFail,-1 ;AC000; fail all INT 24s. + JMP parse_command_line ;AC000; + +SetPSwitch: +; +; We have a permanent COMMAND switch /P. Flag this and stash the +; termination address. +; + cmp [permcom],0 ;AN018; has /p switch been set? + jz permcomok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +permcomok: + INC [PERMCOM] + MOV WORD PTR [oldTerm],OFFSET RESGROUP:LODCOM + MOV WORD PTR [oldTerm+2],DS +; +; Make sure that we display the date and time. If the flag was not +; initialized, set it to indicate yes, do prompt. +; + CMP BYTE PTR [PRDATTM],-1 + JNZ parse_command_line_jmp ;AC018; keep parsing + MOV BYTE PTR [PRDATTM],0 ; If not set explicit, set to prompt + +Parse_command_line_jmp: ;AN018; + JMP parse_command_line ;AC000; keep parsing + +ArgsDoneJump: + JMP ArgsDone + +SetDSwitch: +; +; Flag no date/time prompting. +; + cmp dswitch,0 ;AN018; has /D switch been set? + jz setdateok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +setdateok: + inc dswitch ;AN018; indicate /D entered + MOV BYTE PTR [PRDATTM],1 ; User explicitly says no date time + JMP parse_command_line ;AC000; continue parsing + +SetSSwitch: +; +; Set up pointer to command line, flag no date/time and turn off singlecom. +; + MOV [SINGLECOM],SI ; Point to the rest of the command line + MOV [PERMCOM],0 ; A SINGLECOM must not be a PERMCOM + MOV BYTE PTR [PRDATTM],1 ; No date or time either, explicit + JMP ArgsDone +; +; Look for environment-size setting switch +; +; The environment size is represented in decimal bytes and is +; converted into pargraphs (rounded up to the next paragraph). +; + +SetESwitch: + cmp eswitch,0 ;AN018; has fail switch been set? + jz eswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +eswitchok: + inc eswitch ;AN018; indicate /E entered + mov di,offset resgroup:comnd1_addr ;AN000; get number returned + mov bx,word ptr [di] ;AN000; into bx + + ADD BX, 0FH ; Round up to next paragraph + mov cl,4 ;AC000; convert to pargraphs + SHR BX, cl ;AC000; by right 4 + + MOV EnvSiz,BX ; EnvSiz is in paragraphs + JMP parse_command_line ;AC000; continue parsing command line + +SetMSwitch: + cmp ext_msg,set_extended_msg ;AN018; has /MSG switch been set? + jnz setMswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message +setMswitchok: + MOV Ext_msg,set_extended_msg ;AN000; set /MSG switch + JMP parse_command_line ;AN000; keep parsing + +ARGSDONEJ: + JMP ARGSDONE + +; +; We have a non-switch character here. +; +CHKOTHERARGS: + push ds ;AN054; + push si ;AC000; save place in command line + lds si,comnd1_addr ;AN000; get address of filespec + assume ds:nothing ;AN054; + + mov dx,si ;AN000; put in dx also + MOV AX,(OPEN SHL 8) OR 2 ; Read and write + INT int_command + JC CHKSRCHSPEC ; Wasn't a file + MOV BX,AX + MOV AX,IOCTL SHL 8 + INT int_command + TEST DL,80H + JNZ ISADEVICE + +BADSETCON: ;AN022; + MOV AH,CLOSE ; Close initial handle, wasn't a device + INT int_command + JMP CHKSRCHSPEC + +ISADEVICE: + XOR DH,DH + OR DL,3 ; Make sure has CON attributes + MOV AX,(IOCTL SHL 8) OR 1 + INT int_command + JC BADSETCON ;AN022; Can't set attributes - quit + MOV DX,BX ; Save new handle +;eg POP BX ; Throw away saved SI +;eg POP BX ; Throw away saved CX + PUSH CX + MOV CX,3 + XOR BX,BX + +RCCLLOOP: ; Close 0,1 and 2 + MOV AH,CLOSE + INT int_command + INC BX + LOOP RCCLLOOP + MOV BX,DX ; New device handle + MOV AH,XDUP + INT int_command ; Dup to 0 + MOV AH,XDUP + INT int_command ; Dup to 1 + MOV AH,XDUP + INT int_command ; Dup to 2 + MOV AH,CLOSE + INT int_command ; Close initial handle + POP CX + pop si ;AN000; restore position of command line + pop ds ;AN054; + JMP parse_command_line ;AC000; continue parsing + +CHKSRCHSPEC: ; Not a device, so must be directory spec + + MOV BYTE PTR [CHUCKENV],0 ; If search specified -- no inheritance + MOV AX,OFFSET RESGROUP:PATHSTRING ; Figure environment pointer + MOV CL,4 + SHR AX,CL +;AD054; MOV DX,DS + MOV DX,CS ;AC054; + ADD AX,DX + MOV [ENVIRSEG],AX + + MOV ES,AX + push si ;AN000; remember location of file + xor cx,cx ;AN000; clear cx for counting + +countloop: + lodsb ;AN000; get a character + inc cx ;AN000; increment counter + cmp al,end_of_line_out ;AN000; are we at end of line? + jnz countloop ;AN000; no - keep counting + + mov al,space + dec si ;AN000; move back one + MOV BYTE PTR [SI],al ;AN000; put a space at end of line + pop si ;AC000; get location back + + MOV DI,[ECOMLOC] + +COMTRLOOP: + LODSB + DEC CX + CMP AL,space + JZ SETCOMSR + STOSB + +;;; IF KANJI 3/3/KK + XOR AH,AH +;;; ENDIF 3/3/KK + + JCXZ SETCOMSR + +;;;; IF KANJI 3/3/KK + PUSH DS ;AN054; Make sure we have + PUSH CS ;AN054; local DS for + POP DS ;AN054; ITESTKANJ + INVOKE ITESTKANJ + POP DS ;AN054; restore PARSER DS + JZ COMTRLOOP + DEC CX + MOVSB + INC AH + JCXZ SETCOMSR +;;;; ENDIF 3/3/KK + + JMP SHORT COMTRLOOP + +SETCOMSR: + PUSH CX + + PUSH CS ;AN054; Get local segment + POP DS ;AN054; + assume ds:resgroup ;AN054; + + PUSH DS + MOV SI,OFFSET RESGROUP:COMSPECT + MOV CX,14 + + MOV AL,ES:[DI-1] + +;;;; IF KANJI 3/3/KK + OR AH,AH + JNZ INOTROOT ; Last char was KANJI second byte, might be '\' +;;;; ENDIF 3/3/KK + + CALL PATHCHRCMPR + JNZ INOTROOT + INC SI ; Don't make a double / + DEC CX + +INOTROOT: + REP MOVSB + + MOV DX,[ECOMLOC] ; Now lets make sure its good! + PUSH ES + POP DS + + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + POP DS + JC SETCOMSRBAD ; No COMMAND.COM here + MOV BX,AX ; Handle + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + +SETCOMSRRET: + POP CX + POP SI + POP DS ;AN054; + assume ds:resgroup ;AN054; + +ARGSDONEJ2: + PUSH CS ;AN000; Make sure local ES is + POP ES ;AN000; restored + JMP parse_command_line ;AC000; continue parsing command line + +SETCOMSRBAD: + MOV DX,BADCOMLKMES_ptr ;AC000; get message number + invoke triageError + cmp ax, 65 + jnz doprt + mov dx,BADCOMACCMES_ptr ;AC000; get error message number +doprt: + call print_message + MOV SI,OFFSET RESGROUP:COMSPECT + MOV DI,[ECOMLOC] + MOV CX,14 + REP MOVSB ; Get my default back + + JMP SHORT SETCOMSRRET + +;********************************* +; PARSING ENDS HERE +;********************************* + +ARGSDONE: + mov es,[envirseg] ;AC000; get environment back + ASSUME ES:ENVIRONMENT ;AN000; +;AD060; cmp ext_msg,set_extended_msg ;AN000; was /msg specified? +;AD060; jnz check_permcom ;AN000; No, go check permcom +;AD060; cmp [permcom],0 ;AN000; Yes - was permcom set? +;AD060; jz permcom_error ;AN000; No - error cannot have /MSG without /P + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_extended_msg ;AN000; set up extended error message address +;AD060; push es ;AN016; save environment segment +;AD060; push cs ;AN016; get local segment to ES +;AD060; pop es ;AN016; +;AD060; mov di,offset resgroup:extended_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; +;AD060; pop es ;AN016; restore environment segment +;AD060; mov di,offset resgroup:extmsgend+15 ;AN000; get address of resident end +;AD060; mov [resmsgend],di ;AN000; save it +;AD060; call sysloadmsg ;AN000; load message addresses +;AD060; jmp short process_permcom ;AN000; now go process /P switch + +;AD060;permcom_error: +;AD060; mov disp_class,parse_msg_class ;AN000; set up parse error msg class +;AD060; mov dx,LessArgs_Ptr ;AN000; get message number for "Required parameter missing" +;AD060; call print_message ;AN000; issue error message +;AD060; jmp short comreturns ;AN000; we already know /P wasn't entered + +;AD060;check_permcom: + CMP [PERMCOM],0 + JZ COMRETURNS + +;AD060;process_permcom: + PUSH ES ; Save environment pointer + MOV AH,SET_CURRENT_PDB + MOV BX,DS + MOV ES,BX + INT int_command ; Current process is me + MOV DI,PDB_Exit ; Diddle the addresses in my header + MOV AX,OFFSET RESGROUP:LODCOM + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:CONTC + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:DskErr + STOSW + MOV AX,DS + STOSW + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me forever + + MOV DX,OFFSET RESGROUP:INT_2E + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 02EH + INT int_command ;Set magic interrupt + POP ES ;Remember environment + +COMRETURNS: + MOV AX,WORD PTR DS:[PDB_Parent_PID] + MOV [PARENT],AX ; Save parent + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me + MOV AX,WORD PTR DS:[PDB_JFN_Table] + MOV [IO_SAVE],AX ; Get the default stdin and out + MOV WORD PTR [COM_PTR+2],DS ; Set all these to resident + MOV WORD PTR [COM_FCB1+2],DS + MOV WORD PTR [COM_FCB2+2],DS + MOV DI,OFFSET RESGROUP:COMSPEC + + MOV SI,[ECOMLOC] + CMP BYTE PTR [CHUCKENV],0 + + MOV AX,DS ; XCHG ES,DS + PUSH ES + POP DS + MOV ES,AX + + JZ COPYCOMSP ; All set up for copy + + PUSH CS + POP DS + + MOV SI,OFFSET RESGROUP:COMSPSTRING + PUSH ES + PUSH DI + CALL IFINDE + MOV SI,DI + PUSH ES + POP DS + POP DI + POP ES + JNC COPYCOMSP + +COMSPECNOFND: + MOV SI,CS:[ECOMLOC] ;AC062 + ADD SI,OFFSET RESGROUP:PATHSTRING + PUSH CS + POP DS + +assume es:resgroup +COPYCOMSP: + mov es:comspec_print,di ; Save ptr to beginning of comspec path + cmp byte ptr [si+1],':' ; Is there a drive specifier in comspec + jnz COPYCOMSPLOOP ; If not, do not skip over first 2 bytes + add es:comspec_print,2 + +COPYCOMSPLOOP: + LODSB + STOSB + OR AL,AL + JNZ COPYCOMSPLOOP + mov es:comspec_end,di ; Save ptr to end of comspec path + dec es:comspec_end + mov ah,es:comdrv + add ah,'A'-1 + mov es:cpdrv,ah ; Load drive letter in comprmt2 +assume es:environment + + call setup_for_messages ;AN060; set up parse and extended error messages + PUSH CS + POP DS + MOV BX,[RESMSGEND] ;AC000; get end of resident + MOV CL,4 + SHR BX,CL +Public EnvMaximum +EnvMaximum: +; +; NOTE: The transient has to loaded directly after shrinking to the +; resident size. +; There is an assumption made when loading the transient that it +; still intact after the resident portion. +; If any other ALLOC/DEALLOC/SETBLOCK operations are performed +; inbetween, then there is a real good chance that the non-resident +; portion will be overwritten by arena information. +; + MOV AH,SETBLOCK + INT int_command ; Shrink me to the resident only +; +; Load in the transient and compute the checksum. We may do this in one of +; two ways: First, cheat and use the transient loading code that exists in +; the resident piece. This may be OK except that it will hit the disk. +; +; But we do not need to hit the disk! The transient is already loaded but is +; in the wrong place. We need to block transfer it up to the correct spot. +; +GOTENVIR: + MOV TrnMvFlg, 1 ; Indicate that transient has been moved + PUSH ES + MOV SI,OFFSET RESGroup:TranStart + MOV DI,0 + mov ES,Trnseg + MOV CX,OFFSET TRANGROUP:TRANSPACEEND +; +; We need to ensure that we do not have the potential of overwriting our +; existing code in this move +; It is OK to move if (SI+CX+Segment of Transient < TrnSeg). +; + push cx + mov ax,cx ; Get size of transient in bytes + add ax,si ; Calculate end of transient section + mov cl,4 + shr ax,cl ; Convert to paragraphs + inc ax ; Round up (for partial paragraph) + mov cx,ds + add ax,cx ; Add in current segment + cmp ax,Trnseg ; See if there is overlap + pop cx +; If we are too close to be safe, call LOADCOM instead of moving the code. + jb Ok_To_Move + invoke LOADCOM + jmp short Trans_Loaded +Ok_To_Move: +; +; Everything is set for an upward move. WRONG! We must move downward. +; + ADD SI,CX + DEC SI + ADD DI,CX + DEC DI + STD + REP MOVSB + CLD + +Trans_Loaded: + POP ES + + INVOKE CHKSUM ; Compute the checksum + MOV [SUM],DX ; Save it + + CMP BYTE PTR [PRDATTM],0 ;eg + JNZ NOBATCHSEG ;eg Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; + MOV BX,((SIZE BatchSegment) + 15 + 1 + 0Fh)/16 ;eg + MOV AH,ALLOC ;eg + INT int_command ;eg + JC NOBATCHSEG ;eg didn't allocate - pretend no batch + MOV BATCH,AX ;eg save batch segment + +NOBATCHSEG: + MOV BX, 0FFFFH ; Get size of largest block for env + MOV AH, ALLOC + INT int_command + +; Only allocate maximum 64K worth of environment + + SUB BX,TRNSIZE ;eg subtract # of transient paragraphs + SUB BX,128 ;eg make sure we have 2K left + MOV EnvMax, BX + CMP BX, 4096 ; 64K = 4096 paragraphs + JB MAXOK + MOV BX, 4096-1 + MOV EnvMax, BX +MAXOK: + + MOV AH, ALLOC ; Get max size + INT int_command + + mov bx,[envirseg] ;g get old environment segment + mov oldenv,bx ;g save it + mov usedenv,0 ;g initialize env size counter + MOV DS,bx + ASSUME DS:NOTHING + MOV [ENVIRSEG],AX + MOV ES,AX + XOR SI,SI + MOV DI,SI + MOV BX,EnvMax ; Copy over as much of the environment + ; as possible + SHL BX,1 + SHL BX,1 + SHL BX,1 + SHL BX,1 + MOV EnvMax, BX ; Convert EnvMax to bytes + DEC BX ; Dec by one to leave room for double 0 + XOR DX,DX ; Use DX to indicate that there was + ; no environment size error. +Public Nxtstr +Nxtstr: + CALL GetStrLen ; Get the size of the current env string + push ds ;g get addressability to environment + push cs ;g counter + pop ds ;g + ASSUME DS:RESGROUP + add usedenv,cx ;g add the string length to env size + pop ds ;g + ASSUME DS:NOTHING + CMP CX,1 ; End of environment was encountered. + JZ EnvExit + SUB BX,CX + JAE OKCpyStr ; Can't fit in all of enviroment. + INC DX ; Out of env space msg must be displayed + JMP EnvExit +OKCpyStr: + JMP Nxtstr +EnvExit: + + PUSH CS + POP DS + ASSUME DS:RESGroup + OR DX,DX ; DX will be non-zero if error + JZ EnvNoErr + MOV DX,OUTENVERR_ptr ;AC000; get message number + call print_message + +EnvNoErr: + ; BX now has the left over size of the maximum environment + ; We want to shrink the environment down to the minimum size + ; Set the environment size to max(Envsiz,Env used) + + MOV CX, EnvMax + SUB CX, BX ; CX now has the environment used + ADD CX, 16 ; Round up to next paragraph + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + CMP CX, Envsiz ; Is environment used > Envsiz + JB EnvSet + MOV Envsiz, CX +EnvSet: + MOV BX, Envsiz ; Set environment to size needed + mov ax,es ;eg get environment segment + add ax,bx ;eg add number of environment paragraphs + cmp ax,initend ;eg does this go past end of init? + ja envsetok ;eg yes - do the setblock + mov ax,es ;eg no - get back the environment segment + mov bx,initend ;eg get the segment at end of init + sub bx,ax ;eg setblock envir segment to end of init code + mov resetenv,1 ;eg set flag so we know to set envir later + +envsetok: + MOV AH, SETBLOCK + INT int_command + + IF MSVER + CMP [SINGLECOM],0 + JNZ NOPHEAD ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message +NOPHEAD: + ENDIF + + CMP [BATCH],0 ;eg did we set up a batch segment? + JNZ dodate ;eg yes - go initialize it + JMP NODTTM ; Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; +dodate: + MOV AX,BATCH ;eg get batch segment + MOV EchoFlag,3 ; set batch echo + MOV NEST,1 ; g set nest flag to 1 batch + MOV ES,AX +; +; Initialize the segment +; + XOR DI,DI + MOV AL,BatchType + STOSB + MOV AL,1 ; G initialize echo for batch exit + STOSB ; G + XOR AX,AX ; initialize to zero + STOSW ; G batch segment of last job - batlast + STOSW ; G segment for FOR + STOSB ; G FOR flag + STOSW ; position in file - batseek + STOSW +; +; Clean out the parameters +; + MOV AX,-1 ; initialize to no parameters + MOV CX,10 + REP STOSW +; +; Decide whether we should grab the default drive +; + CMP BYTE PTR [AUTOBAT],0 + + JNZ NOAUTSET + MOV AH,GET_DEFAULT_DRIVE + INT int_command + ADD AL,ucasea + + MOV [AUTOBAT],AL + MOV [KAUTOBAT],AL ;AN000; 3/3/KK + +NOAUTSET: +; +; Copy in the batch file name (including NUL) +; + MOV SI,OFFSET RESGROUP:AUTOBAT + MOV CX,8 + REP MOVSW + MOVSB ;AN027; move in carraige return to terminate string + + MOV DX,OFFSET RESGROUP:AUTOBAT + MOV AX,OPEN SHL 8 + INT int_command ; See if AUTOEXEC.BAT exists + JC NOABAT + MOV BX,AX + MOV AH,CLOSE + INT int_command + JMP DRV0 ;AC000; go process autoexec + +NOABAT: + push ax + call setup_seg + mov word ptr [triage_add+2],ax + pop ax + call triage_add + cmp ax, 65 + jz AccDenErr ;AN000; was network access denied + + +; If AUTOEXEC.BAT is not found, then check for KAUTOEXE.BAT. Changed +; by Ellen to check only when in Korea. The country information +; returned will overlay the old parse data area, but we don't care +; since we won't need the parse information or country information. +; We only care about the country code returned in BX. + + MOV DX,OFFSET RESGROUP:INTERNAT_INFO ;AN000; Set up internat vars + MOV AX,INTERNATIONAL SHL 8 ;AN000; get country dependent info + INT 21H ;AN000; + JC NOKABAT ;AN000; Error - don't bother with it + CMP BX,KOREA_COUNTRY_CODE ;AN000; Are we speaking Korean? + JNZ OPENERR ;AN000; No, don't check for KAUTOEXE + + MOV DI, OFFSET BatFile ;AN000; 3/3/KK + MOV SI,OFFSET RESGROUP:KAUTOBAT ;AN000; Another trial to do 3/3/KK + MOV CX,8 ;AN000; auto execution for the 3/3/KK + REP MOVSW ;AN000; non-English country 3/3/KK + MOVSB ;AN027; move in carraige return to terminate string + MOV DX,OFFSET RESGROUP:KAUTOBAT ;AN000; 3/3/KK + MOV AX,OPEN SHL 8 ;AN000; 3/3/KK + INT int_command ;AN000; See if KAUTOEXE.BAT exists 3/3/KK + JC NOKABAT ;AN000; 3/3/KK + MOV BX,AX ;AN000; 3/3/KK + MOV AH,CLOSE ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + JMP SHORT DRV0 ;AN000; 3/3/KK + +NOKABAT: ;AN000; 3/3/KK + call triage_add ;AN000; get extended error + cmp ax, 65 ;AN000; network access denied? + jnz openerr ;AN000; no - go deallocate batch + +AccDenErr: ;AN000; yes - put out message + mov DX,ACCDEN ;AC000; get message number + call print_message + +openerr: + MOV ES,[BATCH] ; Not found--turn off batch job + MOV AH,DEALLOC + INT int_command + MOV [BATCH],0 ; AFTER DEALLOC in case of ^C + MOV EchoFlag,1 + mov nest,0 ;g indicate no batch in progress + +DODTTM: + MOV AX,OFFSET TRANGROUP:DATINIT + MOV WORD PTR[INITADD],AX + MOV AX,[TRNSEG] + MOV WORD PTR[INITADD+2],AX + CALL DWORD PTR [INITADD] + +NODTTM: + + IF IBMVER + CMP [SINGLECOM],0 + JNZ DRV0 ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message + ENDIF + +DRV0: ; Reset APPEND state + push ds ;AN042; save data segment + push cs ;AN042; Get local segment into DS + pop ds ;AN042; + mov ax,AppendSetState ;AN042; Set the state of Append + mov bx,Append_state ;AN042; back to the original state + int 2fh ;AN042; + pop ds ;AN042; get data segment back + JMP ENDINIT ;G Finish initializing + +; +; Get length of string pointed to by DS:SI. Length includes NULL. +; Length is returned in CX +; +GetStrLen: + xor cx,cx +NxtChar: + lodsb + inc cx + or al,al + jnz NxtChar + ret +; +; If the transient has been loaded in TranSeg, then we need to use that +; segment for calls to routines in the transient area. Otherwise, the current +; code segment is used +; Segment returned in AX. +; +setup_seg: + mov ax,[trnseg] + cmp TrnMvFlg, 1 ; Has transient portion been moved + jz setup_end + push bx + mov bx,cs + mov ax,OFFSET RESGroup:TranStart + shr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + add ax,bx + pop bx +setup_end: + ret + +print_message: + push ax + PUSH DS ;AN000; save data and extra segment + PUSH ES ;AN000; registers + MOV AX,CS ;AN000; get local segment + MOV ES,AX ;AN000; set ES and DS to point to it + MOV DS,AX ;AN000; +;AD054; PUSH BX ;AC000; save BX register +;AD054; PUSH CX ;AC000; save CX register +;AD054; PUSH DX ;AC000; save DX register +;AD054; MOV AX,DX ;AC000; get message number +;AD054; MOV DH,DISP_CLASS ;AC000; get display class +;AD054; MOV DL,NO_CONT_FLAG ;AN000; set control flags off +;AD054; MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12 +;AD054; XOR CH,CH ;AC000; clear upper part of cx +;AD054; MOV CL,NUMBER_SUBST ;AC000; set number of substitutions +;AD054; invoke SYSDISPMSG ;AC000; display the message +;AD054; MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class +;AD054; MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions +;AD054; POP DX ;AC000; restore registers +;AD054; POP CX ;AC000; +;AD054; POP BX ;AC000; + invoke rprint ;AC054; + + POP ES ;AN000; + POP DS ;AN000; + pop ax + ret + +PATHCHRCMPR: + push dx + mov dl,fslash + CMP [RSWITCHAR],dl + JZ RNOSLASHT + CMP AL,dl + JZ RET41 +RNOSLASHT: + CMP AL,bslash +RET41: + pop dx + RET + + +IFINDE: + CALL IFIND ; FIND THE NAME + JC IFIND2 ; CARRY MEANS NOT FOUND + JMP ISCASB1 ; SCAN FOR = SIGN +; +; On return of FIND1, ES:DI points to beginning of name +; +IFIND: + CLD + CALL ICOUNT0 ; CX = LENGTH OF NAME + MOV ES,[ENVIRSEG] + XOR DI,DI + +IFIND1: + PUSH CX + PUSH SI + PUSH DI + +IFIND11: + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE ITESTKANJ + JZ NOTKANJ4 + DEC SI + LODSW + INC DI + INC DI + CMP AX,ES:[DI-2] + JNZ IFIND12 + DEC CX + LOOP IFIND11 + JMP SHORT IFIND12 + +NOTKANJ4: +;;;; ENDIF 3/3/KK + + CALL IUPCONV + INC DI + CMP AL,ES:[DI-1] + JNZ IFIND12 + LOOP IFIND11 + +IFIND12: + POP DI + POP SI + POP CX + JZ IFIND2 + PUSH CX + CALL ISCASB2 ; SCAN FOR A NUL + POP CX + CMP BYTE PTR ES:[DI],0 + JNZ IFIND1 + STC ; INDICATE NOT FOUND + +IFIND2: + RET + +ICOUNT0: + PUSH DS + POP ES + MOV DI,SI + + PUSH DI ; COUNT NUMBER OF CHARS UNTIL "=" + CALL ISCASB1 + JMP SHORT ICOUNTX + PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL + CALL ISCASB2 + +ICOUNTX: + POP CX + SUB DI,CX + XCHG DI,CX + RET + +ISCASB1: + MOV AL,equalsign ; SCAN FOR AN = + JMP SHORT ISCASBX + +ISCASB2: + XOR AL,AL ; SCAN FOR A NUL + +ISCASBX: + MOV CX,100H + REPNZ SCASB + RET + + +; **************************************************************** +; * +; * ROUTINE: IUPCONV (ADDED BY EMG 4.00) +; * +; * FUNCTION: This routine returns the upper case equivalent of +; * the character in AL from the file upper case table +; * in DOS if character if above ascii 128, else +; * subtracts 20H if between "a" and "z". +; * +; * INPUT: DS set to resident +; * AL char to be upper cased +; * FUCASE_ADDR set to the file upper case table +; * +; * OUTPUT: AL upper cased character +; * +; **************************************************************** + +assume ds:resgroup ;AN000; + +iupconv proc near ;AN000; + + cmp al,80h ;AN000; see if char is > ascii 128 + jb other_fucase ;AN000; no - upper case math + sub al,80h ;AN000; only upper 128 chars in table + push ds ;AN000; + push bx ;AN000; + lds bx,dword ptr fucase_addr+1 ;AN000; get table address + add bx,2 ;AN000; skip over first word + xlat ds:byte ptr [bx] ;AN000; convert to upper case + pop bx ;AN000; + pop ds ;AN000; + jmp short iupconv_end ;AN000; we finished - exit + +other_fucase: ;AN000; + cmp al,lcasea ;AC000; if between "a" and "z", + jb iupconv_end ;AC000; subtract 20h to get + cmp al,lcasez ;AC000; upper case equivalent. + ja iupconv_end ;AC000; + sub al,20h ;AC000; Change lower-case to upper + +iupconv_end: ;AN000; + ret + +iupconv endp ;AN000; + +init_contc_specialcase: + ; This routine is called if control-C + add sp,6 ; is type during the date/time prompt + push si ; at initialization time. The desired + mov si,dx ; response is to make it look like the + mov word ptr [si+1],0d00h ; user typed by "popping" the + pop si ; INT 21h stuff off the stack, putting + iret ; a in the user's buffer, and + ; returning directly to the user. + ; In this case the user is TCODE. + +; **************************************************************** +; * +; * ROUTINE: GET_MSG_PTR +; * +; * FUNCTION: Fill in translatable char table starting at +; * at Abort_char with translated characters. +; Set segments of resident messages. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +CHAR_START EQU 201 ;AN000; first character translate is 1 +CHAR_END EQU 207 ;AN000; last is 6 + +GET_MSG_PTR PROC NEAR ;AN000; + + MOV AX,CHAR_START ;AN000; get first char translation + MOV BX,OFFSET RESGROUP:ABORT_CHAR ;AN000; get first char offset +MOVEMES: ;AN000; + MOV DH,-1 ;AN000; utility message + INVOKE SYSGETMSG ;AN000; get the offset of the char + MOV CL,BYTE PTR [SI] ;AN000; get the character in CL + MOV BYTE PTR [BX],CL ;AN000; put the character in the table + INC BX ;AN000; point to next position in table + INC AX ;AN000; increment message number + CMP AX,CHAR_END ;AN000; are we at the end? + JNZ MOVEMES ;AN000; no - keep loading + + MOV AX,DS ;AN000; get data segment + MOV DRVNUM_OP_SEG,AX ;AN000; set up segments for + MOV DRVNUM_OP_SEG2,AX ;AN000; message substitutions + MOV DEVE_OP_SEG,AX ;AN000; used in the resident + MOV DEVE_OP_SEG2,AX ;AN000; portion of command + MOV ERR15_OP_SEG,AX ;AN000; during initialization + MOV ERR15_OP_SEG2,AX ;AN000; to save resident + MOV ERR15_OP_SEG3,AX ;AN000; space. + MOV BADFAT_OP_SEG,AX ;AN000; + MOV COMPRMT1_SEG,AX ;AN000; + MOV COMPRMT1_SEG2,AX ;AN000; + + RET ;AN000; + +GET_MSG_PTR ENDP ;AN000; + + +; **************************************************************** +; * +; * ROUTINE: Setup_for_messages +; * +; * FUNCTION: Sets up system for PARSE and EXTENDED ERROR +; * messages as follows: +; * +; * IF /P and /MSG are entered +; * keep PARSE and EXTENDED ERRORS in memory +; * ELSE IF /P is entered +; * use PARSE and EXTENDED ERRORS on disk +; * remove PARSE ERRORS from memory +; * ELSE +; * remove PARSE ERRORS from memory +; * ENDIF +; * +; * INPUT: PERMCOM Set up with user input +; * EXT_MSG Set up with user input +; * System set up to retain PARSE ERRORS +; * +; * OUTPUT: registers unchanged +; * +; **************************************************************** + + +setup_for_messages proc near ;AN060; + + push ds ;AN060; save data segment + push es ;AN060; save environment segment + push ax ;AN060; + push dx ;AN060; + push di ;AN060; + mov ax,cs ;AN060; get local segment to ES and DS + mov ds,ax ;AN060; + mov es,ax ;AN060; + + cmp [permcom],0 ;AN060; was permcom set? + jz no_permcom ;AN060; No - don't worry about messages + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jz permcom_slash_msg ;AN060; Yes - go process it + push es ;AN060; + mov ax,1 ;AN060; Set ES to 1 as a flag to the message + mov es,ax ;AN060; services that messages are on disk + mov di,offset resgroup:extended_msg_start-100h ;AN060; start address + call set_ext_2f ;AN060; set extended error address + mov di,offset resgroup:parse_msg_start-0100h ;AN060; start address + call set_parse_2f ;AN060; set parse error address + pop es ;AN060; + IF2 ;AN060;; + IFNDEF READ_DISK_INFO ;AN060;; + Extrn READ_DISK_PROC:Far ;AN060;; + ENDIF ;AN060;; + ENDIF ;AN060;; + MOV AX,DOS_GET_EXT_PARSE_ADD ;AN060;; 2FH Interface + MOV DL,DOS_SET_ADDR ;AN060;; Set the READ_DISK_PROC address + LEA DI,READ_DISK_PROC ;AN060;; + INT 2FH ;AN060;; Private interface + jmp short permcom_end ;AN060; and exit + +permcom_slash_msg: ;AN060; Keep messages in memory + mov di,offset resgroup:extended_msg_start ;AN060; start address + call set_ext_2f ;AN060; set the extended message address + mov di,offset resgroup:extmsgend+15 ;AN060; get address of resident end + mov [resmsgend],di ;AN060; save it + jmp short permcom_end ;AN060; exit + +no_permcom: ;AN060; + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jnz no_slash_msg ;AN060; no - no error + mov disp_class,parse_msg_class ;AN060; set up parse error msg class + mov dx,LessArgs_Ptr ;AN060; get message number for "Required parameter missing" + call print_message ;AN060; issue error message + +no_slash_msg: + mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers + mov dl,set_parse_msg ;AN060; set up parse message address + mov di,pars_msg_off ;AN060; old offset of parse messages + mov es,pars_msg_seg ;AN060; old segment of parse messages + int 2fh ;AN060; go set it + +permcom_end: + call sysloadmsg ;AN060; load message addresses + pop di ;AN060; + pop dx ;AN060; + pop ax ;AN060; + pop es ;AN060; get environment back + pop ds ;AN060; + + ret ;AN060; + +setup_for_messages endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_parse_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the PARSE +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_parse_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_parse_msg ;AN060; set up parse message address + int 2fh ;AN060; + + ret ;AN060; + +Set_parse_2f endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_ext_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the EXTENDED +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_ext_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_extended_msg ;AN060; set up extended error message address + int 2fh ;AN060; + + ret ;AN060; + +Set_ext_2f endp ;AN060; + + +ASSUME DS:RESGROUP, ES:RESGROUP + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AC026; include message services macro + +include msgdcl.inc + +INIT ENDS + + END -- cgit v1.2.3