home *** CD-ROM | disk | FTP | other *** search
- page 66,132
- ;============================================================================
- ; BAT2EXEC.COM - a batch file compiler
- ;
- ; BAT2EXEC filename
- ;
- ; Revision History:
- ;
- ; Version 1.0 Initial Release PC Magazine Vol 9 Num 14
- ;
- ;============================================================================
-
- code segment
- assume cs:code
-
- org 2ch
- env_segment dw ? ;Word containing the segment
- ; of the program's env. block.
- org 80h
- command_tail db ? ;Offset of the command tail.
-
- org 100h
-
- main: jmp initialize
- program db 13,10,"BAT2EXEC 1.0 "
- copyright db "(c) 1990 Ziff Communications Co.",10,13
- author db "PC Magazine ",254," Douglas Boling"
- db 10,13,"$",1Ah
- ;----------------------------------------------------------------------------
- ;Equates used to find data offsets in the compiled program.
- ;----------------------------------------------------------------------------
- run_buff_size dw 256 ;Size of runtime buffers
-
- std_data_size equ offset data_end - data_start
- code_start_ptr equ [bp + offset code_start - offset data_start]
- com_stack_ptr equ [bp + offset stack_ptr - offset data_start]
- com_prog_size equ [bp + offset prog_segsize - offset data_start]
- com_label_start equ [bp + offset label_list_strt - offset data_start]
- string1_buff equ [bp + offset str1_buff_ptr - offset data_start]
- string2_buff equ [bp + offset str2_buff_ptr - offset data_start]
- string3_buff equ [bp + offset str3_buff_ptr - offset data_start]
- forloop_ptr equ [bp + offset floop_ptr - offset data_start]
- stdout_hdl equ [bp + offset file_handle1 - offset data_start]
- outfile_hdl equ [bp + offset file_handle2 - offset data_start]
- stdin_hdl equ [bp + offset file_handle3 - offset data_start]
- infile_hdl equ [bp + offset file_handle4 - offset data_start]
- environment_seg equ [bp + offset master_env - offset data_start]
- dos_version equ [bp + offset version_num - offset data_start]
- process_rc equ [bp + offset proc_rc - offset data_start]
- shift_count equ [bp + offset shift_cnt - offset data_start]
-
- code_call_size equ offset code_call_end - offset code_call
- code_jmp_size equ offset code_jmp_end - offset code_jmp
- code_jc_size equ offset code_jc_end - offset code_jc
- code_jnc_size equ offset code_jnc_end - offset code_jnc
- code_jmpdis_size equ offset code_jmpdis_end - offset code_jmpdis
- code_leasi_size equ offset code_leasi_end - offset code_leasi
- code_movsi_size equ offset code_movsi_end - offset code_movsi
- code_movsiim_size equ offset code_movsiim_end - offset code_movsiim
- code_leadi_size equ offset code_leadi_end - offset code_leadi
- code_movdi_size equ offset code_movdi_end - offset code_movdi
- code_movdiim_size equ offset code_movdiim_end - offset code_movdiim
- ;============================================================================
- ;Compiler data
- ;============================================================================
- fileecho db 0 ;File echo flag
- lineecho db 0 ;Current line echo flag
-
- command_table db "IF",0 ;Commands processed by
- db "REM",0 ; compiler
- db "FOR",0
- db "ECHO",0
- db "GOTO",0
- db "EXIT",0
- db "PAUSE",0
- db "SHIFT",0
- db "SET",0
- db "CALL",0
- db "PATH",0
- db "PROMPT",0
- db "CD",0 ;DOS commands internal to
- db "MD",0 ; command.com.
- db "RD",0
- db "CLS",0
- db "DIR",0
- db "DEL",0
- db "REN",0
- db "VER",0
- db "VOL",0
- db "CTTY",0
- db "CHCP",0
- db "TYPE",0
- db "COPY",0
- db "DATE",0
- db "TIME",0
- db "ERASE",0
- db "CHDIR",0
- db "MKDIR",0
- db "RMDIR",0
- db "BREAK",0
- db "RENAME",0
- db "DELETE",0
- db "VERIFY",0
- db "COMMAND",0,0
-
- batcmd_jmptbl dw if_cmd ;if command
- dw rem_cmd ;rem command
- dw for_cmd ;for command
- dw echo_cmd ;echo command
- dw goto_cmd ;goto command
- dw rem_cmd ;exit command
- dw pause_cmd ;pause command
- dw shift_cmd ;shift command
- dw set_cmd ;set command
-
- dw internal_cmd ;call command
- dw set_cmd ;Path command
- dw set_cmd ;Prompt command
- dw internal_cmd ;DOS internal command
- dw external_cmd ;DOS program
- dw label_cmd ;Process BAT label
- batcmd_jmptbl1 = $
-
- ifstr1 db "ERRORLEVEL"
- ifstr2 db "EXIST"
-
- internal_cmdsw db "/C " ;Switch for transient commands
-
- for_active_flag db 0 ;Set if parsing a FOR loop
- goto_active db 0 ;Set if goto parsed
- goto_data_ptr dw 0 ;Data offset of last goto
-
- cmd_switches db ? ;Used if command line switches
- cmd_switch_end = $ ; needed.
-
- last_routine dw offset init_code_next ;Last canned routine used.
-
- codebuff_start dw 0 ;Buffer to construct the code
- codebuff_ptr dd 0 ; image of the COM file.
-
- databuff_start dw ? ;Buffer to hold the data
- databuff_end dw ? ; image of the COM file.
-
- firstlabel dw -1 ;Ptr to 1st label in COM file
-
- outbuff_ptr dd 0 ;Buffer to hold the final
- outbuff_end dw 0 ; image of the COM file.
-
- quote_flag db 0 ;Disable translate flag
- redirect_in db 0 ;Input redirection flag
- redirect_out db 0 ;Output redirection flag
-
- pipe_toggle db 0 ;Piping file flag
- pipein_file dw 0
- pipein_flag db 0
- pipeout_file dw 0
- pipeout_flag db 0
- pipe1_file dw 0
- db "T^M^P_$1.!!!",0 ;Name of piping file 1
- pipe2_file dw 0
- db "T^M^P_$2.!!!",0 ;Name of piping file 2
-
- inbuff_ptr dw offset end_of_code+512 ;Buffer for BAT file
- inbuff_size dw 16384 ;Size of input buffer
-
- file_pointer dw ? ;Ptr to BAT data not read.
- file_handle dw ? ;Handle of BAT file
- file_linecount dw 0 ;Line number being processed.
-
- com_string db ".COM",0 ;Extension for output file
- outfile_name db 13 dup (" ") ;Name of output file.
-
- filemsg1 db 13,10,"Error in line $" ;File identification message.
-
- errmsg0 db "Need DOS 2.0 or greater$"
- errmsg1 db 13,10,"Syntax: BAT2EXEC [filename]",13,10,"$"
- errmsg2 db "Can",39,"t find input file$"
- errmsg3 db "Not enough memory$"
- errmsg4 db "No input file specified$"
- errmsg5 db "COM file size too big$"
- errmsg6 db "Syntax error$"
- errmsg7 db "Compiler data buffer full$"
- errmsg8 db "Label defined more than once$"
- errmsg9 db "Label "
- errmsg9labl db 8 dup (" ")
- db "not found$"
- errmsg10 db "Illegal disk specified$"
- errmsg11 db "FOR loops cannot be nested$"
- endmsg db 13,10,"$"
-
- ;----------------------------------------------------------------------------
- ; Start of compiler code.
- ;----------------------------------------------------------------------------
- initialize proc near
- assume cs:code,ds:code,es:code
- mov dx,offset program ;Display copyright message.
- mov ah,9
- int 21h
- cld ;Set string operations 'up.'
- mov ah,30h ;Get DOS version, run only
- int 21h ; if 2.0 or greater.
- xchg al,ah ;Swap major, minor numbers
- mov dx,offset errmsg0 ;Bad DOS version
- cmp ah,2
- jb jmp_disp_error
-
- mov sp,offset end_of_code + 512 ;Move stack
- mov ah,4ah ;Reduce memory
- mov bx,1000h ; allocation to 64K
- int 21h
-
- mov ax,inbuff_ptr ;Compute start of buffer for
- add ax,inbuff_size ; COM file data.
- mov databuff_start,ax
-
- mov ah,48h ;Allocate memory block for
- mov bx,1000h ; intermediate buffer.
- int 21h
- mov dx,offset errmsg3 ;Not enough memory msg
- jc jmp_disp_error
- mov word ptr codebuff_ptr[2],ax ;Save segment.
-
- mov ah,48h ;Allocate memory block for
- mov bx,1000h ; output file buffer.
- int 21h
- jc jmp_disp_error
- mov word ptr outbuff_ptr[2],ax ;Save segment.
- ;
- ;Parse the command line for switches.
- ;
- mov si,offset command_tail
- xor cx,cx
- or cl,[si] ;Get command line length
- je parse_cmdline_end ;If zero, skip parse routine
- inc si
- parse_cmdline_l1:
- xor bl,bl ;Search for the next
- call scanline ; non-space character.
- jc parse_cmdline_end
- mov al,[si]
- cmp al,"/" ;See if command switch
- je parse_switch_found
- call loadbatfile ;Load input BAT file
- jc jmp_disp_error
- jmp short parse_cmdline_end
- parse_switch_found:
- mov dx,offset errmsg2 ;No cmd line switches.
- jmp_disp_error:
- jmp disp_error
- parse_cmdline_end:
- ;
- ;Compile BAT file line by line.
- ;
- mov si,inbuff_ptr ;SI points to input BAT file
- mov di,databuff_start ;DI points to COM file data.
- add di,std_data_size
- new_line:
- inc file_linecount ;Inc line number
- mov al,fileecho ;Copy the file echo status to
- mov lineecho,al ; the line echo flag
- xor bl,bl ;Look for 1st character
- call scan4char
- jnc comp_1
- cmp al,13 ;See if carrage return, if so
- je new_line ; continue, else assume end
- jmp short comp_end ; of file.
- comp_1:
- call redirect_check
- cmp byte ptr [si],'@' ;See if non echo prefix
- jne comp_2
- mov lineecho,0 ;Don't echo this line
- inc si ;Move past @
- comp_2:
- call parse ;Parse 1st word in the line.
- jc comp_error
- jmp new_line
- comp_error:
- jmp disp_error
- comp_end:
- ;
- ;Inline code complete, append terminate code.
- ;
- call redirect_close
- mov databuff_end,di ;Save ptr to end of data.
- les di,codebuff_ptr
- assume es:nothing
- mov si,offset end_code ;Append terminate code
- mov cx,offset end_code_end-offset end_code
- rep movsb
- mov word ptr codebuff_ptr,di ;Save ptr to end of COM code.
- ;
- ;File processed. Assemble data and code into one routine. Start by
- ;stringing the canned routines together using the links set by the
- ;INCLUDE routine.
- ;
- les di,outbuff_ptr ;Get ptr to output buffer
- mov si,offset init_code_next ; for COM file.
- file_1: mov cx,[si-2] ;Get size of routine
- push [si] ;Save pointer to next routine
- add si,4 ;Skip past number of links
- rep movsb ;Copy routine to COM file.
- pop si
- or si,si ;See if last routine
- jne file_1 ;No, loop back.
- ;
- ;Save starting offset of data to be used by the COM program.
- ;
- mov bp,offset data_start_ptr-offset init_code
- mov ax,100h ;AX = end pointer
- add ax,di ;Add length of canned routines.
- mov es:[bp],ax ;Save data start pointer
- mov bp,di ;Use BP as starting data offset
-
- mov si,databuff_start ;Compute length of COM data
- mov cx,databuff_end ; plus the canned routines.
- sub cx,si
- add ax,cx ;Add data length to end ptr
- ;
- ;Now that we have the length of the canned routines and the data, we can
- ;compute the starting offset of the inline code. Use this number to adjust
- ;the jump table entries in the label list. While fixing offsets check to
- ;see that all labels have code offsets, if not, print no label error msg.
- ;When complete, append data to file.
- ;
- mov bx,offset firstlabel ;Get pointer to the first label
- mov dx,[bx] ;Get offset to 1st label entry
- add dx,bx ;Add in BX to get absolute off
- file_11:
- cmp word ptr [bx],-1 ;See if at end of label list.
- je file_13
- add bx,[bx] ;Get next in list
- cmp word ptr [bx+2],-1 ;See if label ptr to code
- je file_12 ; initialized. No, error.
- add [bx+2],ax ;Add starting offset of code
- jmp short file_11
- file_12:
- mov si,bx ;Label not defined as a
- add si,5 ; destination. Print error
- xor cx,cx ; message inc lost label.
- mov cl,[bx+4] ;Get size of label
- push cs
- pop es
- mov di,offset errmsg9labl
- rep movsb
- mov dx,offset errmsg9 ;Label not found msg
- jmp disp_error
- file_13:
- rep movsb ;Append data to COM file.
- sub dx,databuff_start ;Set pointer to 1st label list
- mov es:com_label_start,dx ;Initialize pointer.
- ;
- ;Append the inline code to the program.
- ;
- mov ax,100h
- add ax,di
- mov es:code_start_ptr,ax ;Save offset of main code.
-
- mov cx,word ptr codebuff_ptr
- mov si,codebuff_start ;Get pointer to code
- mov ds,word ptr codebuff_ptr[2]
- assume ds:nothing
- sub cx,si ;Get size of code
- add ax,cx ;Make sure canned routines
- jnc file_2 ; and data < 64 K bytes.
- file_too_big: mov dx,offset errmsg5 ;COM file too big msg
- jmp disp_error
- file_2:
- rep movsb ;Append inline code.
- ;
- ;Compute the size of the data buffers and the stack used by the COM program.
- ;Write these numbers to the COM file data area.
- ;
- push cs
- pop ds
- assume ds:code
- add ax,512 ;Add room for stack
- jc file_too_big
- and ax,0fffeh ;Set stack on even word.
- mov es:com_stack_ptr,ax ;Save run time stack pointer
- add ax,2 ;Make room for buff length word
- mov es:string1_buff,ax ;Save ptr to parsing buffer.
- add ax,258 ;Add room for buffer 2
- jc file_too_big
- mov es:string2_buff,ax ;Save ptr to parsing buffer 2
- add ax,258 ;Add room for buffer
- jc file_too_big
- mov es:string3_buff,ax ;Save ptr to For loop buffer
- add ax,256 ;Add room for buffer
- jc file_too_big
-
- mov outbuff_end,di ;Save end pointer to file
- add ax,15
- jc file_3 ;Compute size of COM file
- mov cl,4 ; in paragraphs.
- shr ax,cl
- mov es:com_prog_size,ax ;Save file size
- mov byte ptr es:shift_count,0 ;Clear shift count
- file_3:
- ;
- ;Write file to disk.
- ;
- mov ah,3ch ;Create file
- xor cx,cx ;Normal attributes
- mov dx,offset outfile_name ;Name of file
- int 21h
-
- mov bx,ax ;Copy handle
- mov ah,40h ;Write file
- push ds
- lds dx,outbuff_ptr ;Get start of buffer
- mov cx,cs:[outbuff_end] ;Get number of bytes to write
- sub cx,dx
- int 21h ;Write file to disk
- pop ds
-
- mov ah,3eh ;Close file
- int 21h
- ;
- ;Compile complete. Clean up and end.
- ;
- good_exit:
- xor al,al ;Return code = 0
- exit:
- push ax ;Save return code
- mov ah,49h ;Release memory block used
- mov es,word ptr cs:[codebuff_ptr+2] ; for file buffer.
- int 21h
-
- pop ax ;Get back return code
- mov ah,4Ch ;Terminate
- int 21h
- ;
- ;Display error message.
- ;
- disp_error:
- push cs
- pop ds
- assume ds:code
- cmp file_linecount,0
- je disp_error1 ;If processing a file, print
- push dx ; a message informing the
- mov dx,offset filemsg1 ; user the line that
- call printmsg ; contained the error.
- mov ax,file_linecount
- call hex2asc
- mov dx,offset endmsg
- call printmsg
- pop dx
- disp_error1:
- call printmsgcr ;print string
- mov al,01 ;Terminate with RC = 1
- jmp short exit
-
- ;-----------------------------------------------------------------------------
- ; PARSE Parse a statment.
- ; Entry: SI - Pointer to string to parse.
- ; DI - Pointer to end of COM file data.
- ; Exit: CF - Set if error.
- ; SI - Updated.
- ;-----------------------------------------------------------------------------
- parse proc near
- mov bx,14
- mov al,[si] ;See if label
- cmp al,":"
- je parse_2
-
- mov bx,12
- cmp al,"%" ;See if cmd line param or env
- je parse_2 ; var. If so, internal cmd
-
- mov ax,[si+1] ;See if change to default disk
- cmp al,":"
- jne parse_1
- mov bx, 12 ;Set internal command.
- cmp ah," "
- jbe parse_2
- parse_1:
- call capsword ;Capitalize batch command
- push di ;Search list of BAT cmds.
- mov di,offset command_table
- call findstr
- pop di
- parse_2:
- push bx ;Scan past command except for
- cmp bx,8 ; external progs, inter cmds,
- ja parse_3 ; and labels.
- mov bl,1
- call scan4char
- jnc parse_3 ;If end of line, back up to
- dec si ; show CR.
- parse_3:
- pop bx
- shl bx,1 ;Compute offset of routine to
- add bx,offset batcmd_jmptbl ; call.
- call [bx] ;Call routine to compile line.
- ret
- parse endp
-
- ;-----------------------------------------------------------------------------
- ; FINDSTR determines if a string is in a list.
- ; Entry: SI - Pointer to ASCII string to find.
- ; DI - Pointer to list of ASCIIZ strings.
- ; CX - Size of string
- ; Exit: CF - Clear if string found
- ; BX - If CF clear, index into list
- ;-----------------------------------------------------------------------------
- findstr proc near
- push cx
- push es
- push cs ;Point ES:DI to table of
- pop es ; batch commands.
- mov dx,cx ;Save length of string
- xor bx,bx ;Zero index counter
- finds_1:
- push si
- mov cx,dx ;Restore command size
- repe cmpsb ;Compare command
- pop si
- je string_found
- inc bx
- xor al,al
- cmp [di-1],al
- jne finds_2
- dec di
- finds_2:
- mov cx,10 ;Scan to next zero
- repne scasb
- cmp byte ptr [di],0 ;See if second zero. If so
- jne finds_1 ; end of list.
- mov bx,13
- stc ;Indicate string not found
- findstr_exit:
- pop es
- pop cx
- ret
- string_found:
- cmp bx,12 ;If past the BAT commands,
- jb findstr_3 ; then it is an internal cmd.
- mov bx,12
- findstr_3:
- clc ;Set string found flag
- jmp short findstr_exit
- findstr endp
-
- ;-----------------------------------------------------------------------------
- ; CAPSWORD capitalizes word pointed to by SI
- ; Entry: SI - Pointer to ASCII word to capitalize
- ; Exit: CX - Size of word
- ;-----------------------------------------------------------------------------
- capsword proc near
- assume ds:nothing,es:nothing
- push di
- push si
- push es
- push ds ;Set ES:DI = DS:SI
- pop es
- mov di,si
- xor cx,cx ;Clear byte counter.
- caps_1:
- lodsb ;Get character
- cmp al,"0" ;Allow numbers
- jb caps_exit
- cmp al,"9"
- jbe caps_2
- cmp al,"A" ;If between A and Z, continue
- jb caps_exit
- cmp al,"Z"
- jbe caps_2
- cmp al,"a" ;If batween a and z,
- jb caps_exit ; capitalize it, else, exit
- cmp al,"z"
- ja caps_exit
- and al,0DFh
- caps_2:
- stosb ;Save character
- inc cx ;Inc byte counter
- jmp short caps_1
- caps_exit:
- pop es
- pop si
- pop di
- ret
- capsword endp
-
- ;-----------------------------------------------------------------------------
- ; REDIRECT CLOSE post process redirection commands
- ; Entry: DI - Pointer to end of COM file data.
- ; Exit: CF - Set if error.
- ; Batch file line updated to remove any redirection symbols
- ;-----------------------------------------------------------------------------
- redirect_close proc near
- assume cs:code,ds:code
- cmp redirect_in,0 ;See if redirecton active
- je redirclose_1
- mov redirect_in,0
- mov bx,offset redirci_next ;Append close redirect file
- call include_code ; routine to code.
- xor cx,cx
- call inline_code
- redirclose_1:
- cmp redirect_out,0 ;See if redirecton active
- je redirclose_2
- mov redirect_out,0
- mov bx,offset redirco_next ;Append close redirect file
- call include_code ; routine to code.
- xor cx,cx
- call inline_code
- redirclose_2:
- cmp pipein_flag,0 ;See if in pipe curr active
- je redirclose_3
- mov dx,pipein_file ;Get offset of input pipe file
- mov cx,1 ;Indicate parameter type
- mov bx,offset redirdel_next ;Delete the piping file
- call include_code
- call inline_code
- mov pipein_flag,0 ;Clear flag
- redirclose_3:
- cmp pipeout_flag,0 ;See if out pipe curr active
- je redirclose_exit
- mov dx,pipeout_file ;Get offset of input pipe file
- xor bx,bx ;Add output redirection code
- xor ax,ax ; to file.
- call redirect_openi
- mov pipein_flag,1 ;Set pipe input flag
- mov pipeout_flag,0 ;Clear pipe output flag
- mov pipein_file,dx ;Copy pointer to filename
- redirclose_exit:
- ret
- redirect_close endp
-
- ;-----------------------------------------------------------------------------
- ; REDIRECT CHECK process redirection commands
- ; Entry: SI - Pointer to current BAT file line
- ; DI - Pointer to end of COM file data.
- ; Exit: CF - Set if error.
- ; Batch file line updated to remove any redirection symbols
- ;-----------------------------------------------------------------------------
- redirect_check proc near
- assume cs:code,ds:code
- push si
- call redirect_close
- mov quote_flag,0
- redirect_1:
- mov bp,si ;Save current position
- lodsb
- cmp al,'"' ;See if quote
- jne redirect_2
- not quote_flag
- redirect_2:
- cmp quote_flag,0 ;Ignore characters in quotes
- jne redirect_3
- ;
- ; Check for piping
- ;
- cmp al,'|' ;Check for piping symbol
- jne redirect_5
- mov byte ptr [si-1],13 ;Replace | with CR
-
- mov bx,offset pipe1_file ;Get offset of pipe file to
- cmp pipe_toggle,0 ; use. Alternate files so
- jne redirect_3 ; that input and output files
- mov bx,offset pipe2_file ; don't get mixed up.
- redirect_3:
- not pipe_toggle
- xor dx,dx ;If file not already used,
- or dx,[bx] ; load the filename into
- jne redirect_4 ; the COM data buffer.
- mov dx,di
- sub dx,databuff_start ;Compute offset of filename
- mov [bx],dx ;Save pointer to filename
- lea si,[bx+2] ;Get address of filename
- mov ah,1
- call copy_string ;Copy name to COM data buffer
- xor al,al ;Terminate filename with zero
- stosb
- redirect_4:
- mov pipeout_file,dx
- mov pipeout_flag,1
- xor bx,bx ;Add output redirection code
- xor ax,ax ; to file.
- call redirect_openo
- jmp short redirect_exit ;Terminate line scan.
- ;
- ; Check for output redirection
- ;
- redirect_5:
- cmp al,'>' ;Check for redirect out
- jne redirect_7
- xor bx,bx
- cmp byte ptr [si],'>' ;Check for append redirect
- jne redirect_6
- lodsb ;Remove 2nd >
- inc bx
- redirect_6:
- push bx ;Save append flag
- xor bl,bl
- call scan4char ;Get filename
- mov dx,di
- mov ah,1 ;Copy only one word
- call copy_string
- xor al,al ;Terminate name with zero
- stosb
- sub dx,databuff_start ;Compute offset of filename
- pop ax
- call redirect_openo
- call erase_redirect ;Erase redirect from line.
- jmp short redirect_1
- redirect_7:
- cmp al,'<' ;Check for redirect in
- jne redirect_10
- xor bl,bl
- call scan4char ;Get filename
- mov dx,di
- mov ah,1 ;Copy only one word
- call copy_string
- xor al,al ;Terminate name with zero
- stosb
- sub dx,databuff_start ;Compute offset of filename
- call redirect_openi
- call erase_redirect ;Erase redirect from line.
- jmp redirect_1
- redirect_10:
- cmp al,13
- je redirect_exit
- jmp redirect_1
- redirect_exit:
- clc
- pop si
- ret
- redirect_check endp
-
- ;-----------------------------------------------------------------------------
- ; REDIRECT OPENO process redirection commands
- ; Entry: AX - 1 = append file.
- ; Entry: DX - Offset from data buffer start of file name
- ; BX - 0 no translation of filename.
- ;-----------------------------------------------------------------------------
- redirect_openo proc near
- assume cs:code,ds:code
- push si
- push ax ;Save append flag
- mov cx,0031h ;Indicate parameter type
- or bx,bx ;See if env var or cmd line
- je redirect_oo1 ; parms.
-
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine. Include if needed.
-
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0032h ;Indicate parameter type
- call inline_code ;Insert translate code.
- redirect_oo1:
- mov bx,offset rediroo_next ;Append open redirect file
- call include_code
- pop bx ;Restore append flag
- call inline_code
- mov redirect_out,1 ;Set redirect active flag
- pop si
- ret
- redirect_openo endp
-
- ;-----------------------------------------------------------------------------
- ; REDIRECT OPENI loads code to open a file for input redirection
- ; Entry: DX - Offset from data buffer start of file name
- ; BX - 0 no translation of filename.
- ;-----------------------------------------------------------------------------
- redirect_openi proc near
- assume cs:code,ds:code
- push si
- mov cx,1 ;Indicate parameter type
- or bx,bx ;See if env var or cmd line
- je redirect_oi1 ; parms.
-
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine. Include if needed.
-
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,2 ;Indicate parameter type
- call inline_code ;Insert translate code.
- redirect_oi1:
- mov bx,offset rediroi_next ;Append open redirect file
- call include_code
- call inline_code
- mov redirect_in,1 ;Set redirect active flag
- pop si
- ret
- redirect_openi endp
-
- ;-----------------------------------------------------------------------------
- ; ERASE REDIRECT
- ; Entry: BP - Pointer to redirect character
- ; SI - Pointer to end of redirect phrase.
- ;-----------------------------------------------------------------------------
- erase_redirect proc near
- assume cs:code,ds:code
- push di ;Save ptr to data buffer
- mov al,' '
- mov di,bp ;Get start of redirect string
- dec si
- erase_1:
- stosb
- cmp di,si
- jb erase_1
- pop di
- ret
- erase_redirect endp
-
- ;-----------------------------------------------------------------------------
- ; IF CMD compiles an IF command.
- ; Entry: SI - Pointer to character after the IF command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- if_cmd proc near
- assume cs:code,ds:code
- xor bl,bl ;Find 1st char of next word
- call scan4char
- mov bx,si ;Save pointer to test
- mov dx,di
- mov bp,0 ;Clear 'NOT' flag
- ;
- ;See if NOT prefix is used in test
- ;
- lodsw ;Get 1st two chars of test
- or ax,2020h
- cmp ax,'on' ;See if 'no'
- jne if_cmd_000
- lodsw ;Get 2nd and 3rd characters
- or al,20h ;Convert 3rd char to lower
- cmp al,'t' ; case. See if last char is
- jne if_cmd_000 ; 't' followed by s space
- cmp ah,' '
- ja if_cmd_000
- inc bp
- xor bl,bl ;Find next word
- call scan4char
- mov bx,si
- ;
- ;Test for string compare by looking for == signs.
- ;
- if_cmd_000:
- mov si,bx ;Restore pointer to condition
- if_cmd_00:
- lodsb ;Scan past first string to
- cmp al,'=' ; determine if this is a
- je if_cmd_02 ; string comparison.
- cmp al,9
- je if_cmd_01
- cmp al,' '
- jb if_syntax_jmp
- jne if_cmd_00
- if_cmd_01:
- lodsb ;Scan past any spaces before
- cmp al,9 ; the equals signs.
- je if_cmd_01
- cmp al,' '
- je if_cmd_01
- jnb if_cmd_02
- if_syntax_jmp:
- jmp if_syntax
- if_cmd_02:
- cmp word ptr [si-1],"==" ;See if string compare
- jne if_cmd_0 ;No, check other tests
- inc si ;Move SI past equals signs
- push si ;Save pointer to 2nd string
- mov si,bx ;Restore ptr to 1st string
- push di ;Save ptr to size byte
- inc di
- mov dx,di ;Save ptr to start of string
- sub dx,databuff_start
- mov ah,1 ;Copy only one word
- call copy_string ;Load string into data space
- or bx,bx ;See if translation is needed
- mov bx,dx
- pop bx
- mov [bx],cl ;Save length of string
- mov cl,1 ;Assume LEA parameter call
- je if_cmd_03
-
- mov bx,offset procstr_next ;Append translate string
- call include_code ; routine to code.
- mov bx,offset str2_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx ;Copy ptr to buffer.
- mov cx,2 ;Use MOV parameter type
- if_cmd_03:
- pop si ;Restore ptr to 2nd string
- push dx ;Save pointer to 1st string
- push cx ;Save parameter type
- if_cmd_04:
- push di ;Save ptr to size byte
- inc di
- mov dx,di ;Save ptr to start of string
- sub dx,databuff_start
- mov ah,1
- call copy_string ;Load string into data space
- or bx,bx ;See if translation is needed
- pop bx
- mov [bx],cl ;Save length of string
- mov cx,10h ;Set parameter type
- je if_cmd_06
-
- mov bx,offset procstr_next ;Append translate string
- call include_code ; routine to code.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx ;Copy ptr to buffer.
- mov cx,20h ;Use proper parameter type
- if_cmd_06:
- mov bx,offset ifequal_next ;Append comparison code
- call include_code
- pop bx ;Restore param 1 type
- and bl,0fh
- or cl,bl ;Combine parameter types
- mov bx,dx ;Move parameter 2
- pop dx ;Restore parameter 1
- call inline_code ;Add call to string compare
- jmp if_cmd_10
- if_syntax:
- mov dx,offset errmsg6 ;Syntax error.
- stc
- jmp if_exit
- ;
- ;See if ERRORLEVEL test.
- ;
- if_cmd_0:
- mov si,bx ;Restore pointer to test
- mov di,offset ifstr1 ;See if ERRORLEVEL test
- call capsword
- cmp cx,10
- jne if_cmd_2
- repe cmpsb ;Compare strings
- jne if_cmd_2
- mov bx,offset iferrlev_next ;Save offset of errlev code
- push bx ; on stack. Use exist code
- jmp short if_cmd_21 ; to append error code.
- ;
- ;See if EXIST test.
- ;
- if_cmd_2:
- mov si,bx ;Restore pointer to test
- mov di,offset ifstr2 ;See if EXIST test
- cmp cx,5 ;Check length of string
- jne if_syntax
- repe cmpsb ;Compare strings
- jne if_syntax
- mov bx,offset ifexist_next ;Save test existance code off
- push bx
- if_cmd_21:
- xor bl,bl
- call scan4char ;Scan to next word.
- mov di,dx ;Restore data pointer
- sub dx,databuff_start
- mov ah,1
- call copy_string
- xor al,al ;Terminate string with zero.
- stosb
- mov cl,21h ;Set parameter type
- or bx,bx ;See if translation is needed
- je if_cmd_3
-
- mov bx,offset procstr_next ;Append translate string
- call include_code ; routine to code.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx ;Copy ptr to buffer.
- mov cl,22h ;Use proper parameter type
- if_cmd_3:
- pop bx ;Restore test code offset
- call include_code
- mov bx,offset str2_buff_ptr - offset data_start
- call inline_code ;Insert exist test call
- if_cmd_10:
- mov cx,200h ;Include Jump if carry opcode
- or bp,bp
- je if_cmd_12
- mov cx,300h ;Change to Jump if not carry
- if_cmd_12:
- call inline_code
- push ax ;Save address of jmp to modify
- push word ptr codebuff_ptr ;Save current code buff ptr
- ;
- ;Compile the remainder of the line as if it were a normal statment.
- ;
- xor bl,bl ;Scan for next word
- call scan4char
- call parse ;Compile remainder of line.
-
- pop cx ;Compute the difference for the
- pop bx ; jmp opcode.
- jc if_exit ;If error during parse, exit.
- push es
- mov ax,word ptr codebuff_ptr
- mov es,word ptr codebuff_ptr[2]
- sub ax,cx
- mov es:[bx],ax ;Save jmp offset
- pop es
- clc
- if_exit:
- ret
- if_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; FOR CMD compiles an FOR command.
- ; Entry: SI - Pointer to character after the FOR command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- for_cmd proc near
- assume cs:code,ds:code
- cmp for_active_flag,0
- je for_cmd_0
- mov dx,offset errmsg11 ;No nested FOR loops
- stc
- jmp for_exit
- for_cmd_0:
- mov goto_active,0 ;Clear goto detect flag
- inc for_active_flag
- xor bl,bl ;Find 1st char of next word
- call scan4char
- jc jmp_for_syntax
- mov bp,si ;Save pointer to loop variable
- mov dx,di
- sub dx,word ptr databuff_start
- ;
- ;Copy the set data to the com file data area. As always, if environment
- ;variables or command line parameters are in the data, insert a call to
- ;the translate routine before calling the for loop routine.
- ;
- for_cmd_1:
- lodsb ;Scan until '(' is found
- cmp al,13 ; indicating the start of the
- jne for_cmd_2 ; data set.
- jmp_for_syntax:
- jmp for_syntax
- for_cmd_2:
- cmp al,'('
- jne for_cmd_1
- mov ah,2 ;Copy until ')' found.
- call copy_string
- xor al,al ;Terminate string with zero.
- stosb
-
- push word ptr codebuff_ptr ;Save current code buff ptr
- mov cl,11h ;Set parameter type
- ; or bx,bx ;See if translation is needed
- ; je for_cmd_3
-
- mov bx,offset procstr_next ;Append translate string
- call include_code ; routine to code.
- mov bx,offset str3_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx ;Copy ptr to buffer.
- mov cl,12h ;Use proper parameter type
- for_cmd_3:
- mov bx,offset forloop_next
- call include_code
- mov bx,di ;Initialize for loop data
- sub bx,databuff_start ; structure.
- mov word ptr [di],0
- inc di
- inc di
- call inline_code ;Insert call to loop code.
- mov cx,200h ;Include Jump if carry opcode
- call inline_code
- push ax ;Save address of jmp to modify
- push word ptr codebuff_ptr ;Save current code buff ptr
-
- ;
- ;Scan the remainder of the line. Replace all instances of the loop variable
- ;with a special code that the run time translate routine understands.
- ;
- xor bl,bl ;Find DO
- call scan4char
- jc for_syntax_1
- mov bl,1 ;Find end of 'DO'
- call scan4char
- jc for_syntax_1
- xor bl,bl ;Find start of loop command.
- call scan4char
- jc for_syntax_1
- push si ;Save pointer to command.
- push di ;Save data buffer pointer.
- mov di,si
- mov bl,2 ;Find the end of the line.
- call scan4char
- mov dx,si ;Save pointer to end of line
- for_cmd_4:
- mov si,bp ;Get ptr to loop variable.
- mov cx,3 ;Scan the remainder of the
- repe cmpsb ; line for the loop variable.
- jne for_cmd_5 ; When found, replace with
- dec di ; % followed by 7fh. This
- dec di ; flag tells the runtime
- mov ax,207fh ; xlate routine to sub in
- stosw ; the loop string.
- for_cmd_5:
- cmp di,dx ;See if at the end of the line.
- jb for_cmd_4
- pop di ;Restore data buffer ptr
- pop si ;Restore ptr to command.
- ;
- ;Compile the remainder of the line as if it were a normal statment.
- ;
- call parse ;Compile remainder of line.
-
- pop dx ;Get code ptr after loop code
- pop bx ;Get addr of JC
- pop ax ;Get code ptr to loop code
- jc for_exit1
-
- sub ax,word ptr codebuff_ptr ;Compute displacment from END
- sub ax,3 ; of JMP opcode.
- mov cx,400h ;Insert JMP opcode after code
- call inline_code ; for statments inside FOR
- mov ax,word ptr codebuff_ptr; loop.
- sub ax,dx
- push es
- mov es,word ptr codebuff_ptr[2]
- mov es:[bx],ax
- pop es
- ;
- ; If goto parsed during FOR, place jump for goto after FOR loop
- ;
- cmp goto_active,0
- je for_exit
- mov dx,goto_data_ptr
- mov bx,offset gotodly_next ;Append goto delay
- call include_code ; routine to code.
- mov cx,1
- call inline_code ;Add code to COM file.
- for_exit:
- clc
- for_exit1:
- mov for_active_flag,0 ;Clear flag
- ret
- for_syntax_1:
- add sp,6 ;Clean off stack
- for_syntax:
- mov dx,offset errmsg6 ;Syntax error
- stc
- jmp short for_exit1
- for_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; GOTO CMD compiles a goto command.
- ; Entry: SI - Pointer to first character after the command.
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- goto_cmd proc near
- assume cs:code,ds:code
- mov goto_active,1 ;Needed for FOR loop
- mov bp,di ;Save ptr to start of string.
- xor bl,bl ;Find the first nonspace char.
- call scan4char
- push si
- xor ax,ax
- stosw ;Save word in case FOR loop
- xor ah,ah ; delay goto.
- call copy_string ;Copy label to COM data.
- xor al,al ;Terminate label with zero
- stosb
- pop si
- mov dx,offset errmsg8 ;Check to see if label found.
- or cx,cx ;If not, error.
- je goto_cmd_error
- cmp for_active_flag,0 ;If in for loop, force eval
- jne goto_c1 ; Jmp must occur after FOR
-
- or bx,bx ;See if env var or cmd line
- je goto_c2 ; parms. If not hard code jmp
- goto_c1:
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine. Include if needed.
-
- mov dx,bp ;Get pointer to label.
- sub dx,databuff_start ;Compute offset.
- mov goto_data_ptr,dx ;Save offset in case FOR loop
- add dx,2 ;Move past word ptr
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx
- mov cx,32h ;Use proper parameter type
- mov bx,offset goto_next ;Append goto string
- call include_code ; routine to code.
- xor bx,bx
- cmp for_active_flag,0 ;If in FOR loop delay goto.
- je goto_c11 ; Pass ptr to word to save
- mov bx,goto_data_ptr ; destination address.
- goto_c11:
- call inline_code ;Add code to COM file.
- jmp goto_cmd_exit
- ;
- ;Since label doesn't use env vars or cmd line params, hard code JMP.
- ;
- goto_c2:
- mov di,bp ;Reset data ptr to ignore label
- call getlabel ;See if label in list.
- mov ax,bx ;Copy pointer to label pointer
- add ax,2 ; to code.
- sub ax,databuff_start ;Compute offset of pointer
- mov cx,100h ;Insert JMP opcode.
- call inline_code
- goto_cmd_exit:
- mov bl,2
- call scan4char ;Scan to the end of the line.
- clc
- goto_cmd_exit1: ret
- goto_cmd_error:
- stc
- jmp short goto_cmd_exit1
- goto_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; LABEL CMD processes a label found in the bat file.
- ; Entry: SI - Pointer to first character of the label
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- label_cmd proc near
- assume cs:code,ds:code
- inc si ;Move past ':'
- call getlabel
- cmp word ptr [bx+2],-1 ;See if list entry initialized
- jne label_error ; if so error.
- mov ax,word ptr codebuff_ptr
- mov [bx+2],ax ;Save code ptr in COM data
- mov bl,2
- call scan4char ;Scan to the end of the line.
- clc
- label_exit:
- ret
- label_error:
- mov dx,offset errmsg8 ;Two identical labels
- stc
- jmp short label_exit
- label_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; GETLABEL searches the label list in the data area. If a matching label entry
- ; is found it is returned, if not a label entry is created.
- ; Entry: SI - Pointer to first character of the label
- ; DI - Pointer to end of compiled data.
- ; Exit: BX - Points to label entry.
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- getlabel proc near
- assume cs:code,ds:code
- call capsword ;Convert to caps & get length.
- cmp cx,8 ;Max length of a label 8
- jbe getlabel_1 ; characters to be consistant
- mov cx,8 ; with DOS.
- getlabel_1:
- mov bp,di ;Save data ptr
- mov di,offset firstlabel ;Get ptr to the 1st label
- mov bx,di
- cmp word ptr [di],-1 ;See if any labels defined.
- je getlabel_2 ;No, skip label list search.
-
- push cx ;Save label size
- add bx,[bx] ;Point to first label
- call lblsrch_code ;Search label list.
- pop cx
- mov di,bp ;Create label entry.
- jnc getlabel_exit
- getlabel_2:
- mov di,bp ;Create label entry.
- mov ax,-1
- stosw ;Clear end of list tag
- stosw ;Indicate unitialized label
- mov al,cl
- stosb ;Save length of label
- rep movsb ;Copy label into data buffer
- mov ax,bp
- sub ax,bx ;Compute offset to new label
- mov [bx],ax ;Load offset in prev. label
- mov bx,bp ;Get start of label entry
- getlabel_exit:
- clc
- ret
- getlabel endp
-
- ;-----------------------------------------------------------------------------
- ; EXTERNAL CMD compiles a routine to exexute a program.
- ; Entry: SI - Pointer to character after the command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- external_cmd proc near
- assume cs:code,ds:code
- mov dx,di ;Save ptr to filename
- sub dx,databuff_start ;Compute offset.
- mov ah,1
- call copy_string ;Copy filename to COM data.
- xor al,al ;Terminate filename with zero
- stosb
- inc di
- push di ;Save ptr to command line tail
- xor ah,ah
- call copy_string ;Copy command line tail.
- mov ax,000dh ;Append CR and zero
- stosw
- pop bp ;Get ptr to cmd tail
- mov [bp-1],cl ;Save length of command line
- sub bp,databuff_start ;Compute offset.
- mov cx,11h
- or bx,bx ;See if translation code needed
- je externalcmd_1
-
- push dx
- mov dx,bp ;Get pointer to cmd line tail
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov cx,21h ;Use proper parameter type
- mov bp,bx
- pop dx
- externalcmd_1:
- mov bx,offset external_next ;Append prog launch code
- call include_code
- mov bx,bp ;Get ptr to filename
- call inline_code ;Add code to COM file.
- clc
- ret
- external_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; INTERNAL CMD compiles a command internal to command.com
- ; Entry: SI - Pointer to character after the command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- internal_cmd proc near
- assume cs:code,ds:code
- inc di ;Make room for string size.
- push di ;Save ptr to internal command.
- push si
- mov si,offset internal_cmdsw
- movsw ;Copy /C switch to tell
- movsb ; COMMAND.COM to execute and
- pop si ; terminate.
- xor ah,ah
- call copy_string ;Copy internal command
- mov ax,000dh ;Append CR and zero
- stosw
- pop bp
- add cl,3 ;Add length of /c switch
- mov [bp-1],cl ;Save length of command line
-
- mov dx,bp ;Get pointer to internal cmd
- sub dx,databuff_start ;Compute offset.
- mov cx,1
- or bx,bx ;See if translation code needed
- je internalcmd_1
-
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov cx,2 ;Use proper parameter type
- mov dx,bx ;Get input from str1 buffer
- internalcmd_1:
- mov bx,offset intcmd_next ;Append internal cmd routine
- call include_code ; to code.
- call inline_code ;Add code to COM file.
- clc
- ret
- internal_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; SET CMD compiles a command to change variables in the evvironment
- ; Entry: SI - Pointer to character after the command
- ; DI - Pointer to end of compiled data.
- ; Exit: CF - Set if error
- ; DX - Offset to error message if CF set.
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- set_cmd proc near
- assume cs:code,ds:code
- xor bl,bl ;Find the first nonspace char.
- call scan4char
- mov dx,di ;Save ptr to set command.
- xor ah,ah
- call copy_string ;Copy string to COM data
- xor al,al ;Append zero
- stosb
- sub dx,databuff_start ;Compute offset of data.
- mov cx,1
- or bx,bx ;See if translation code needed
- je setcmd_1
-
- mov bx,offset procstr_next ;Get offset of translate
- call include_code ; routine.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov cx,2 ;Use proper parameter type
- mov dx,bx ;Get input from str1 buffer
- setcmd_1:
- mov bx,offset setenv_next ;Append set routine to code.
- call include_code
- call inline_code ;Add code to COM file.
- clc
- ret
- set_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; ECHO CMD compiles an ECHO command.
- ; Entry: SI - Pointer to character after the ECHO command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- echo_cmd proc near
- assume cs:code,ds:code
- xor bl,bl ;Echo can either echo a
- call scan4char ; string to the keyboard or
- jc echo_c0 ; toggle the echo flag.
- or al,20h ;Check for on or off keyword
- cmp al,"o" ; to indicate what type of
- jne echo_c0 ; Echo this is.
- mov ax,[si+1] ;Get next two characters
- or ax,2020h ;Make lower case
- mov bl,1
- cmp al,"n" ;Check for echo on
- je echo_c00
- cmp ax,"ff" ;Check for echo off
- jne echo_c0
- dec bl
- mov ah,[si+3] ;Get character past word
- echo_c00:
- cmp ah," " ;Make sure not just the start
- ja echo_c0 ; of another word.
- mov fileecho,bl ;Save status of echo flag
- mov bl,2
- call scan4char ;Find end of line.
- jmp short echo_exit
- ;
- ;Echo ASCII line, Include code in COM file to echo string.
- ;
- echo_c0:
- mov dx,di ;Save pointer to string start
- xor ah,ah
- call copy_string ;Copy string to COM data.
- mov ax,0d0ah ;Terminate line with CRLF
- stosw
- xor al,al ;Append zero byte
- stosb
- mov cx,1 ;Append runtime routines.
- sub dx,databuff_start
- or bx,bx ;Check translate flag, if set
- je echo_c21 ; append translate code 1st.
- mov bx,offset procstr_next ;Append translate string
- call include_code ; routine to code.
- mov bx,offset str1_buff_ptr - offset data_start
- mov cx,0021h ;Indicate parameter type
- call inline_code ;Insert translate code.
- mov dx,bx
- mov cx,2 ;Use proper parameter type
- echo_c21:
- mov bx,offset echo_msg_next ;Append echo string
- call include_code ; routine to code.
- echo_c3:
- call inline_code ;Add code to COM file.
- echo_cstatus:
- echo_exit:
- clc
- echo_cmd_exit:
- ret
- echo_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; PAUSE CMD compiles a PAUSE command.
- ; Entry: SI - Pointer to character after the PAUSE command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- pause_cmd proc near
- assume cs:code,ds:code
- ;Append routine if necessary
- mov bx,offset pause_next ;Append PAUSE routine if
- call include_code ; necessary.
-
- mov cx,0 ;Add inline code with 0 params
- call inline_code ; to call pause routine.
-
- mov bl,2 ;Scan to end of line
- call scan4char
- clc
- pause_cmd_exit:
- ret
- pause_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; SHIFT CMD compiles a SHIFT command.
- ; Entry: SI - Pointer to character after the SHIFT command
- ; DI - Pointer to end of compiled data.
- ; Exit: AL - Error code if CF set
- ; CF - Set if error
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- shift_cmd proc near
- assume cs:code,ds:code
- mov bx,offset shift_next ;Append shift routine if
- call include_code ; necessary.
- mov cx,0 ;Add inline code with 0 params
- call inline_code ; to call pause routine.
- mov bl,2 ;Scan to end of line
- call scan4char
- clc
- ret
- shift_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; REM CMD Processes remark lines in batch file.
- ; Entry: SI - pointer to line in BAT file
- ;-----------------------------------------------------------------------------
- rem_cmd proc near
- assume cs:code,ds:code
- dec si ;Back up to make sure we don't
- rem_c1: lodsb ; miss a carrage return.
- cmp al,1ah ;Loop until end of line or end
- je rem_exit ; of file.
- cmp al,13
- jne rem_c1
- rem_exit:
- clc
- ret
- rem_cmd endp
-
- ;-----------------------------------------------------------------------------
- ; COPY STRING copies a string to the com file data buffer.
- ; Entry: SI - Pointer to 1st character of the string.
- ; DI - Pointer to end of compiled data.
- ; AH - 0 = copy until end of line
- ; 1 = copy only one word
- ; 2 = copy until ')'
- ; Exit: BX - 0 if no environment variables or command line parameters.
- ; CX - Size of string.
- ; SI,DI updated.
- ;-----------------------------------------------------------------------------
- copy_string proc near
- assume cs:code,ds:code
- push dx
- mov dx,di ;Copy pointer to string
- xor bx,bx ;Clear param/env flag
- xor cx,cx ;Clear count
- copystr_1:
- lodsb ;Get byte
- cmp al,9 ;Don't exit if tab
- je copystr_2
- cmp al,13 ;See if carrage return
- jbe copystr_exit ;Yes, quit.
- copystr_2:
- cmp ah,2 ;See if set copy
- jne copystr_3 ;No, skip next test.
- cmp al,')' ;See if end of set
- je copystr_exit ;Yes, quit.
- copystr_3:
- cmp ah,1 ;See if phrase or word copy
- jne copystr_4 ;Phase, skip next test.
- cmp al,' ' ;See if end of word.
- jbe copystr_exit ;Yes, quit.
- cmp al,'=' ;Equal sign indicates end of
- je copystr_exit ; word.
- copystr_4:
- inc cx
- cmp al,'%' ;See if translation needed.
- jne copystr_6
- inc bh
- or bl,bl ;See if already set.
- mov bl,0 ;Clear flag
- jne copystr_6 ;If set, this must be the
- cmp byte ptr [si],7fh ;Check for For loop var. If
- jne copystr_5 ; found, copy it removing
- stosb ; the extra space.
- lodsb
- inc si
- jmp short copystr_6
- copystr_5:
- cmp byte ptr [si],'9' ; trailing % of an env var.
- jbe copystr_6
- call capsword ;Env var, capitialize it.
- inc bl
- copystr_6:
- stosb ;Save byte
- jmp short copystr_1 ;Loop back.
- copystr_exit:
- pop dx
- ret
- copy_string endp
-
- ;-----------------------------------------------------------------------------
- ; INLINE CODE Adds the necessary inline code to call a canned
- ; routine.
- ; Entry: AX - Offset of canned routine.
- ; CL - (low nibble) Method to pass parameter one
- ; CL - (high nibble) Method to pass parameter two
- ; CH - (low nibble) Call/Jump method
- ; DX - Parameter one
- ; BX - Parameter two
- ;-----------------------------------------------------------------------------
- inline_code proc near
- push bp
- push si ;Save pointer to input buffer.
- push di
- push es
- les di,codebuff_ptr ;Point ES:DI to buffer
- mov bp,cx
- and cl,0fh ;Look only at SI code nibble
- cmp cl,1 ;Check for LEA SI
- jne inline_1
- mov si,offset code_leasi
- mov [si+2],dx ;Load paramter one
- mov cx,code_leasi_size
- rep movsb ;Copy routine into COM file.
- jmp short inline_10
- inline_1:
- cmp cl,2 ;Check for MOV SI
- jne inline_2
- mov si,offset code_movsi
- mov [si+2],dx ;Load parameter one
- mov cx,code_movsi_size
- rep movsb ;Copy routine into COM file.
- jmp short inline_10
- inline_2:
- cmp cl,3 ;Check for MOV SI Immediate
- jne inline_10
- mov si,offset code_movsiim
- mov [si+1],dx ;Load parameter one
- mov cx,code_movsiim_size
- rep movsb ;Copy routine into COM file.
- inline_10:
- mov cx,bp ;Get back code
- and cl,0f0h
- cmp cl,10h ;Check for LEA DI
- jne inline_11
- mov si,offset code_leadi
- mov [si+2],bx ;Load paramter two
- mov cx,code_leadi_size
- rep movsb ;Copy routine into COM file.
- jmp short inline_13
- inline_11:
- cmp cl,20h ;Check for MOV DI
- jne inline_12
- mov si,offset code_movdi
- mov [si+2],bx ;Load parameter two
- mov cx,code_movdi_size
- rep movsb ;Copy routine into COM file.
- jmp short inline_13
- inline_12:
- cmp cl,30h ;Check for MOV immed DI
- jne inline_13
- mov si,offset code_movdiim
- mov [si+1],bx ;Load parameter two
- mov cx,code_movdiim_size
- rep movsb ;Copy routine into COM file.
- inline_13:
- mov cx,bp
- and ch,0fh
- jne inline_20
- mov si,offset code_call ;Code to call the canned
- mov cx,code_call_size ; routine.
- mov [si+1],ax ;Insert the destination offset.
- rep movsb ;Copy routine into COM file.
- jmp short inline_30
- inline_20:
- cmp ch,01 ;Check for jmp
- jne inline_21
- mov si,offset code_jmp ;Code to jmp to destination.
- mov cx,code_jmp_size
- mov [si+2],ax ;Insert the destination offset.
- rep movsb ;Copy routine into COM file.
- jmp short inline_30
- inline_21:
- cmp ch,02 ;Check for jc
- jne inline_22
- mov si,offset code_jc ;Code to jc to destination.
- mov cx,code_jc_size
- lea ax,[di+3] ;Save offset of JMP to mod
- rep movsb ;Copy routine into COM file.
- jmp short inline_30
- inline_22:
- cmp ch,03 ;Check for jnc
- jne inline_23
- mov si,offset code_jnc ;Code to jnc to destination.
- mov cx,code_jnc_size
- lea ax,[di+3] ;Save offset of JMP to mod
- rep movsb ;Copy routine into COM file.
- jmp short inline_30
- inline_23:
- cmp ch,04 ;Check for jmp displacment
- jne inline_30
- mov si,offset code_jmpdis ;Code to jmp IP relative.
- mov [si+1],ax
- mov cx,code_jmpdis_size
- rep movsb ;Copy routine into COM file.
- inline_30:
- mov word ptr cs:codebuff_ptr,di
- pop es
- pop di
- pop si
- pop bp
- ret
- inline_code endp
-
- ;-----------------------------------------------------------------------------
- ; INCLUDE CODE - Appends the routine to the append list if necessary and
- ; returns the offset of the routine in the compiled program.
- ; Entry: BX - Pointer to header of canned routine to append.
- ; Exit: AX - Offset of canned routine in COM file.
- ;-----------------------------------------------------------------------------
- include_code proc near
- assume ds:code,es:nothing
- push cx
- push dx
- mov ax,[bx-4] ;Get COM file offset
- or ax,ax ;If zero, routine has not
- jne include_exit ; been appended.
- mov cx,bx ;Save pointer to new routine
- ;
- ;Address the prevous 'last' routine header. Update that header, then use
- ;information in that header to compute the offset of the new routine.
- ;
- xchg bx,last_routine
- mov [bx],cx ;Add code to chain.
- mov ax,[bx-2] ;Compute offset of new routine
- add ax,[bx-4] ; by adding the offset of the
- sub ax,[bx+2] ; prevous routine to its size.
- mov bx,cx
-
- mov cx,[bx+2] ;Get number of called routines.
- add ax,cx
- mov [bx-4],ax ;Set offset of code.
- jcxz include_exit
- shr cx,1 ;If this routine needs other
- add bx,4 ; routines, include them in
- push ax ; the COM file.
- include_1:
- push cx
- push bx
- mov bx,[bx]
- call include_code
- pop bx
- mov [bx],ax
- add bx,2
- pop cx
- loop include_1
- pop ax
- include_exit:
- pop dx
- pop cx
- ret
- include_code endp
- ;-----------------------------------------------------------------------------
- ; PRINTMSG prints the message pointed to by DX to the screen.
- ; Entry: DX - pointer to ASCII message terminated by $
- ;-----------------------------------------------------------------------------
- printmsg proc near
- assume ds:nothing,es:nothing
- push ds
- push cs
- pop ds
- assume ds:code
- mov ah,9 ;Print message
- int 21h
- pop ds
- ret
- printmsg endp
-
- ;-----------------------------------------------------------------------------
- ; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the message.
- ; Entry: DX - pointer to ASCII message terminated by $
- ;-----------------------------------------------------------------------------
- printmsgcr proc near
- assume ds:nothing,es:nothing
- push dx
- call printmsg
- mov dx,offset endmsg
- call printmsg
- pop dx
- ret
- printmsgcr endp
-
- ;-----------------------------------------------------------------------------
- ; HEX2ASC converts a binary number to ASCII and prints it to the screen.
- ; Entry: AX - binary number
- ;-----------------------------------------------------------------------------
- hex2asc proc near
- assume ds:nothing,es:nothing
- push bx
- mov cx,5 ;Allow max of five digits
- hex_loop1:
- xor dx,dx ;Clear high word
- mov bx,10 ;Load number base
- div bx ;Divide by base (10)
- add dl,30h ;Convert to ascii
- push dx ;Save digit on stack
- loop hex_loop1
- mov cx,5 ;Allow max of five digits
- mov bl,"0" ;Set leading zero indicator
- hex_loop2:
- pop dx ;Get digit off stack
- or bl,dl ;Don't print leading zeros.
- cmp bl,"0" ;The first non zero will
- je hex_1 ; change bl to non-zero.
- mov ah,2 ;DOS character output
- int 21h
- hex_1:
- loop hex_loop2
- hex_exit:
- pop bx
- ret
- hex2asc endp
-
- ;-----------------------------------------------------------------------------
- ; LOADBATFILE loads the input BAT file.
- ; Entry: DS:SI - pointer to the name of the file to open
- ; Exit: CF - clear if successful
- ;-----------------------------------------------------------------------------
- loadbatfile proc near
- assume cs:code,ds:code
- push si
- mov dx,si ;Save filename pointer
- mov di,offset outfile_name ;Point DI to buffer to hold
- mov cx,8 ; the output file name.
- loadfile_1:
- lodsb ;Copy the name until the
- cmp al,' ' ; extension is reached.
- je loadfile_10
- cmp al,'.'
- je loadfile_10
- stosb
- loop loadfile_1
- loadfile_10:
- mov si,offset com_string ;Append COM extension to
- movsb ; output file name.
- movsw
- movsw
- mov file_pointer,0 ;Clear file pointer.
- mov si,dx ;Get back filename pointer
- mov bl,1 ;Find end of filename
- call scanline
- dec si
- mov byte ptr [si],0 ;Make filename ASCIIZ.
- mov ax,3d00h ;Open file (Read only)
- int 21h
- jc loadfile_error
- mov bx,ax ;Copy file handle
- ;
- ;Read contents into file buffer.
- ;
- mov ah,3fh ;Read input BAT file into
- mov dx,inbuff_ptr ; memory above stack space
- mov cx,inbuff_size ;Get size of buffer
- int 21h
- cmp ax,cx ;Check if complete file read.
- jbe loadfile_2
- std ;If there is more of the file
- push di ; to read, scan backwards to
- push es ; the end of the last line.
- push cs
- pop es
- mov di,ax
- mov al,13 ;Scan for last CR
- repne scasb
- mov ax,di
- pop es
- pop di
- mov file_pointer,ax
- mov file_handle,bx
- loadfile_2:
- mov word ptr ds:[si],1A0Dh ;Append CR and EOF bytes
- mov cx,ax ;Save new file size
- mov si,dx ;Reset file pointer.
- mov ah,3eh ;Close file.
- int 21h
- mov cs:[file_linecount],0 ;Reset line counter.
- loadfile_exit:
- clc
- loadfile_exit1:
- pop si
- ret
- loadfile_error:
- stc
- mov dx,offset errmsg2 ;Bad filename specified.
- jmp short loadfile_exit1
- loadbatfile endp
-
- ;-----------------------------------------------------------------------------
- ; SCANLINE performs the same function as SCAN4CHAR but keeps track of the
- ; carriage returns.
- ; Entry: SI - pointer to ASCII string
- ; BL - 0 = find next char, 1 = find next space
- ; Exit: AL - first nonspace character
- ; CF - set if carriage return found
- ;-----------------------------------------------------------------------------
- scanline proc near
- call scan4char ;Find the next char.
- jnc scanline_exit
- inc cs:[file_linecount] ;Point to next line.
- stc
- scanline_exit:
- ret
- scanline endp
-
- ;-----------------------------------------------------------------------------
- ; SCAN4CHAR scans a string to find the first character.
- ; Entry: SI - pointer to ASCII string
- ; BL - 0 = find next char, 1 = find next space, 2 = find end of line.
- ; Exit: AL - matching character
- ; SI - pointer to matching character
- ; CF - set if carriage return or EOF found
- ;-----------------------------------------------------------------------------
- scan4char proc near
- assume ds:nothing,es:nothing
- scan4loop:
- lodsb
- cmp al,13 ;Check for carriage return.
- je scan4_eol
- cmp al,1ah ;Check for end of file char.
- jne scan4_1
- scan4_eol:
- stc
- jmp short scan4_exit1
- scan4_1:
- cmp bl,1 ;Check if searching for space,
- je scan4_2 ; character, or end of line.
- ja scan4loop
- cmp al," " ;Check for space or other
- jbe scan4loop ; 'white' characters.
- jmp short scan4_exit
- scan4_2:
- cmp al," " ;Check for characters.
- ja scan4loop
- scan4_exit:
- dec si ;Back up before character
- clc
- scan4_exit1:
- ret
- scan4char endp
-
- ;============================================================================
- ;Routines used by compiled program.
- ;============================================================================
- ;!!--------------------------------------------------------------------------
- ;Code fragments used to call canned routines.
- ;----------------------------------------------------------------------------
- code_call proc near
- mov ax,1234h ;Set address to call routine.
- call ax ;Call canned routine.
- code_call_end = $
- code_call endp
-
- code_jmp proc near
- mov ax,[bp+1234h] ;Set address to call routine.
- jmp ax ;Jump to new offset.
- code_jmp_end = $
- code_jmp endp
-
- code_jc proc near
- jnc code_jc_end ;Jump over long jmp
- jmp initialize ;This jmp will be modified
- code_jc_end = $
- code_jc endp
-
- code_jnc proc near
- jc code_jnc_end ;Skip over long jmp
- jmp initialize ;This jmp will be modified
- code_jnc_end = $
- code_jnc endp
-
- code_jmpdis proc near
- jmp initialize ;This jmp will be modified
- code_jmpdis_end = $
- code_jmpdis endp
-
- code_leasi proc near
- lea si,[bp+1234h] ;Load address of data
- code_leasi_end = $
- code_leasi endp
-
- code_movsi proc near
- mov si,[bp+1234h] ;Load data
- code_movsi_end = $
- code_movsi endp
-
- code_movsiim proc near
- mov si,1234h ;Load immediate data
- code_movsiim_end = $
- code_movsiim endp
-
- code_leadi proc near
- lea di,[bp+1234h] ;Load address of data
- code_leadi_end = $
- code_leadi endp
-
- code_movdi proc near
- mov di,[bp+1234h] ;Load data
- code_movdi_end = $
- code_movdi endp
-
- code_movdiim proc near
- mov di,1234h ;Load immediate data
- code_movdiim_end = $
- code_movdiim endp
-
- ;----------------------------------------------------------------------------
- ;Predefined data needed for all compiled programs.
- ;----------------------------------------------------------------------------
- data_start = $
- code_start dw ? ;Offset of main code routine
- stack_ptr dw ? ;Offset of end of code + stack
- prog_segsize dw ? ;Size of COM prog in paragraphs
- str1_buff_ptr dw ? ;Buffer for parsing strings
- str2_buff_ptr dw ? ;Buffer for parsing strings
- str3_buff_ptr dw ? ;Buffer for For loop variables
- floop_ptr dw ? ;Pointer to for loop string
- file_handle1 dw ? ;Saved handle of std output
- file_handle2 dw ? ;Handle of output file
- file_handle3 dw ? ;Saved handle of std input
- file_handle4 dw ? ;Handle of input file
- label_list_strt dw ? ;Offset into data of 1st label.
- master_env dw ? ;Segment of environment blk
- version_num dw ? ;DOS version number
- proc_rc db ? ;Return code of last program.
- shift_cnt db ? ;Count of shift parameter
- data_end = $
-
- ;----------------------------------------------------------------------------
- ;INIT CODE Routine at the start of all compiled programs.
- ;----------------------------------------------------------------------------
- init_code_off dw 100h ;Pointer to offset in COM file
- init_code_size dw offset init_code_end-offset init_code_start
- init_code_next dw 0 ;Ptr to next routine to append
- init_code_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- init_code_start = $
-
- init_code proc near
- assume cs:code,ds:code,es:code,ss:code
- mov bp,ds:[offset data_start_ptr - offset init_code + 100h]
- mov bp,[bp]
- mov sp,com_stack_ptr ;Move stack pointer
- mov bx,com_prog_size ;Reduce memory allocation
- mov ah,4ah ;Resize memory block
- int 21h
- mov ax,ds:[2ch] ;Get program environment seg
- mov environment_seg,ax ; use unless SET cmd used.
- mov bx,code_start_ptr ;Get starting code offset
- jmp bx ;Jump to start of code.
- init_code endp
- data_start_ptr dw ? ;Offset of data area.
- init_code_end = $
-
- ;----------------------------------------------------------------------------
- ;END CODE Routine appended at the end of all compiled programs.
- ;----------------------------------------------------------------------------
- end_code_off dw 0 ;Pointer to offset in COM file
- end_code_size dw offset end_code_end-offset end_code_start
- end_code_next dw 0 ;Ptr to next routine to append
- end_code_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- end_code_start = $
-
- end_code proc near
- assume cs:code,ds:code
- mov ax,4c00h ;Terminate program
- int 21h
- end_code endp
- end_code_end = $
-
- ;----------------------------------------------------------------------------
- ;ECHO MSG CODE Routine used print a string to the standard output device
- ; Entry: DS:SI - offset of string to print.
- ;----------------------------------------------------------------------------
- echo_msg_off dw 0 ;Pointer to offset in COM file
- echo_msg_size dw offset echo_msg_end-offset echo_msg_start
- echo_msg_next dw 0 ;Ptr to next routine to append
- echo_msg_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- echo_msg_start = $
-
- echo_msg_code proc near
- assume cs:code,ds:code
- mov dl,[si] ;Get character
- inc si
- or dl,dl
- je echo_msg_1
- mov ah,2 ;Print character
- int 21h
- jmp short echo_msg_code
- echo_msg_1:
- ret
- echo_msg_code endp
- echo_msg_end = $
-
- ;----------------------------------------------------------------------------
- ;ECHO STATUS CODE Routine used to report the status of the echo flag.
- ; Entry: AL - Echo flag.
- ;----------------------------------------------------------------------------
- echo_stat_ptr dw 0 ;Pointer to offset in COM file
- echo_stat_size dw offset echo_stat_end-offset echo_stat_start
- echo_stat_next dw 0 ;Ptr to next routine to append
- echo_stat_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- echo_stat_start = $
-
- echo_stat_code proc near
- assume cs:code,ds:code
- call echo_stat_1 ;Push IP on stack
- echo_msg db "ECHO is $"
- echo_on db "on",10,13,"$"
- echo_off db "off",10,13,"$"
- echo_stat_1:
- pop dx ;Pop offset of echo message
- push ax ;Save status of echo flag
- mov ah,9
- int 21h
- add dx,offset echo_on-offset echo_msg ;Point to 'on' msg
- pop ax
- or al,al ;Check status of echo flag
- je echo_report_1
- add dx,offset echo_off-offset echo_on ;Point to 'off' msg
- add dx,5 ;Point to off message.
- echo_report_1:
- mov ah,9 ;Print last part of echo stat
- int 21h
- ret
- echo_stat_code endp
- echo_stat_end = $
-
- ;----------------------------------------------------------------------------
- ;PAUSE CODE Routine used pause execution of the COM file.
- ;----------------------------------------------------------------------------
- pause_ptr dw 0 ;Pointer to offset in COM file
- pause_size dw offset pause_end-offset pause_start
- pause_next dw 0 ;Ptr to next routine to append
- pause_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- pause_start = $
-
- pause_code proc near
- assume cs:code,ds:code
- call pause_1 ;Push IP on stack
- pause_msg db "Strike any key when ready...",13,10,"$"
- pause_1:
- pop dx ;Pop offset of message
- mov ah,9 ;Print message.
- int 21h
-
- mov ah,7 ;Keyboard unfiltered input
- int 21h ; without echo.
- ret
- pause_code endp
- pause_end = $
-
- ;----------------------------------------------------------------------------
- ;SHIFT CODE Routine used shift the input parameters by one.
- ;----------------------------------------------------------------------------
- shift_ptr dw 0 ;Pointer to offset in COM file
- shift_size dw offset shift_end-offset shift_start
- shift_next dw 0 ;Ptr to next routine to append
- shift_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- shift_start = $
-
- shift_code proc near
- assume cs:code,ds:code
- inc byte ptr shift_count ;Inc shift count.
- ret
- shift_code endp
- shift_end = $
-
- ;-----------------------------------------------------------------------------
- ; SCAN_CHAR scans a string to find the first character.
- ; Entry: SI - pointer to ASCII string
- ; DL - 0 = find next char, 1 = find next space
- ; CX - file length
- ; Exit: AL - first nonspace character
- ; CF - set if carriage return found
- ;-----------------------------------------------------------------------------
- scan4_off dw 0 ;Pointer to offset in COM file
- scan4_size dw offset scan4_end - offset scan4_start
- scan4_next dw 0 ;Ptr to next routine to append
- scan4_lnks dw 0
- scan4_start = $
-
- scan_char proc near
- assume ds:nothing,es:nothing
- scan_loop:
- lodsb
- cmp al,9 ;See if char is tab
- je scan_space ;If before, end of line
- cmp al," " ;See if char is space.
- jb scan_eol ;If before, end of line
- je scan_space
- or dl,dl ;Not space, if looking
- jne scan_loop ; for space continue.
- jmp short scan_exit
- scan_space:
- or dl,dl ;Space found, see if looking
- je scan_loop ; for one.
- scan_exit:
- clc
- ret
- scan_eol:
- stc
- ret
- scan_char endp
- scan4_end = $
-
- ;-----------------------------------------------------------------------------
- ; GETMEMBER returns a pointer to the Nth word in a line.
- ; Entry: SI - pointer to line of words
- ; DH - number of the word to return
- ; Exit: SI - pointer to word
- ; CF - Set if word not in line.
- ;-----------------------------------------------------------------------------
- getmember_scan4 equ [bx-6]
- getmember_off dw 0 ;Pointer to offset in COM file
- getmember_size dw offset getmember_end - offset getmember_start
- getmember_next dw 0 ;Ptr to next routine to append
- getmember_lnks dw 2 ;Bytes in the dependancy header
- getmember_start = $
- dw offset scan4_next ;Offset of called routine.
-
- getmember proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call getmember_0
- getmember_0:
- pop bx
- getmember_1:
- xor dl,dl
- call getmember_scan4 ;Find next word
- jc getmember_notfound
- dec dh ;Dec parameter count
- jle getmember_2
- inc dl
- call getmember_scan4 ;Find next space
- jc getmember_exit
- jmp short getmember_1 ;If not done, loop back.
- getmember_2:
- dec si ;Backup to 1st char in word.
- clc
- getmember_exit:
- pop bx
- ret
- getmember_notfound:
- stc
- jmp short getmember_exit
- getmember endp
- getmember_end = $
-
- ;-----------------------------------------------------------------------------
- ; PROCSTRING processes a string to convert any environment variables or
- ; command line variables.
- ; Entry: DS:SI - ASCIIZ string to process
- ; ES:DI - pointer to output buffer.
- ; Exit: DS:SI - pointer to beginning of new ASCIIZ string.
- ; [SI-1] - Length of new string.
- ;-----------------------------------------------------------------------------
- procstr_cmdl equ [bx-8]
- procstr_env equ [bx-6]
- procstr_off dw 0 ;Pointer to offset in COM file
- procstr_size dw offset procstr_end - offset procstr_start
- procstr_next dw 0 ;Ptr to next routine to append
- procstr_lnks dw 4 ;Bytes in the dependancy header
-
- procstr_start = $
- dw offset subparm_next ;Offset of called routines.
- dw offset subenv_next
-
- procstr_code proc near
- assume cs:code,ds:code,es:code
- push bx
- call procstr_0
- procstr_0:
- pop bx
- push di
- push si
- mov ah,255 ;Set size of buffer
- procstr_1:
- lodsb ;Get byte from string
- or al,al ;Check for end of string
- je procstr_exit
- cmp al,"%" ;See if special character
- procstr_jmp:
- je procstr_3 ;Yes, process special char.
- procstr_2:
- stosb ;Store byte from string
- dec ah
- jne procstr_1
- procstr_exit:
- xor al,al ;Force zero byte end.
- stosb
- pop si
- pop di
- mov bl,255
- sub bl,ah
- mov ds:[di-1],bl ;Store length of string
- pop bx
- ret
- ;
- ;A percent sign has been found indicating a 'soft' parameter. Three types of
- ;soft parameters are allowed; command line parameter, environment variable,
- ;and for loop parameter.
- ;
- procstr_3:
- lodsb ;Get next character
- dec cx
- cmp al,"%" ;If double %, include one
- je procstr_2 ; in string.
- cmp al,7fh ;See if for loop var
- jne procstr_32
- push si
- mov si,forloop_ptr ;Get ptr to for loop string
- procstr_30:
- lodsb
- cmp al,0 ;If zero, end of string
- je procstr_31
- stosb
- dec ah ;Dec buffer size counter
- jne procstr_30 ;If buffer not full, continue
- procstr_31:
- pop si ;Get back source string pointer
- jmp short procstr_4
- procstr_32:
- mov dh,al ;Copy and check to see if
- sub dh,"0" ; the next char is a number.
- jb procstr_5 ; If so, assume a line
- cmp dh,9 ; parameter.
- ja procstr_5
- call procstr_cmdl ;Call cmd line param routine
- procstr_4:
- or ah,ah
- jne procstr_1
- jmp short procstr_exit ;If at end of string, done
- procstr_5:
- dec si ;Backup to 1st character
- inc cx
- call procstr_env
- jmp short procstr_4
- procstr_code endp
- procstr_end = $
-
- ;-----------------------------------------------------------------------------
- ; SUBLINEPARAM substitutes a parameter from the command line.
- ; Entry: ES:DI - pointer to buffer to copy the line parameter
- ; DH - binary number of the line parameter
- ; AH - size of buffer
- ; Exit: ES:DI - pointer to byte after the parameter in the buffer
- ; CX - remaining length of the buffer
- ;-----------------------------------------------------------------------------
- subparm_getmem equ [bx-6]
- subparm_off dw 0 ;Pointer to offset in COM file
- subparm_size dw offset subparm_end - offset subparm_start
- subparm_next dw 0 ;Ptr to next routine to append
- subparm_lnks dw 2 ;Bytes in the dependancy header
- subparm_start = $
- dw offset getmember_next ;Offset of called routine.
-
- sublineparam proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call sublineparam_1
- db "DOS2X",0 ;Dummy %0 parameter for DOS 2x
- sublineparam_1:
- pop bx
- push cx
- push si
- push ds
- mov si,80h ;Get ptr to cmd line
- xor cx,cx
- mov cl,[si] ;Get number of chars in buffer.
- inc si ;Point to data
- add dh,ds:shift_count ;Add in shift count.
- or dh,dh ;Check count of param to find.
- jnz sublineparam_12
- ;
- ;For parameter 0, attempt to look in the env block for the name of the prog.
- ;
- push ax ;Save buffer size in AH
- mov ah,30h ;Get DOS version
- int 21h ;If DOS 2.x, program nane not
- cmp al,2 ; in the env segment. Use
- pop ax
- ja sublineparam_10 ; dunny name instead.
- lea si,[bx] ;Point to dummy parameter
- jmp short sublineparam_2
- sublineparam_10:
- push es
- push di
- mov es,ds:[2ch] ;Get segment of local env
- xor al,al
- xor di,di
- mov cx,8000h
- sublineparam_11:
- repne scasb ;Find double zero
- scasb
- jne sublineparam_11
- scasw ;Scan to name
- mov si,di ;Copy pointer to name
- pop di
- pop es
- mov ds,ds:[2ch]
- jmp short sublineparam_2
- sublineparam_12:
- call subparm_getmem ;Get pointer to proper word.
- jc sublineparam_exit
- sublineparam_2:
- lodsb ;Get character from parameter
- cmp al," " ;If space, parameter done
- jbe sublineparam_exit
- stosb
- dec ah ;Dec buffer size counter
- jnz sublineparam_2
- sublineparam_exit:
- pop ds
- pop si
- pop cx
- pop bx
- ret
- sublineparam endp
- subparm_end = $
- ;-----------------------------------------------------------------------------
- ; SUBENVVAR substitutes a parameter from the program environment block.
- ; Entry: DS:SI - pointer to enviroment variable.
- ; ES:DI - pointer to buffer.
- ; AH - size of buffer.
- ; Exit: ES:DI - pointer to byte after the parameter in the buffer
- ; DS:SI - pointer to the character after the line parameter number
- ; CX - remaining free bytes in the buffer.
- ;-----------------------------------------------------------------------------
- subenv_srchenv equ [bx-6]
- subenv_off dw 0 ;Pointer to offset in COM file
- subenv_size dw offset subenv_end-offset subenv_start
- subenv_next dw 0 ;Ptr to next routine to append
- subenv_lnks dw 2 ;Bytes in the dependancy header
- subenv_start = $
- dw offset searchenv_next ;Call to search environment blk
-
- subenvvar proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call subenvvar_0
- subenvvar_0:
- pop bx
- push ds
- ;
- ;Compute the length of the variable name.
- ;
- mov cx,255
- push di ;Save pointer to internal buff
- mov di,si ;Compute the length of the
- mov dx,cx ; environment variable by
- mov al,"%" ; searching for the trailing
- repne scasb ; % sign.
- sub dx,cx ;Compute length of variable.
- dec dx ;Subtract % byte from length.
- mov cx,di
- pop di
- push cx ;Save ptr to end of var
- call subenv_srchenv ;Search environment block.
- jc short subenvvar_exit ;CF set, variable not found.
- ;
- ;Environment variable found. Substitute into string.
- ;
- subenvvar_1:
- lodsb ;Get env var character
- or al,al ;Check for end of string
- je subenvvar_exit
- stosb ;Save character in string
- dec ah ;Dec buffer size count.
- jne subenvvar_1 ;If buffer not full, continue
- subenvvar_exit:
- pop si ;Restore string pointer
- pop ds ;Restore segment register
- pop bx
- ret
- subenvvar endp
- subenv_end = $
-
- ;-----------------------------------------------------------------------------
- ; SEARCH_ENV scans the environment block for a string.
- ; Entry: DS:SI - pointer to ASCII string
- ; DX - length of string
- ; Exit: DS:SI - points to first character of environment string
- ; CF - clear if string found
- ;-----------------------------------------------------------------------------
- searchenv_off dw 0 ;Pointer to offset in COM file
- searchenv_size dw offset searchenv_end - offset searchenv_start
- searchenv_next dw 0 ;Ptr to next routine to append
- searchenv_lnks dw 0
- searchenv_start = $
-
- search_env proc near
- assume ds:nothing,es:nothing
- push bx
- push cx
- push di
- push es
- mov es,environment_seg ;Get seg of environment blk
- xor di,di ;Point ES:DI to environment.
- mov bx,si ;Save pointer to var name
- search_env_1:
- mov si,bx ;Get back ptr to var name.
- mov cx,dx ;Compare env var to var in
- repe cmpsb ; string.
- je search_env_2 ;Variable found, exit loop
- xor al,al ;Find next environment var.
- mov cx,-1 ;Scan the entire segment.
- repne scasb
- cmp byte ptr es:[di],0 ;If double zero, end of env
- jne search_env_1 ; block. else, loop back.
- search_env_not_found:
- mov si,di ;Point SI to end of env data
- push es
- pop ds
- stc
- jmp short search_env_exit
- search_env_2:
- ;
- ;Environment variable found. Point DS:SI to the string.
- ;
- mov si,di
- push es ;DS:SI points to env string
- pop ds
- search_env_3:
- lodsb ;Move environment pointer past
- cmp al,"=" ; the equals sign.
- jne search_env_3
- cmp byte ptr [si],0
- je search_env_not_found
- search_env_4:
- lodsb ;Move pointer to first
- or al,al ; non-space character.
- jb search_env_5
- cmp al," "
- jb search_env_4
- search_env_5:
- dec si
- clc
- search_env_exit:
- pop es
- pop di
- pop cx
- pop bx
- ret
- search_env endp
- searchenv_end = $
-
- ;----------------------------------------------------------------------------
- ;EXTERNAL CMD Routine used to launch programs from the COM file.
- ; Entry DS:SI - Pointer to the ASCIIZ program name
- ; ES:DI - Pointer to the ASCIIZ command line tail
- ;----------------------------------------------------------------------------
- extern_intcmd equ [bx-14]
- extern_echomsg equ [bx-12]
- extern_parspath equ [bx-10]
- extern_launch equ [bx-8]
- extern_ifexits equ [bx-6]
- extern_pathcnt equ [bx]
- extern_path_var equ [bx+1]
- extern_file_ext equ [bx+6]
- extern_filename equ [bx+15]
- extern_filetail equ [bx+17]
- extern_lostmsg equ [bx+19]
- extern_cmdparm equ [bx+45]
- external_ptr dw 0 ;Pointer to offset in COM file
- external_size dw offset external_end - offset external_start
- external_next dw 0 ;Ptr to next routine to append
- external_lnks dw 10 ;Bytes in the dependancy header ;Number of routines called
- external_start = $
- dw intcmd_next ;Call to launch COMMAND.COM
- dw echo_msg_next ;Call to display string
- dw parsepath_next ;Call to get part of path
- dw launch_next ;Call execute file
- dw ifexist_next ;Call to find file
-
- external_code proc near
- assume cs:code,ds:code
- push bx
- call external_0
- db 0 ;Cnt to track path search.
- db "PATH="
- db "COMEXEBAT"
- dw 0 ;Pointer to filename
- dw 0 ;Pointer to command line tail
- db "Bad command or filename",13,10,0
- db "/C "
- external_0:
- pop bx ;Get pointer to local vars.
- mov extern_filename,si ;Save ptr to file name
- mov extern_filetail,di ;Save ptr to command line tail
- mov dx,string2_buff ;Get pointer to free buffer.
- add dx,4 ;Make room for /C if needed.
- ;Parse path to generate filename.
- external_1:
- mov di,dx ;Get ptr to start of buffer
- xor cx,cx ;Check to see if we need to
- or cl,extern_pathcnt ; check the directorys in
- je external_2 ; the path.
- mov si,extern_filename
- call extern_parspath
- jnc external_2 ;If we have checked all
- lea si,extern_lostmsg ; directories in the path,
- call extern_echomsg ; display file not found msg.
- jmp short external_exit
-
- ;Append filename to the end of the path.
- external_2:
- mov cx,8
- external_3:
- lodsb
- cmp al,' ' ;See if end of word
- jbe external_4
- cmp al,'.' ;See if end of filename
- je external_4
- stosb
- loop external_3
- external_4:
- mov al,'.' ;Append '.' to filename
- stosb
- lea si,extern_file_ext ;Get pointer to extensions
- mov cx,3 ;3 extension types COM EXE BAT
- external_5:
- movsw ;Append extension to filename
- movsb
- xor al,al ;Termainate with zero
- stosb
- push dx
- push si
- push cx
- mov si,dx ;Get ptr to start of name
- call extern_ifexits ;Search for file
- pop cx
- pop si
- pop dx
- jnc external_6
- sub di,4 ;Backup to file extension
- loop external_5
- inc byte ptr extern_pathcnt ;Look in the next path str
- jmp short external_1
- external_6:
- cmp cx,1 ;See if BAT extension
- jne external_8
- lea si,extern_cmdparm ;Get pointer to /C
- sub dx,4
- mov di,dx ;Get ptr to string buffer
- movsw ;Copy /C param
- movsb
- xor al,al
- mov cx,252
- repne scasb ;Find end of filename
- mov byte ptr [di-1],' ' ;Fill in zero with space
- mov si,extern_filetail ;Get ptr to command line tail
- cmp [si-1],cl
- ja external_7
- mov cl,[si-1] ;Get length of cmd line tail
- external_7:
- rep movsb
- mov byte ptr [di],13 ;Append CR to cmd line.
- mov si,dx ;Get pointer to BAT filename
- mov ax,di ;Compute length of cmd line.
- sub ax,dx
- mov [si-1],al
- call extern_intcmd ;Launch COMMAND.COM
- jmp short external_exit
- external_8:
- mov di,extern_filetail ;Get ptr to command line tail
- dec di ;Back up to buffer length
- mov si,dx ;Get ptr to start of name
- call extern_launch ;Execute program
- external_exit:
- pop bx
- ret
- external_code endp
- external_end = $
-
- ;-----------------------------------------------------------------------------
- ; PARSEPATH Parses the PATH and returns a qualified directory from the path.
- ; Entry: ES:DI - pointer to destination buffer.
- ; CX - index into the path variable. (zero based.)
- ; Exit: ES:DI - pointer to ASCIIZ destination filename.
- ; CF - Set if past end of the path
- ;-----------------------------------------------------------------------------
- parsepath_srenv equ [bx-6]
- parsepath_off dw 0 ;Pointer to offset in COM file
- parsepath_size dw offset parsepath_end - offset parsepath_start
- parsepath_next dw 0 ;Ptr to next routine to append
- parsepath_lnks dw 2
- parsepath_start = $
- dw offset searchenv_next ;Call to search env block
-
- parsepath proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call parsepath_1
- db "PATH"
- parsepath_1:
- pop bx
- push dx
- push si
- mov dx,4 ;Length of PATH string
- mov si,bx
- call getcom_srchenv ;PATH var ptr return in DS:SI
- parsepath_2:
- dec cx ;Dec path segment count
- jcxz parsepath_4
- parsepath_3:
- lodsb ;Get character
- or al,al ;See if end of path string
- je parsepath_notfound
- cmp al,';' ;See if end of path segment
- jne parsepath_3
- jmp short parsepath_2
- parsepath_4:
- lodsb
- cmp al,';' ;See if end of path segment
- je parsepath_5
- or al,al ;See if end of path
- je parsepath_5
- stosb
- jmp short parsepath_4
- parsepath_5:
- push cs
- pop ds
- cmp byte ptr es:[di-1],'\' ;Append \ if necessary.
- je parsepath_6
- mov al,'\'
- stosb
- parsepath_6:
- clc
- parsepath_exit:
- pop si
- pop dx
- pop bx
- ret
- parsepath_notfound:
- stc
- jmp short parsepath_exit
- parsepath endp
- parsepath_end = $
-
- ;-----------------------------------------------------------------------------
- ; INTCMD Launches the shell ,usually COMMAND.COM, to run an internal command.
- ; Entry DS:SI - pointer to the ASCIIZ internal command to run.
- ;-----------------------------------------------------------------------------
- intcmd_launch equ [bx-8]
- intcmd_getcom equ [bx-6]
- intcmd_off dw 0 ;Pointer to offset in COM file
- intcmd_size dw offset intcmd_end - offset intcmd_start
- intcmd_next dw 0 ;Ptr to next routine to append
- intcmd_lnks dw 4
- intcmd_start = $
- dw offset launch_next ;Call to load and run program.
- dw offset getcom_next ;Call to find shell name.
-
- intcommand proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call intcmd_1
- intcmd_1:
- pop bx ;Get pointer to sub calls.
- mov di,si ;Copy ptr to command
- dec di ;Back up to cmd line size.
- push ds
- call intcmd_getcom ;Get comspec string.
- call cs:intcmd_launch ;Run program.
- pop ds
- pop bx
- ret
- intcommand endp
- intcmd_end = $
-
- ;-----------------------------------------------------------------------------
- ; GETCOMSPEC Gets the name of the shell program running
- ; Exit: DS:SI - pointer to the ASCIIZ name of the shell porgram.
- ;-----------------------------------------------------------------------------
- getcom_srchenv equ [bx-6]
- getcom_off dw 0 ;Pointer to offset in COM file
- getcom_size dw offset getcom_end - offset getcom_start
- getcom_next dw 0 ;Ptr to next routine to append
- getcom_lnks dw 2
- getcom_start = $
- dw offset searchenv_next ;Call to search environment blk
-
- getcomspec proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call getcom_1
- getcom_str db "COMSPEC"
- getcom_1:
- pop bx
- mov dx,offset getcom_1 - offset getcom_str
- mov si,bx
- call getcom_srchenv ;Get pointer to comspec string
- pop bx
- ret
- getcomspec endp
- getcom_end = $
-
- ;----------------------------------------------------------------------------
- ;LAUNCH PROG Routine used to load and run programs.
- ; Entry DS:SI - pointer to the program name to run.
- ; ES:DI - pointer to the command line tail.
- ; Exit return code variable set.
- ;----------------------------------------------------------------------------
- launch_fcb equ [bx]
- launch_ptr dw 0 ;Pointer to offset in COM file
- launch_size dw offset launch_end - offset launch_start
- launch_next dw 0 ;Ptr to next routine to append
- launch_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- launch_start = $
-
- launch_code proc near
- assume cs:code,ss:code
- push bx
- call launch_1 ;Push IP on stack
- db 0 ;Dummy FCB for program
- db "DUMMY FCB"
- db 0,0,0,0
- launch_1:
- pop bx ;Get pointer to local vars.
-
- push ds
- push es ;Save stack ptr since it is not
- mov com_stack_ptr,sp ; saved under DOS 2.x.
-
- push cs ;Create Parameter block on
- lea dx,launch_fcb ; the stack. Start with 2nd
- push dx ; FCB.
- push cs ;Push ptr to 1st FCB
- push dx
- push cs ;Push ptr to command line tail.
- push di
- xor ax,ax ;Use parent env block.
- push ax
- mov bx,sp ;Copy pointer to parameter blk
-
- mov ax,4b00h ;DOS EXEC program.
- mov dx,si ;Get pointer to filename
- int 21h
- mov bp,offset data_start_ptr - offset init_code + 100h
- mov bp,cs:[bp]
- mov bx,cs ;Reload BP to access local data
- cli
- mov ss,bx ;Restore stack
- mov sp,com_stack_ptr
- sti
- pop es
- pop ds
- ;Get return code
- mov ah,4dh ;Get return code
- int 21h
- mov process_rc,al ;Save
- pop bx
- ret
- launch_code endp
- launch_end = $
-
- ;----------------------------------------------------------------------------
- ;GOTO Routine to jump to a label pointed to by a cmd line parameter or
- ; environment variable.
- ; Entry DS:SI - pointer to label to find.
- ; DI - Wait flag/ptr. If <> 0, put goto address at pointer.
- ; Exit This routine does not return unless the label is not found.
- ;----------------------------------------------------------------------------
- goto_echomsg equ [bx-7]
- goto_lblsrch equ [bx-5]
- goto_ptr dw 0 ;Pointer to offset in COM file
- goto_size dw offset goto_end - offset goto_start
- goto_next dw 0 ;Ptr to next routine to append
- goto_lnks dw 4 ;Bytes in the dependancy header ;Number of routines called
- goto_start = $
- dw echo_msg_next ;Used to print error msg
- dw lblsrch_next ;Used to find label
-
- goto_code proc near
- assume cs:code,ds:code
- call goto_1
- db 8 dup (" ")
- db " Label not found",13,10,0
- goto_1:
- pop bx
- push di ;Save wait flag/pointer
- mov di,bx ;Load label into error msg
- xor dx,dx ;Get size of label as it is
- mov cx,8 ; copied into error msg.
- goto_2:
- lodsb
- cmp al," "
- jbe goto_4
- cmp al,'a'
- jb goto_3
- and al,0dfh ;Capitalize label
- cmp al,'Z'
- ja goto_4
- goto_3:
- stosb
- inc dx
- loop goto_2
- goto_4:
- mov cx,dx ;Get size of label
- mov si,bx ;Get pointer to label
- mov di,com_label_start ;Get ptr to start of label list
- add di,bp ;Add offset of data
- push bx ;Save ptr to msg
- call goto_lblsrch ;Call search routine
- pop dx ;Restore ptr to message
- pop si ;Restore Wait flag/pointer
- jc goto_5 ;CF set, label not found.
- mov ax,[bx+2] ;Get destination ptr
- or si,si ;See if delay flag <> 0
- je goto_41 ;If 0, no delay
- mov [bp+si],ax ;Save ret addr at pointer
- ret
- goto_41:
- pop ax ;Remove return address
- push [bx+2] ;Push new return address
- goto_exit:
- ret
- goto_5:
- mov bx,dx ;Set addressability to call
- call goto_echomsg ;Print error message.
- ret
- goto_code endp
- goto_end = $
-
- ;----------------------------------------------------------------------------
- ;GOTO DLY Routine used if goto statment is inside a FOR loop. Since a for
- ; loop cannot be exited before it ends, this routine checks to see if
- ; the GOTO statment was ever executed. If so, we now can jump.
- ; Entry DS:SI - pointer to destination pointer. 0 = no jump.
- ; Exit This routine does not return unless the ptr = 0
- ;----------------------------------------------------------------------------
- gotodly_ptr dw 0 ;Pointer to offset in COM file
- gotodly_size dw offset gotodly_end - offset gotodly_start
- gotodly_next dw 0 ;Ptr to next routine to append
- gotodly_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- gotodly_start = $
-
- gotodly_code proc near
- assume cs:code,ds:code
- xor ax,ax ;Get pointer, test if zero.
- or ax,[si] ;If zero, return. If not
- je gotodly_exit ; push the new destination
- pop bx ; on the stack and return.
- push ax
- gotodly_exit:
- ret
- gotodly_code endp
- gotodly_end = $
-
- ;----------------------------------------------------------------------------
- ;LABEL SEARCH Routine to search list of labels to determine goto destination.
- ; Entry ES:DI - pointer to the first entry in the list. (Assume ES = DS)
- ; DS:SI - pointer to label to find.
- ; CX - Length of label
- ; Exit BX - pointer to matching list entry, or last entry if not found.
- ; CF - Set if label not found.
- ;----------------------------------------------------------------------------
- lblsrch_ptr dw 0 ;Pointer to offset in COM file
- lblsrch_size dw offset lblsrch_end - offset lblsrch_start
- lblsrch_next dw 0 ;Ptr to next routine to append
- lblsrch_lnks dw 0 ;Bytes in the dependancy header ;Number of routines called
- lblsrch_start = $
-
- lblsrch_code proc near
- assume cs:code,ds:code
- push si
- mov dx,si ;Save ptr to label
- mov ax,cx ;Save label length
- mov bx,di ;Get ptr to list
- lblsrch_1:
- mov di,bx
- add di,4 ;Move to label string
- mov si,dx ;Get ptr to new label
- mov cx,ax ;Get length of label
- cmp [di],cl ;Compare lengths of the labels
- jne lblsrch_2
- inc di ;Skip past length byte
- repe cmpsb ;Compare labels.
- je lblsrch_4
- lblsrch_2:
- cmp word ptr [bx],-1 ;See if at end of list
- je lblsrch_3
- add bx,[bx] ;Point to next label
- jmp short lblsrch_1
- lblsrch_3:
- stc ;No label found.
- jmp short lblsrch_exit
- lblsrch_4:
- clc ;Label found
- lblsrch_exit:
- pop si
- ret
- lblsrch_code endp
- lblsrch_end = $
-
- ;-----------------------------------------------------------------------------
- ; IFEQUAL Compares two strings.
- ; Entry: DS:SI - Pointer to first ASCIIZ String
- ; ES:DI - Pointer to second ASCIIZ String
- ; CX - Length of strings.
- ; Exit: CF - Clear if equal
- ;-----------------------------------------------------------------------------
- ifequal_off dw 0 ;Pointer to offset in COM file
- ifequal_size dw offset ifequal_end - offset ifequal_start
- ifequal_next dw 0 ;Ptr to next routine to append
- ifequal_lnks dw 0
- ifequal_start = $
-
- ifequal proc near
- assume cs:code,ds:code,es:code,ss:code
- xor cx,cx
- mov cl,[si-1] ;Get size of string
- cmp cl,[di-1] ;Compare sizes of strings
- jne ifequal_notequal
- rep cmpsb ;Compare strings
- jne ifequal_notequal
- clc
- ret
- ifequal_notequal:
- stc
- ret
- ifequal endp
- ifequal_end = $
-
- ;-----------------------------------------------------------------------------
- ; IFEXIST Determines if a file exists.
- ; Entry: DS:SI - Pointer to ASCIIZ filename.
- ; DI - Pointer to buffer for disk transfer area.
- ; Exit: CF - Clear if file exists
- ; DI - IF file exists, points to filename.
- ;-----------------------------------------------------------------------------
- ifexist_off dw 0 ;Pointer to offset in COM file
- ifexist_size dw offset ifexist_end - offset ifexist_start
- ifexist_next dw 0 ;Ptr to next routine to append
- ifexist_lnks dw 0
- ifexist_start = $
-
- ifexist proc near
- assume cs:code,ds:code,es:code,ss:code
- mov dx,di
- mov ah,1ah ;Set DTA
- int 21h
-
- mov dx,si ;Copy pointer to filename
- xor cx,cx ;Normal attributes
- mov ah,4eh ;DOS Find First
- int 21h
- jc ifexist_exit
- add di,1eh ;Point DI to filename in DTA
- clc
- ifexist_exit:
- ret
- ifexist endp
- ifexist_end = $
-
- ;-----------------------------------------------------------------------------
- ; IFERRLEV Compares the value passed with the return code of the last
- ; program executed.
- ; Entry: SI - Pointer to ASCIIZ Error level.
- ; Exit: CF - Clear if process error level above or equal to SI
- ;-----------------------------------------------------------------------------
- iferrlev_off dw 0 ;Pointer to offset in COM file
- iferrlev_size dw offset iferrlev_end - offset iferrlev_start
- iferrlev_next dw 0 ;Ptr to next routine to append
- iferrlev_lnks dw 0
- iferrlev_start = $
-
- iferrlev proc near
- assume cs:code,ds:code,es:code,ss:code
- xor ax,ax ;Convert ASCIIZ number into
- mov bx,ax ; decimal
- iferrlev_1:
- mov bl,[si] ;Convert error level number
- sub bl,'0' ; from ASCII to decimal.
- jb iferrlev_2
- cmp bl,9
- ja iferrlev_2
- mov dx,10
- mul dx
- jc iferrlev_2
- add ax,bx ;Add in digit
- inc si
- jmp short iferrlev_1
- iferrlev_2:
- cmp process_rc,al ;Compare to last program
- ret
- iferrlev endp
- iferrlev_end = $
-
- ;-----------------------------------------------------------------------------
- ; FORLOOP Processes commands in a FOR loop.
- ; Entry: SI - Pointer to ASCIIZ set of parameters.
- ; DI - Pointer loop structure in data area
- ; LoopCnt db 0 Member of the set to use
- ; FirstFlag db 0 Indicates Find first/next
- ; Exit: CF - Set if FOR loop complete.
- ;-----------------------------------------------------------------------------
- forloop_getmem equ [bx-6]
- forloop_off dw 0 ;Pointer to offset in COM file
- forloop_size dw offset forloop_end - offset forloop_start
- forloop_next dw 0 ;Ptr to next routine to append
- forloop_lnks dw 2
- forloop_start = $
- dw getmember_next
-
- forloop proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call forloop_0
- db 43 dup (0) ;Used for DTA
- forloop_0:
- pop bx
- ;
- ;Set DTA. If 2nd time or later time looping on a member, use find next to
- ;determine the string for this time through the loop.
- ;
- lea dx,[bx]
- mov ah,1ah ;Set DTA
- int 21h
-
- cmp byte ptr [di+1],0 ;See if first time for member
- je forloop_1
- mov ah,4fh ;Find next file
- int 21h
- jc forloop_1 ;Not found, go to next member
- lea dx,[bx+1eh] ;Point to filename in DTA
- jmp short forloop_notdone ;Execute loop body
- ;
- ;First time with this member of the set, if wildcards are in the member,
- ;use DOS find first to get the loop string.
- ;
- forloop_1:
- mov byte ptr [di+1],0 ;Clear first/next flag
- inc byte ptr [di] ;Look at next member of the set
- mov dh,[di] ;Get loop count
- call forloop_getmem ;Get member of set. If no
- jc forloop_done ; more members, loop done.
- mov dx,si ;Save pointer to member
- xor ah,ah ;Clear wildcard flag
- forloop_2:
- lodsb ;Scan set member to check for
- cmp al,' ' ; any wildcard chars.
- jbe forloop_4
- cmp al,'?'
- jne forloop_3
- inc ah ;Set wildcard found flag
- forloop_3:
- cmp al,'*'
- jne forloop_2
- inc ah ;Set wildcard found flag
- jmp short forloop_2
- forloop_4:
- mov byte ptr [si-1],0 ;Set zero terminator.
- or ah,ah ;If no wildcards, execute
- je forloop_notdone ;Execute loop body
- mov byte ptr [di+1],1 ;Set first/next flag
- xor cx,cx ;Normal attributes
- mov ah,4eh ;DOS find first
- int 21h
- jc forloop_1 ;If not found, get next member
- lea dx,[bx+1eh] ;Set ptr to filename in DTA
- forloop_notdone:
- mov forloop_ptr,dx ;Set loop data ptr
- clc
- forloop_exit:
- pop bx
- ret
- forloop_done:
- mov word ptr [di],0 ;Clear loop variables
- stc
- jmp short forloop_exit
- forloop endp
- forloop_end = $
-
- ;-----------------------------------------------------------------------------
- ; FINDENV Finds the master environment block.
- ; Exit: Variable Environment_seg set with segment of master environment.
- ;-----------------------------------------------------------------------------
- findenv_dosver equ [bx+7]
- findenv_cmdname equ [bx]
- findenv_off dw 0 ;Pointer to offset in COM file
- findenv_size dw offset findenv_end - offset findenv_start
- findenv_next dw 0 ;Ptr to next routine to append
- findenv_lnks dw 0
- findenv_start = $
-
- findenv proc near
- assume cs:code,ds:code,es:code,ss:code
- push bx
- call findenv_0
-
- db "COMMAND"
- dw 0
- findenv_0:
- pop bx
- push es
-
- mov ax,ds:[2ch] ;Get default env
- cmp environment_seg,ax ;Check to see if already
- jne findenv_8 ; found.
-
- mov ah,30h ;Get dos Version
- int 21h
- xchg al,ah
- mov findenv_dosver,ax
-
- mov ah,52h ;get address of first MCB
- int 21h
- mov ax,es:[bx-2] ;point ES to MCB
- mov cx,20 ;Allow only 20 loops.
- findenv_1:
- mov es,ax
- cmp byte ptr es:[0],"M" ;check for mcb signature
- jne short findenv_8
- inc ax ;point AX to memory block
- cmp ax,es:[1] ;See if this is a PSP block
- je findenv_4
- findenv_2:
- add ax,es:[3] ;Get size of memory block
- loop findenv_1
- jmp short findenv_8
- findenv_4:
- cmp word ptr findenv_dosver,0a00h ;If OS/2, use DOS 3.3 method.
- jae findenv_5
- cmp word ptr findenv_dosver,0400h;If DOS 4.00 or greater,
- jb findenv_5 ; COMMAND.COM may not be the
- push ds ; first program loaded. Look
- lea si,findenv_cmdname ; at the name of the program
- mov di,8 ; stored in the last 8 bytes
- mov cx,7 ; of the memory control
- repe cmpsb ; block. If the string
- pop ds ; "COMMAND" isn't found,
- jne findenv_2 ; keep looking.
- findenv_5:
- mov es,ax
- mov bx,es:[2ch] ;Get seg of prog environment
- mov ax,bx
- dec bx
- mov es,bx
- cmp byte ptr es:[0],"M" ;See if valid memory block
- je findenv_7
- mov dx,ax ;Save COMMAND PSP segment
- dec ax ;Point back to mcb
- mov es,ax
- findenv_6:
- add ax,es:[3] ;Get size of memory block
- inc ax
- cmp es:[1],dx ;See if owned by CMD.COM
- je findenv_7
- mov es,ax
- loop findenv_6
- findenv_7:
- mov environment_seg,ax
- findenv_8:
- pop es
- pop bx
- ret
- findenv endp
- findenv_end = $
-
- ;-----------------------------------------------------------------------------
- ; SET_ENV Sets/resets environment variables.
- ; Entry: DS:SI - pointer to ASCII string containing the environment variable
- ; and, optionally, the string to assign.
- ;-----------------------------------------------------------------------------
- setenv_findenv equ [bx-10]
- setenv_echo equ [bx-8]
- setenv_serchenv equ [bx-6]
- setenv_fullmsg equ [bx]
- setenv_off dw 0 ;Pointer to offset in COM file
- setenv_size dw offset setenv_end - offset setenv_start
- setenv_next dw 0 ;Ptr to next routine to append
- setenv_lnks dw 6
- setenv_start = $
- dw offset findenv_next ;Call to find the master env
- dw offset echo_msg_next ;Call to print line.
- dw offset searchenv_next ;Call to search environment blk
-
- set_env proc near
- assume ds:nothing,es:nothing
- push bx
- call setenv_1
- db "Out of environment space",13,10,0
- setenv_1:
- pop bx ;Set up local addressing
- call setenv_findenv ;Find master env block
- push bp
- push es
- mov cx,255
- xor dx,dx
- push si ;Save ptr to new env var
- mov di,si
- setenv_2:
- lodsb
- cmp al,"=" ;Scan until end of variable
- je setenv_4 ; found.
- cmp al,'a'
- jb setenv_3
- and al,0dfh ;Capitalize variable
- cmp al,'Z'
- ja setenv_4
- setenv_3:
- stosb
- inc dx
- loop setenv_2
- setenv_4:
- pop si
- mov ax,si
- inc di
- cmp byte ptr cs:[di]," " ;If nothing past '=' then
- jae setenv_41 ; simply erase var from env.
- xor ax,ax
- setenv_41:
- push ax
- call setenv_serchenv ;Get pointer to variable
- pop dx ;Save ptr to var
- push ds
- pop es
- mov di,si ;Copy pointer to variable
- jc setenv_61
-
- xor al,al ;Scan backwards to find start
- std ; of var name
- mov cx,256
- repne scasb
- inc di
- inc di
- push di
- cld ;Scan forward to find end of
- mov cx,256 ; variable.
- repne scasb
- mov si,di
- pop di
- xor ah,ah
- setenv_5:
- lodsb ;Move byte from past var to
- stosb ; cover up current assignment
- or ah,al ;If two zeros in a row then
- je setenv_6 ; end of env vars.
- mov ah,al
- jmp short setenv_5
- setenv_6:
- dec di ;Back up before last zero
- setenv_61:
- push cs
- pop ds
- mov si,dx ;Get back ptr to env var
- or si,si ;See if var assignment
- je setenv_9
-
- push es ;Get size of the environment
- mov ax,es ; block by reading the size
- dec ax ; in the memory control block.
- mov es,ax
- mov bp,es:[3]
- mov cl,4
- shl bp,cl ;Convert to bytes.
- dec bp
- dec bp
- pop es
- setenv_7:
- lodsb ;Copy new env var
- stosb
- or al,al ;Check for end of variable.
- je setenv_8
- cmp di,bp ;Check for end of env block.
- jb setenv_7
- push cs
- pop ds
- lea si,setenv_fullmsg ;If environment block full,
- call setenv_echo ; print message.
- xor al,al ;Terminate with zeros.
- stosb
- setenv_8:
- xor al,al
- stosb
- setenv_9:
- pop es
- pop bp
- pop bx
- ret
- set_env endp
- setenv_end = $
-
- ;-----------------------------------------------------------------------------
- ; REDIROO Opens a file for output redirection.
- ; Entry: DS:SI - pointer to ASCII filename to open.
- ; DI - 0 open new file, 1 append to existing file.
- ;-----------------------------------------------------------------------------
- rediroo_off dw 0 ;Pointer to offset in COM file
- rediroo_size dw offset rediroo_end - offset rediroo_start
- rediroo_next dw 0 ;Ptr to next routine to append
- rediroo_lnks dw 0
- rediroo_start = $
-
- rediroo proc near
- assume ds:nothing,es:nothing
-
- mov word ptr stdout_hdl,-1 ;Clear handle
- mov dx,si ;Get ptr to outfile file
- xor cx,cx ;Normal attributes
- mov ax,3c02h ;Create file
- or di,di ;See if append or new file
- je rediroo_2
- inc ah ;Open file
- rediroo_2:
- int 21h
- jc rediroo_exit
- mov bx,ax ;Copy file handle
- or di,di
- je rediroo_3
- mov ax,4202h ;Move file ptr to end of file
- xor dx,dx
- mov cx,dx
- int 21h
- jc rediroo_exit
- rediroo_3:
- mov outfile_hdl,bx ;Save output file handle
- push bx
- mov ah,45h ;Duplicate output handle
- mov bx,1 ;Std output handle
- int 21h
- mov stdout_hdl,ax ;Save dup std output handle
-
- mov cx,1
- pop bx
- mov ah,46h ;Force dup file handle
- int 21h
- rediroo_exit:
- ret
- rediroo endp
- rediroo_end = $
-
- ;-----------------------------------------------------------------------------
- ; REDIRCO Closes a file used for output redirection.
- ;-----------------------------------------------------------------------------
- redirco_off dw 0 ;Pointer to offset in COM file
- redirco_size dw offset redirco_end - offset redirco_start
- redirco_next dw 0 ;Ptr to next routine to append
- redirco_lnks dw 0
- redirco_start = $
-
- redirco proc near
- assume ds:nothing,es:nothing
- cmp word ptr stdout_hdl,-1 ;If error on redirect, skip
- je redirco_exit ; restore.
-
- mov ah,46h ;Force restore of std out
- mov bx,stdout_hdl
- mov cx,1
- int 21h
-
- mov ah,3eh ;Close file
- mov bx,outfile_hdl ;Get output file handle
- int 21h
- redirco_exit:
- ret
- redirco endp
- redirco_end = $
-
- ;-----------------------------------------------------------------------------
- ; REDIROI Opens a file for input redirection.
- ; Entry: DS:SI - pointer to ASCII filename to open.
- ; DI - 0 open new file, 1 append to existing file.
- ;-----------------------------------------------------------------------------
- rediroi_off dw 0 ;Pointer to offset in COM file
- rediroi_size dw offset rediroi_end - offset rediroi_start
- rediroi_next dw 0 ;Ptr to next routine to append
- rediroi_lnks dw 0
- rediroi_start = $
-
- rediroi proc near
- assume ds:nothing,es:nothing
-
- mov word ptr stdin_hdl,-1 ;Clear handle
- mov dx,si ;Get ptr to outfile file
- mov ax,3d00h ;Open file, Read only
- int 21h
- jc rediroi_exit
- mov infile_hdl,ax ;Save input file handle
- push ax
-
- mov ah,45h ;Duplicate input handle
- xor bx,bx
- int 21h
- mov stdin_hdl,ax ;Save dup std input handle
-
- xor cx,cx
- pop bx
- mov ah,46h ;Force dup file handle
- int 21h
- rediroi_exit:
- ret
- rediroi endp
- rediroi_end = $
-
- ;-----------------------------------------------------------------------------
- ; REDIRCI Closes a file used for input redirection.
- ;-----------------------------------------------------------------------------
- redirci_off dw 0 ;Pointer to offset in COM file
- redirci_size dw offset redirci_end - offset redirci_start
- redirci_next dw 0 ;Ptr to next routine to append
- redirci_lnks dw 0
- redirci_start = $
-
- redirci proc near
- assume ds:nothing,es:nothing
- cmp word ptr stdin_hdl,-1 ;If error on redirect, skip
- je redirci_exit ; restore.
-
- mov ah,46h ;Force restore of std in hdl
- mov cx,cx
- xor bx,stdin_hdl
- int 21h
-
- mov ah,3eh ;Close file
- mov bx,infile_hdl ;Get input file handle
- int 21h
- redirci_exit:
- ret
- redirci endp
- redirci_end = $
-
- ;-----------------------------------------------------------------------------
- ; REDIRDEL Deletes piping file.
- ; Entry: DS:SI - pointer to ASCII filename to delete.
- ;-----------------------------------------------------------------------------
- redirdel_off dw 0 ;Pointer to offset in COM file
- redirdel_size dw offset redirdel_end - offset redirdel_start
- redirdel_next dw 0 ;Ptr to next routine to append
- redirdel_lnks dw 0
- redirdel_start = $
-
- redirdel proc near
- assume ds:nothing,es:nothing
-
- mov dx,si ;Copy pointer to filename
- mov ah,41h ;Delete file
- int 21h
- ret
- redirdel endp
- redirdel_end = $
-
- initialize endp
- even ;compiler stack on word boundry
- end_of_code = $
- code ends
-
- end main