home *** CD-ROM | disk | FTP | other *** search
- page 66,132
- ;============================================================================
- ; STRINGS.COM - a set of string handling functions for batch files.
- ;
- ; Syntax:
- ; STRINGS [/H][/M][/Pc ][var = ] function arg1 [, arg2] [, arg3]
- ;
- ; /? - Print help message
- ; /M - Use master environment block
- ; /Pc - Use c as parse character instead of ','
- ;
- ; Revision History:
- ;
- ; Version 1.0 Initial Release
- ;
- ;============================================================================
-
- code segment
- assume cs:code
-
- org 2ch
- local_environment 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,"STRINGS 1.0 "
- copyright db "(c) 1991 Douglas Boling",10,13
- db "First published in PC Magazine, September 10, 1991"
- db 10,13,10,"$",1Ah
-
- VAR_SIZE equ 128 ;Max size of variables
- DATABUFF_SIZE equ 16384 ;Size of file data buffer
-
- command_table db "LEFT",0 ;String functions
- db "RIGHT",0
- db "MID",0
- db "LENGTH",0
- db "FIND",0
- db "FINDC",0
- db "LOWER",0
- db "UPPER",0
- db "CHAR",0
- db "VAL",0
- db "FILENAME",0
- db "FILEEXT",0
-
- db "READ",0 ;File functions
- db "WRITE",0
- db "FILESIZE",0
- db "LINESIZE",0
- db "TRUENAME",0
-
- db "VER",0 ;System functions
- db "ASK",0
- db "ENVFREE",0
- db "ENVSIZE",0
- db "MASTERVAR",0
-
- db "ADD",0 ;Math functions
- db "SUB",0
- db "MUL",0
- db "DIV",0
- db 0 ;End of list flag
-
- jump_table dw offset left_str
- dw offset right_str
- dw offset mid_str
- dw offset length_str
- dw offset find_str
- dw offset findc_str
- dw offset lower_str
- dw offset upper_str
- dw offset char_str
- dw offset val_str
- dw offset filename_str
- dw offset fileext_str
-
- dw offset readrec_file
- dw offset writerec_file
- dw offset filesize_file
- dw offset numrec_file
- dw offset truename_file
-
- dw offset ver_sys
- dw offset ask_sys
- dw offset envfree_sys
- dw offset envsize_sys
- dw offset mastervar_sys
-
- dw offset add_num
- dw offset sub_num
- dw offset mul_num
- dw offset div_num
- jump_table_end = $
-
- parse_char db "," ;Char used to parse command
- fill_char db " " ;Char used to fill zeros
- equalsub_char db 0cdh
-
- databuff_ptr dw 0 ;Ptr to file data buffer
-
- environment_seg dw 0 ;Segment of master env
- dos_version dw 0
- shell_name db "COMMAND"
- console_out db 1 ;Flag for con out.
- use_mastenv db 0 ;Flag to use master env
- parse_literal db 0 ;Flag to respect lead spaces
-
- dest_var_val dw 0
- dest_var_name dw 0 ;Buffer pointers to parsed
- cmd_value dw 0 ; command line variables.
- var1_value dw 0 ; These pointers must be
- var2_value dw 0 ; kept in this order for the
- var3_value dw 0 ; cmdline parse routine.
-
- hlpmsg db 13,10,"Usage: STRINGS [/H][/M][/Pc][environment var =]"
- db " FUNCTION [str1][, str2][, str3]",13,10,13,10
- db " /? - Print this help message",13,10
- db " /M - Use master environment as destination",13,10
- db " /Pc - Use char c instead of ',' as the parse "
- db "character",13,10,10
- db " LEFT Returns left n chars "
- db "String, Num of chars",13,10
- db " RIGHT Returns right n chars "
- db "String, Num of chars",13,10
- db " MID Returns middle n chars "
- db "String, Start char, Length",13,10
- db " LENGTH Returns string length "
- db "String",13,10
- db " FIND Finds position of findstring "
- db "String, findstring",13,10
- db " FINDC Finds position of findstring. Case sen "
- db "String, findstring",13,10,0
- hlpmsga db " LOWER Returns string all lowercase "
- db "String",13,10
- db " UPPER Returns string all uppercase "
- db "String",13,10
- db " CHAR Returns ASCII number of character "
- db "Character",13,10
- db " VAL Returns ASCII char for a number "
- db "Number",13,10,10
-
- db " READ Returns a line from a file "
- db "Filename, line number",13,10
- db " WRITE Writes a string to the end of a file "
- db "Filename, String",13,10
- db " FILESIZE Returns the size of a file "
- db "Filename",13,10
- db " LINESIZE Returns the number of lines "
- db "Filename",13,10,0
- hlpmsgb db " FILENAME Returns the file name "
- db "Filename",13,10
- db " FILEEXT Returns the file extension "
- db "Filename",13,10
- db " TRUENAME Returns the complete filename "
- db "Filename",13,10,10
-
- db " ASK Returns a response from a user "
- db "[Prompt string]",13,10
- db " VER Returns the DOS version number",13,10
- db " ENVFREE Returns the bytes free in the environment",13,10
- db " ENVSIZE Returns the size of the environment",13,10
- db " MASTERVAR Returns a variable from the Master env ",13,10,10
-
- db " ADD Returns the sum of two numbers "
- db "Number, Number",13,10
- db " SUB Returns the difference of two numbers "
- db "Number, Number",13,10
- db " MUL Returns the product of two numbers "
- db "Number, Number",13,10
- db " DIV Returns the quotient of two numbers "
- db "Number, Number",13,10
- db 0
-
- errmsg0 db "Need DOS 2.0 or greater",0
- errmsg1 db "For help type STRINGS /?",0
- errmsg2 db "Not enought memory",0
- errmsg3 db "Unknown command line switch",0
- errmsg6 db "Illegal filename",0
- errmsg7 db "Line numbers must be greater than 0",0
- errmsg8 db "Line not found",0
- errmsg9 db "DOS error",0
-
- errmsg10 db "Multiply overflow error",0
- errmsg11 db "Divide by zero error",0
- errmsg12 db "Addition overflow",0
- errmsg13 db "Subtraction underflow",0
- errmsg14 db "Number too large",0
- errmsg15 db "Out of environment space",0
- errmsg16 db "Can't find environment",0
- errmsg17 db "Variable not found",0
-
- pausemsg db "Press any key to continue",13,10,0
- endmsg db 13,10,0
-
- ;----------------------------------------------------------------------------
- ; Start of code.
- ;----------------------------------------------------------------------------
- initialize proc near
- assume cs:code,ds:code,es:code
- 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 dos_version,ax
- mov si,offset errmsg0 ;Bad DOS version
- cmp ah,2
- jae main_1
- jmp disp_error
- main_1:
- mov di,offset end_of_code + 512 ;Set up data buffers
- mov sp,di ;Set stack
- mov si,offset dest_var_val
- mov cx,6 ;Set buffer pointers
- xor ax,ax
- main_2:
- mov [si],di ;Save ptr to buffer
- push cx
- mov cx,VAR_SIZE ;Initialize buffer to zero
- rep stosb
- pop cx
- inc si
- inc si
- loop main_2
- mov databuff_ptr,di ;Save data buffer ptr
-
- mov bx,DATABUFF_SIZE
- add bx,di
- mov cl,4
- shr bx,cl
- inc bx
- mov ah,4ah ;Reduce memory allocation
- int 21h
-
- call parse_cmdline ;Parse command line
- jc disp_error
-
- mov si,dest_var_name ;Point to dest env var name
- call caps_string
-
- mov si,cmd_value ;Point to command buffer
- call caps_string
-
- mov di,offset command_table
- call findstr
- mov si,offset errmsg1
- jc disp_error
- shl bx,1 ;Compute offset of routine to
- add bx,offset jump_table ; call.
- call [bx] ;Call routine to compile line.
- jc disp_error
-
- mov si,dest_var_val
- cmp console_out,0 ;See how to return result
- je main_3
- call print_strcr ;Print result string to screen
- jmp short main_6
- main_3:
- mov di,dest_var_name
- xchg di,si
-
- cmp use_mastenv,0 ;Find environment block
- jne main_4
- call findenv ;Use parent's env by default.
- jnc main_5
- main_4:
- call findmaster ;Find master env
- jc disp_error
- main_5:
- mov environment_seg,ax
-
- call setenv ;Set environemnt variable.
- jc main_7
- main_6:
- xor al,al ;Return code = 0
- exit:
- mov ah,4Ch ;Terminate
- int 21h
- ;
- ;Display error message.
- ;
- main_7:
- mov si,offset errmsg15 ;Out of environment space
- disp_error:
- push cs
- pop ds
- assume ds:code
-
- mov ah,9 ;Print copyright message
- mov dx,offset program
- int 21h
-
- push si
- call print_strcr ;print string
- pop si
- cmp si,offset hlpmsg
- jne main_9
- mov ax,40h
- mov es,ax
- mov al,es:[84h]
- cmp al,42
- ja main_8
-
- call pause_scr
- mov si,offset hlpmsga
- call print_strcr
-
- call pause_scr
- mov si,offset hlpmsgb
- call print_strcr
- jmp short main_9
- main_8:
- mov si,offset hlpmsga
- call print_strcr
- mov si,offset hlpmsgb
- call print_strcr
- main_9:
- mov al,01 ;Terminate with RC = 1
- jmp short exit
-
- ;=============================================================================
- ; String Functions
- ;=============================================================================
- ;-----------------------------------------------------------------------------
- ; RIGHT STR returns the right n characters of the source string
- ;-----------------------------------------------------------------------------
- right_str proc near
- assume cs:code,ds:code,es:code
- mov si,var2_value ;Convert 2nd parameter to hex
- call asc2hex
- call truncnum ;Truncate number to string len
-
- push ax
- mov di,var1_value ;Scan to end of string
- call find_end
- pop ax
- right_str_2:
- sub di,ax
- dec di
- cmp di,var1_value
- ja right_str_3
- mov di,var1_value
- right_str_3:
- mov si,dest_var_val
- xchg di,si
- call copy_string ;Copy string to dest buffer
- clc
- ret
- right_str endp
-
- ;-----------------------------------------------------------------------------
- ; LEFT STR Returns the left n characters of the source string
- ;-----------------------------------------------------------------------------
- left_str proc near
- assume cs:code,ds:code,es:code
- mov si,var2_value ;Convert 2nd parameter to hex
- call asc2hex
- call truncnum ;Truncate number to string len
-
- mov si,var1_value
- mov bx,ax
- mov byte ptr [si+bx],0
-
- mov di,dest_var_val
- call copy_string ;Copy string to dest buffer
- clc
- ret
- left_str endp
-
- ;-----------------------------------------------------------------------------
- ; MID STR Returns a string of n characters starting m characters from the
- ; left of the source string
- ;-----------------------------------------------------------------------------
- mid_str proc near
- assume cs:code,ds:code,es:code
- mov si,var2_value ;Convert 2nd parameter to hex
- call asc2hex
- dec ax
- call truncnum ;Truncate number to string len
- mov cx,ax ;Copy second parameter
-
- mov si,var3_value ;Convert 3rd parameter to hex
- cmp byte ptr [si],0 ;See if no parameter
- je mid_str_0
- call asc2hex ;If no number, return max
- jnc mid_str_1 ; value to insure remainder
- mid_str_0:
- mov ax,VAR_SIZE ; of string returned.
- mid_str_1:
- call truncnum ;Truncate number to string len
-
- push ax ;Save length of substring
- xor ax,ax
- cmp al,1 ;Clear zero flag
- mov di,var1_value ;Scan to new start of string
- jcxz mid_str_11
- repne scasb
- mid_str_11:
- pop cx ;Pop length of substring
- mov si,di ;Copy ptr to start of substr
- je mid_str_2 ;If end of str found, end
-
- repne scasb ;Scan until end of substring
- mov byte ptr [di],0
- mid_str_2:
- mov di,dest_var_val
- call copy_string ;Copy string to dest buffer
- clc
- ret
- mid_str endp
-
- ;-----------------------------------------------------------------------------
- ; LENGTH STR Computes the length of the source string
- ;-----------------------------------------------------------------------------
- length_str proc near
- assume cs:code,ds:code,es:code
- mov di,var1_value ;Find_end also returns the
- call find_end ; length of the string in
- mov ax,cx ; CX.
- xor dx,dx
- mov di,dest_var_val ;Convert value to ASCII
- call hex2asc
- clc
- ret
- length_str endp
-
- ;-----------------------------------------------------------------------------
- ; UPPER STR Convert the source string to upper case
- ;-----------------------------------------------------------------------------
- upper_str proc near
- assume cs:code,ds:code,es:code
- mov di,dest_var_val
- mov si,var1_value
- push di
- call copy_string ;Copy string to dest buffer
- pop si
- call caps_string ;Convert to upper case.
- clc
- ret
- upper_str endp
-
- ;-----------------------------------------------------------------------------
- ; LOWER STR Convert the source string to lower case
- ;-----------------------------------------------------------------------------
- lower_str proc near
- assume cs:code,ds:code,es:code
- mov di,dest_var_val
- mov si,var1_value
- push di
- call copy_string ;Copy string to dest buffer
- pop si
- call lc_string ;Convert to lower case.
- clc
- ret
- lower_str endp
-
- ;-----------------------------------------------------------------------------
- ; CHAR STR Convert the source number to a ASCII character
- ;-----------------------------------------------------------------------------
- char_str proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Convert ASCII number to hex
- call asc2hex
- mov di,dest_var_val
- xor ah,ah ;Write number directly to
- stosw ; dest string. Include
- clc ; zero for termination.
- ret
- char_str endp
-
- ;-----------------------------------------------------------------------------
- ; VAL STR Convert the source character to its HEX equivalent
- ;-----------------------------------------------------------------------------
- val_str proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Get ASCII character, then
- lodsb ; write its hex equivalent
- xor ah,ah ; to the output var.
- xor dx,dx
- mov di,dest_var_val
- call hex2asc
- clc
- ret
- val_str endp
-
- ;-----------------------------------------------------------------------------
- ; FILENAME STR Return only the filename from a filename string
- ;-----------------------------------------------------------------------------
- filename_str proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Fully qualify filename
- mov di,var2_value ;Use 2nd buff as temp buff
- call parse_filename
- mov si,di
- mov bx,di
- filename_1:
- lodsb
- cmp al,'\' ;Mark start of filename or
- jne filename_2 ; directory.
- mov bx,si
- filename_2:
- or al,al
- je filename_3
- cmp al,'.'
- jne filename_1
- dec si
- filename_3:
- mov cx,si
- sub cx,bx ;Compute length
- mov di,dest_var_val
- mov si,bx
- rep movsb
- clc
- ret
- filename_str endp
-
- ;-----------------------------------------------------------------------------
- ; FILEEXT STR Return only the filename extension from a filename string
- ;-----------------------------------------------------------------------------
- fileext_str proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Fully qualify filename
- mov di,var2_value ;Use 2nd buff as temp buff
- call parse_filename
- mov si,di
- xor bx,bx
- fileext_1:
- lodsb
- cmp al,'.' ;Mark start of filename or
- jne fileext_2 ; directory.
- mov bx,si
- fileext_2:
- or al,al
- jne fileext_1
-
- or bx,bx
- je fileext_3
- mov cx,si
- sub cx,bx ;Compute length
- mov di,dest_var_val
- mov si,bx
- rep movsb
- fileext_3:
- clc
- ret
- fileext_str endp
-
- ;-----------------------------------------------------------------------------
- ; FIND STR finds a string within another string.
- ; Exit: AL - Return code if string not found
- ; CF - Set if string not found
- ;-----------------------------------------------------------------------------
- find_str proc near
- mov si,var1_value ;To ignore case, capitalize
- call caps_string ; both strings, then call
- mov si,var2_value ; the findc function.
- call caps_string
- call findc_str
- ret
- find_str endp
-
- ;-----------------------------------------------------------------------------
- ; FINDC STR finds a string within another string, respects case.
- ; Exit: AL - Return code if string not found
- ; CF - Set if string not found
- ;-----------------------------------------------------------------------------
- findc_str proc near
- mov di,var1_value ;Get ptr to 1st string
- push di
- call find_end ;Compute length
- pop si
- push cx ;Save length
- mov di,var2_value
- mov dx,di
- call find_end
- mov bx,cx ;Save length of search string
- pop cx ;Restore length of trg string
- sub cx,bx ;Sub length of search string.
- jb find_str_not_found
- inc cx
- find_str_1:
- push cx
- mov cx,bx ;Restore search str length
- mov di,dx ;Restore ptr to search str
- push si
- repe cmpsb ;Compare command
- pop si
- pop cx
- je find_str_found
- inc si ;Inc target string ptr
- loop find_str_1
- find_str_not_found:
- xor ax,ax ;Set bad return code
- jmp short find_str_2
- find_str_found:
- mov ax,si ;Copy offset
- sub ax,var1_value ;Sub starting offset
- inc ax
- find_str_2:
- xor dx,dx
- mov di,dest_var_val ;Convert value to ASCII
- call hex2asc
- clc
- find_str_exit:
- ret
- findc_str endp
- ;=============================================================================
- ; File Functions
- ;=============================================================================
- ;-----------------------------------------------------------------------------
- ; READ REC returns record n from a file.
- ;-----------------------------------------------------------------------------
- readrec_file proc near
- assume cs:code,ds:code,es:code
-
- mov si,var1_value ;Fully qualify filename
- mov di,dest_var_val ;Use dest buff as temp buff
- call parse_filename
- mov dx,di ;Copy filename pointer
- call open_file
- jc readrec_error
-
- mov si,var2_value ;Convert 2nd param to record
- call asc2hex ; number.
-
- call findrec_file ;Find record.
- mov ax,si ;Copy end of file flag.
- mov si,offset errmsg8 ;Record not found.
- jc readrec_error1 ;Error if record not found.
-
- mov si,dest_var_val
- xchg di,si
- jcxz readrec_2
- readrec_1:
- lodsb ;Copy record to destination
- cmp al,13 ; buffer.
- je readrec_3
- stosb
- loop readrec_1
- readrec_2:
- or ah,ah ;Check end of file flag
- jne readrec_3
- mov dx,databuff_ptr ;If at end of data buffer.
- mov cx,VAR_SIZE ; read enough to complete
- call read_file ; record.
- jc readrec_error
- mov cx,ax ;Copy number of bytes read.
- mov di,dx
- jmp short readrec_1
- readrec_3:
- xor al,al ;Append terminating zero
- stosb
- call close_file ;Close file
- jc readrec_error
- readrec_exit:
- ret
- readrec_error:
- mov si,offset errmsg9 ;Generic DOS error msg
- stc
- jmp short readrec_exit
- readrec_error1:
- call close_file
- stc
- jmp short readrec_exit
- readrec_file endp
-
- ;-----------------------------------------------------------------------------
- ; WRITE REC appends a string to the end of a file.
- ;-----------------------------------------------------------------------------
- writerec_file proc near
- assume cs:code,ds:code,es:code
-
- mov si,var1_value ;Fully qualify filename
- mov di,dest_var_val ;Use dest buff as temp buff
- call parse_filename
- mov dx,di ;Copy filename pointer
- call open_file ;Open file. If file does not
- jnc writerec_0 ; exist, create the file.
- call create_file
- jc writerec_error
- mov si,1
- jmp short writerec_1
- writerec_0:
- xor ax,ax ;Move file ptr to end of file
- cwd
- mov cx,2 ;Move pointer from end.
- call move_fileptr ;Move file pointer
- jc writerec_error
- mov si,1
- or dx,dx
- jne writerec_01
- or ax,ax
- je writerec_1
- writerec_01:
- mov ax,-1 ;Move file ptr to last byte
- cwd
- mov cx,2 ;Move pointer from end.
- call move_fileptr ;Move file pointer
- jc writerec_error
- dec si ;Clear EOF marker flag
-
- mov dx,dest_var_val ;Read last char to check for
- mov cx,1 ; EOF marker
- call read_file
- jc writerec_error
-
- mov di,dx
- cmp byte ptr [di],1Ah
- jne writerec_1
-
- mov ax,-1 ;See if last byte 1A EOF mark
- cwd
- mov cx,2 ;Move pointer from end.
- call move_fileptr ;Move file pointer
- jc writerec_error
- inc si ;Set EOF marker flag
- writerec_1:
- mov di,var2_value ;Get length of string
- mov dx,di
- call find_end
- dec di ;Backup before zero
- mov ax,0a0dh
- stosw
- inc cx
- inc cx
- or si,si
- je writerec_2
- mov al,1ah ;Append EOF marker
- stosb
- inc cx
- writerec_2:
- call write_file
- jc writerec_error
-
- call close_file ;Close file
- jc writerec_error
- writerec_exit:
- mov di,dest_var_val ;Clear dest value.
- mov byte ptr [di],0
- ret
- writerec_error:
- mov si,offset errmsg9 ;Generic DOS error msg
- stc
- jmp short writerec_exit
- writerec_error1:
- call close_file
- stc
- jmp short writerec_exit
- writerec_file endp
-
- ;-----------------------------------------------------------------------------
- ; NUMREC FILE returns the number of records in a file.
- ;-----------------------------------------------------------------------------
- numrec_file proc near
- assume cs:code,ds:code,es:code
-
- mov si,var1_value ;Fully qualify filename
- mov di,dest_var_val ;Use dest buff as temp buff
- call parse_filename
- mov dx,di ;Copy filename pointer
- call open_file
- jc numrec_error
-
- xor ax,ax ;Attempt to find large rec num
- mov dx,ax
-
- call findrec_file ;Find record.
- jnc numrec_error1 ;Error if record found.
-
- not ax ;Compliment line count. No
- not dx ; need to add 1 since count
- ; already 1 too many.
- mov di,dest_var_val ;Convert rec number to ASCII
- call hex2asc
-
- call close_file ;Close file
- jc numrec_error
- numrec_exit:
- ret
- numrec_error:
- mov si,offset errmsg9 ;Generic DOS error msg
- stc
- jmp short numrec_exit
- numrec_error1:
- call close_file
- jc numrec_error
- stc
- jmp short numrec_exit
- numrec_file endp
-
- ;-----------------------------------------------------------------------------
- ; FIND REC returns an offset to the Nth record of a file.
- ; Entry: DX,AX - Record to find
- ; BX - Source File handle
- ; Exit: DX,AX - Records remaing if end of file
- ; CF - Set if record not found.
- ; DI - Points to record.
- ; CX - Number of bytes to end of data buffer
- ; SI - Points to error message if CF set.
- ;-----------------------------------------------------------------------------
- findrec_numl equ word ptr [bp-2]
- findrec_numh equ word ptr [bp-4]
- findrec_eof equ byte ptr [bp-5]
- findrec_file proc near
- assume cs:code,ds:code,es:code
- push bp
- mov bp,sp
- sub sp,6
-
- mov si,offset errmsg8 ;Record not found
- mov findrec_eof,0 ;Clear end of file flag.
- mov findrec_numl,ax ;Save record number.
- mov findrec_numh,dx
- findrec_1:
- mov cx,databuff_ptr
- xchg cx,dx
-
- mov cx,DATABUFF_SIZE ;Get size of data buffer
- call read_file ;Read data from file.
- jc findrec_error
-
- cmp ax,cx ;See if buffer filled. If
- je findrec_2 ; not, end of file.
- mov findrec_eof,1 ;Set end of file flag.
- findrec_2:
- mov cx,ax ;Copy num bytes read.
- mov di,dx ;Copy buffer ptr
- mov dx,ax ;Save size of buffer
-
- mov al,13 ;Scan for CR
- findrec_3:
- sub findrec_numl,1 ;Decriment record count
- sbb findrec_numh,0
-
- jne findrec_4 ;See if record count = 0
- cmp findrec_numl,0
- je findrec_5
- findrec_4:
- repne scasb
- je findrec_3
- cmp findrec_eof,1 ;If end of buffer, see if
- jne findrec_1 ; end of file. Yes = exit
- stc
- jmp short findrec_exit
- findrec_5:
- cmp byte ptr [di],0ah ;discard Line feed
- jne findrec_6
- inc di
- dec cx
- findrec_6:
- clc
- findrec_exit:
- mov ah,findrec_eof
- mov al,0
- mov si,ax ;Save end of file flag
-
- mov ax,findrec_numl ;Get record number.
- mov dx,findrec_numh
-
- mov sp,bp
- pop bp
- ret
- findrec_error:
- mov si,offset errmsg9 ;Generic DOS error msg
- findrec_error1:
- stc
- jmp short findrec_exit
- findrec_file endp
-
- ;-----------------------------------------------------------------------------
- ; FILE SIZE returns the size of a file
- ;-----------------------------------------------------------------------------
- filesize_file proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Fully qualify filename
- mov di,dest_var_val ;Use dest buff as temp buff
- call parse_filename
- mov dx,di ;Copy filename pointer
- call open_file
- mov di,dest_var_val ;Point DI to result buffer.
- jc filesize_exit
-
- xor ax,ax ;Zero offset.
- xor dx,dx
- mov cl,2 ;Move pointer from end.
- call move_fileptr ;Move file pointer
- jc filesize_exit
-
- call hex2asc ;Convert size to ASCII
- filesize_exit:
- ret
- filesize_file endp
-
- ;-----------------------------------------------------------------------------
- ; TRUENAME FILE returns the fully qualified name of a file.
- ;-----------------------------------------------------------------------------
- truename_file proc near
- assume cs:code,ds:code,es:code
- mov si,var1_value ;Fully qualify filename
- mov di,dest_var_val ;Use dest buff as temp buff
- call parse_filename
- jnc truename_1
- mov si,offset errmsg6 ;Illegal filename msg
- truename_1:
- ret
- truename_file endp
-
- ;=============================================================================
- ; System Functions
- ;=============================================================================
- ;-----------------------------------------------------------------------------
- ; VER SYS returns the DOS version number
- ;-----------------------------------------------------------------------------
- ver_sys proc near
- mov ax,dos_version
- push ax
- mov al,100
- xchg al,ah ;Copy major ver number
- mul ah
- pop bx
- xor bh,bh
- add ax,bx
- xor dx,dx
- mov di,dest_var_val
- call hex2asc
- clc
- ret
- ver_sys endp
-
- ;-----------------------------------------------------------------------------
- ; ASK SYS prints a string then returns the user response.
- ;-----------------------------------------------------------------------------
- ask_sys proc near
-
- mov si,var1_value
- cmp byte ptr [si],0
- je ask_1
- call print_strcr ;Print result string
- ask_1:
- mov bx,80h
- mov byte ptr [bx],127
- mov dx,bx
- mov ah,0ah
- int 21h
-
- mov si,offset endmsg
- call print_str ;Insert a CR-LF
-
- xor cx,cx ;Append zero to string.
- inc bx
- mov cl,[bx]
- inc bx
- mov si,bx
- add bx,cx
- mov byte ptr [bx],0
- inc cx
- mov di,dest_var_val ;Move string to result buff
- rep movsb
-
- clc
- ret
- ask_sys endp
-
- ;-----------------------------------------------------------------------------
- ; RC SYS returns the return code from the prev process
- ;-----------------------------------------------------------------------------
- rc_sys proc near
- mov ah,4dh ;Get return code
- int 21h
- xor ah,ah
- xor dx,dx
- mov di,dest_var_val
- call hex2asc
- clc
- ret
- rc_sys endp
-
- ;-----------------------------------------------------------------------------
- ; ENVFREE SYS returns the number of bytes free in the environment.
- ;-----------------------------------------------------------------------------
- envfree_sys proc near
- push es
-
- cmp use_mastenv,0 ;Find environment block
- jne envfree_0
- call findenv ;Use parent's env by default.
- jnc envfree_01
- envfree_0:
- call findmaster ;Find master env
- jc envfree_exit
- envfree_01:
- push ax
- dec ax
- mov es,ax
- mov dx,es:[3] ;Get size of env segment
- mov cl,4 ;Convert paragraphs to bytes
- shl dx,cl
- pop es
-
- mov cx,dx
- xor ax,ax
- xor di,di
- envfree_1:
- repne scasb ;Loop through the environment
- cmp byte ptr es:[di],al ; until the end of the
- loopne envfree_1 ; env strings is found.
- jcxz envfree_2
- mov ax,dx
- sub ax,di
- dec ax ;Sub byte for extra zero
- envfree_2:
- xor dx,dx
- pop es
- mov di,dest_var_val
- call hex2asc
- clc
- envfree_exit:
- ret
- envfree_sys endp
-
- ;-----------------------------------------------------------------------------
- ; ENVSIZE SYS returns the size of the environment.
- ;-----------------------------------------------------------------------------
- envsize_sys proc near
- push es
-
- cmp use_mastenv,0 ;Find environment block
- jne envsize_1
- call findenv ;Use parent's env by default.
- jnc envsize_2
- envsize_1:
- call findmaster ;Find master env
- jc envfree_exit
- envsize_2:
- push ax
- dec ax
- mov es,ax
- mov ax,es:[3] ;Get size of env segment
- mov cl,4 ;Convert paragraphs to bytes
- shl ax,cl
- pop es
-
- xor dx,dx
- pop es
- mov di,dest_var_val
- call hex2asc
- clc
- ret
- envsize_sys endp
-
- ;-----------------------------------------------------------------------------
- ; MASTERVAR SYS returns the value from a variable in the master environment.
- ;-----------------------------------------------------------------------------
- mastervar_sys proc near
- push ds
- push es
-
- mov di,var1_value
- push di
- call find_end
- mov word ptr es:[di-1],003dh ;Append = sign
- pop si
-
- call caps_string
-
- push cx ;Save length of var name
- call findmaster
- pop cx
- jc mastervar_exit
- mov es,ax
- xor di,di ;Use find string routine to
- call findstr ; find the variable name.
- jnc mastervar_1
- mov si,offset errmsg17
- stc
- jmp short mastervar_exit
- mastervar_1:
- mov si,dest_var_val
- push es
- push ds ;Exchange DS:SI and ES:DI
- pop es ; pointers.
- pop ds
- xchg si,di
- mastervar_2:
- lodsb ;Find end of var name.
- cmp al,'='
- jne mastervar_2
-
- call copy_string
- clc
- mastervar_exit:
- pop ds
- pop es
- ret
- mastervar_sys endp
-
- ;=============================================================================
- ; Number Functions
- ;=============================================================================
- ;-----------------------------------------------------------------------------
- ; ADD NUM returns the sum of two numbers
- ;-----------------------------------------------------------------------------
- add_num proc near
- assume cs:code,ds:code,es:code
- call conv2num ;Convert first two parms to
- jc add_num_exit ; 32 bit numbers. Carry
- add ax,bx ; set, overflow.
- adc dx,cx
- mov si,offset errmsg12 ;Add overflow
- jc add_num_exit ;If overflow, error
-
- mov di,dest_var_val
- call hex2asc ;Convert result to ASCII
- add_num_exit:
- ret
- add_num endp
-
- ;-----------------------------------------------------------------------------
- ; SUB NUM returns the difference of two numbers
- ;-----------------------------------------------------------------------------
- sub_num proc near
- assume cs:code,ds:code,es:code
- call conv2num ;Convert first two parms to
- jc sub_num_exit ; 32 bit numbers. Carry
- sub ax,bx ; set, overflow.
- sbb dx,cx
- mov si,offset errmsg13 ;Sub underflow
- jc sub_num_exit
-
- mov di,dest_var_val
- call hex2asc ;Convert result to ASCII
- sub_num_exit:
- ret
- sub_num endp
-
- ;-----------------------------------------------------------------------------
- ; MUL NUM returns the product of two numbers
- ;-----------------------------------------------------------------------------
- mul_num proc near
- assume cs:code,ds:code,es:code
- push bp
- call conv2num ;Convert first two parms to
- jc mul_num_exit ; 32 bit numbers. Carry
- mov di,dx ; set, overflow.
- mov si,ax
- mul cx ;32 bit multiply.
- jc mul_num_error ;Param 1 in DI,SI
- mov bp,ax ;Param 2 in CX,BX
- mov ax,di
- mul cx ; DI SI
- or ax,dx ; CX BX
- jnz mul_num_error ; ---------------------
- mov ax,di ; (BX * SI)
- mul bx ; (BX * DI)
- jc mul_num_error ; (CX * SI)
- add bp,ax ; + (CX * DI)
- mov ax,si ; ---------------------
- mul bx ; DX AX
- add dx,bp
- jc mul_num_error
-
- mov di,dest_var_val
- call hex2asc ;Convert result to ASCII
- mul_num_exit:
- pop bp
- ret
- mul_num_error:
- stc
- mov si,offset errmsg10 ;Multiply overflow
- stc
- jmp short mul_num_exit
- mul_num endp
-
- ;-----------------------------------------------------------------------------
- ; DIV NUM returns the quotient of two numbers
- ;-----------------------------------------------------------------------------
- div_num proc near
- assume cs:code,ds:code,es:code
- call conv2num ;Convert first two parms to
- jc div_num_exit ; 32 bit numbers.
- push cx
- or cx,bx ;Prevent divide by zero
- pop cx
- jz div_num_error
- div_num_1:
- or cx,cx ;Divide both numbers by 2
- je div_num_2 ; until high word of
- shr dx,1 ; divisor (CX) is zero.
- rcr ax,1
-
- shr cx,1
- rcr bx,1
- jmp short div_num_1
- div_num_2:
- push ax ;Save low word
- mov ax,dx
- xor dx,dx
- div bx ;Divide high word
- mov cx,ax ;Save high quotent
- pop ax
- div bx ;Divide low word
- mov dx,cx
-
- mov di,dest_var_val
- call hex2asc ;Convert result to ASCII
- div_num_exit:
- ret
- div_num_error:
- mov si,offset errmsg11
- stc
- jmp short div_num_exit
- div_num endp
-
- ;=============================================================================
- ; Support Procedures
- ;=============================================================================
- ;-----------------------------------------------------------------------------
- ; CONV2NUM converts the first two parameters to hex numbers.
- ; Exit: DX AX - Number from 1st parameter
- ; CX BX - Number from 1st parameter
- ; CF - Set if either number too large
- ; SI - Set to error message if CF set
- ;-----------------------------------------------------------------------------
- conv2num proc near
- mov si,var2_value ;Convert 2nd parameter to hex
- call asc2hex
- jc conv2num_error
- mov bx,ax ;Copy second parameter
- mov cx,dx
-
- mov si,var1_value ;Convert 1st parameter to hex
- call asc2hex
- jc conv2num_error
- conv2num_exit:
- ret
- conv2num_error:
- mov si,offset errmsg14 ;Number too large
- jmp short conv2num_exit
- conv2num endp
-
- ;-----------------------------------------------------------------------------
- ; PARSE CMDLINE Parse the command line into seperate buffers for each word.
- ; Entry: SI - Pointer to string to parse.
- ; Exit: CF - Set if error.
- ; SI - Points to error message if CF set.
- ;-----------------------------------------------------------------------------
- parse_cmdline proc near
- mov si,offset command_tail
- cmp byte ptr [si],0 ;See if cmdline = 0
- jne parse_cmdline_1 ;If zero, report error
- parse_error:
- mov si,offset errmsg1 ;Syntax error message
- stc
- jmp parse_cmdline_exit1
- parse_cmdline_1:
- inc si
- xor cx,cx
- xor bx,bx
- call scan4char ;Find 1st char
- jc parse_error
-
- cmp al,'/' ;See if cmdline switch
- jne parse_cmdline_2
- inc si ;Skip past '/'.
- lodsb ;Get cmdline switch
- cmp al,'?'
- je parse_cmdline13
- or al,20h
- cmp al,'m'
- jne parse_cmdline_11
- mov use_mastenv,1 ;Set use master env flag
- jmp short parse_cmdline_1
- parse_cmdline_11:
- cmp al,'p'
- jne parse_cmdline_12
- lodsb
- mov parse_char,al ;Set new parse character
- jmp short parse_cmdline_1
- parse_cmdline_12:
- cmp al,'h'
- jne parse_error
- parse_cmdline13:
- mov si,offset hlpmsg
- stc
- jmp short parse_cmdline_exit1
- parse_cmdline_2:
- mov di,cmd_value
- mov bx,203dh ;copy until = or space
- call copy_till
- jc parse_cmdline_exit
- cmp al,'='
- je parse_cmdline_4
- parse_cmdline_3:
- xor bl,bl
- call scan4char ;Find next char
- jc parse_cmdline_exit
- cmp byte ptr [si],'='
- jne parse_cmdline_5
- inc si ;Move src ptr past =
- parse_cmdline_4:
- mov console_out,0 ;Clear console out flag
- xor bl,bl ;Find next char
- call scan4char
- jc parse_error
-
- push si ;If = found, 1st parameter
- mov si,cmd_value ; was dest var name. Copy
- mov di,dest_var_name ; name, then get new cmd
- call copy_string ; string.
- pop si
-
- mov bx,2020h ;Copy until next space
- mov di,cmd_value
- call copy_till
- mov al,0 ;Terminate new cmd with 0
- stosb
- jc parse_cmdline_exit
- parse_cmdline_5:
- mov bp,offset var1_value
- mov cx,3 ;Max 3 parameters
- parse_cmdline_6:
- xor bl,bl ;Find start of parameter
- call scan4char
- jc parse_cmdline_exit
-
- mov bl,parse_char ;If consecutive parse chars
- mov bh,bl ; lead a parameter, skip the
- cmp [si],bx ; characters. This is used
- jne parse_cmdline_7 ; to allow leading spaces in
- inc si ; parameters.
- inc si
- parse_cmdline_7:
- mov di,[bp] ;Get ptr to buffer
- xor bh,bh
- call copy_till ;Copy until parse char
- jc parse_cmdline_exit
- add bp,2
- loop parse_cmdline_6
- parse_cmdline_exit:
- clc
- parse_cmdline_exit1:
- ret
- parse_cmdline endp
-
- ;-----------------------------------------------------------------------------
- ; COPY TILL Copys a string until a specified character is found
- ; Entry: SI - Pointer to source string
- ; DI - Pointer to destination buffer
- ; BL - 1st end character
- ; BH - 2nd end character
- ;-----------------------------------------------------------------------------
- copy_till proc near
- copytill_1:
- lodsb
- cmp al,13 ;Check for carriage return.
- je copytill_eol
- copytill_2:
- cmp al,equalsub_char ;See if = sub char
- jne copytill_3
- mov al,'='
- copytill_3:
- cmp al,bl ;See if end character found
- je copytill_exit
- cmp al,bh ;See if any char at or below
- jbe copytill_exit ; 2nd end character.
- stosb
- jmp short copytill_1
- copytill_exit:
- clc
- copytill_exit1:
- ret
- copytill_eol:
- stc
- jmp short copytill_exit1
- copy_till endp
-
- ;-----------------------------------------------------------------------------
- ; PARSE FILENAME creates a proper pathname for a filename
- ; Entry: SI - Pointer to ASCIIZ filename
- ; DI - Pointer to buffer to hold resulting pathname
- ;-----------------------------------------------------------------------------
- parse_filename proc near
- assume cs:code,ds:code,es:code
- push di
- push si
- cmp dos_version,300h ;See if DOS 3.x or greater.
- jb parse_fname_0 ;If not, parse the old way.
- mov ah,60h ;DOS Resolve Path
- int 21h
- jmp short parse_fname_7
- parse_fname_0:
- cmp byte ptr [SI+1],":" ;See if disk specified
- je parse_fname_1 ;Yes, skip disk assignment
-
- mov ah,19h ;Get default disk
- int 21h
- inc al
-
- mov dl,al ;Save default disk number
- add al,40h ;Make ASCII
- mov ah,":"
- jmp short parse_fname_2
- parse_fname_1:
- lodsw ;Get disk specified
- and al,0DFh ;Convert to caps
- mov dl,al
- sub dl,40h ;Convert to hex
- parse_fname_2:
- stosw ;Load disk specification
- ;Look for directory specification.
- mov bx,di ;save start of path
- mov al,"\"
- cmp byte ptr [si],al ;See if starting from root
- je parse_fname_3 ;Yes, skip append of path
-
- stosb ;Start at root
- push si ;Save current pointer
- mov si,di ;Point to dest buffer
- mov ah,47h ;Get default path
- int 21h
- pop si
-
- cmp byte ptr [di],0 ;See if NULL path
- je parse_fname_3
-
- call find_end ;Scan to end of path string
- dec di ;move back before zero
- mov al,"\" ;Append path string with
- stosb ; a \. CX = length of path
- parse_fname_3:
- add cx,2 ;Append filename to path.
- mov ax,VAR_SIZE ;Compute space remaining in
- sub ax,cx ; the destination buffer.
- xchg cx,ax
- xor ah,ah ;Clear last char holder
- parse_fname_4:
- lodsb ;Get filename character. If
- or al,al ; end of string, exit.
- jz parse_fname_6 ;Else, write char.
- stosb
- cmp ax,".." ;If last two chars are ..,
- jne parse_fname_5 ; scan backwards to delete
- std ; last directory.
- sub di,4 ;First, backup past '\..'
- mov al,"\" ;Look for directory sep
- push cx
- mov cx,di ;Compute length of path
- sub cx,bx
- repne scasb ;Now, past last directory
- pop cx
- cld ;Scan forwards again
- inc di ;Move back past \
- parse_fname_5:
- mov ah,al ;Save last character read.
- loop parse_fname_4
- parse_fname_6:
- xor al,al ;Terminate string with 0
- stosb
- parse_fname_7:
- pop si
- pop di
- ret
- parse_filename endp
-
- ;-----------------------------------------------------------------------------
- ; CREATE FILE Creates a new file.
- ; Entry: DX - Pointer to ASCIIZ filename.
- ; Exit: BX - File handle
- ; CF - Set if error
- ;-----------------------------------------------------------------------------
- create_file proc near
- push cx
- mov ah,3ch ;Create file
- xor cx,cx ;Normal attributes
- int 21h
- mov bx,ax ;Copy file handle
- pop cx
- ret
- create_file endp
-
- ;-----------------------------------------------------------------------------
- ; OPEN FILE Opens a file.
- ; Entry: DX - Pointer to ASCIIZ filename.
- ; Exit: BX - File handle
- ; CF - Set if error
- ;-----------------------------------------------------------------------------
- open_file proc near
- mov ax,3d02h ;Open file, read/write
- int 21h
- mov bx,ax ;Copy file handle
- ret
- open_file endp
-
- ;-----------------------------------------------------------------------------
- ; CLOSE FILE Closes a file.
- ; Entry: BX - File handle
- ; Exit: CF - Set if error
- ;-----------------------------------------------------------------------------
- close_file proc near
- mov ah,3eh ;Close file
- int 21h
- ret
- close_file endp
-
- ;-----------------------------------------------------------------------------
- ; READ FILE Reads data from a file
- ; Entry: BX - File handle
- ; CX - Number of bytes to read
- ; DX - Pointer to data buffer
- ; Exit: CF - Set if error
- ; AX - bytes read.
- ;-----------------------------------------------------------------------------
- read_file proc near
- mov ah,3fh ;Read file data
- int 21h
- ret
- read_file endp
-
- ;-----------------------------------------------------------------------------
- ; WRITE FILE Writes data to a file
- ; Entry: BX - File handle
- ; CX - Number of bytes to write
- ; DX - Pointer to data buffer
- ; Exit: CF - Set if error
- ;-----------------------------------------------------------------------------
- write_file proc near
- mov ah,40h ;Write file data
- int 21h
- ret
- write_file endp
-
- ;-----------------------------------------------------------------------------
- ; MOVE FILEPTR Moves the file read pointer of a file.
- ; Entry: AX,DX - Offset of file pointer
- ; BX - File handle
- ; CL - Move type, 0 = from start, 2 = from end.
- ; Exit: CF - Set if error
- ;-----------------------------------------------------------------------------
- move_fileptr proc near
- xchg cx,dx ;Copy most sig word
- xchg dx,ax ;Copy least sig word
- mov ah,42h ;Move file pointer
- int 21h
- ret
- move_fileptr endp
-
- ;-----------------------------------------------------------------------------
- ; TRUNCNUM truncates a number to the max length of a string
- ; Entry: AX - Number to truncate
- ; Exit: AX - Truncated number
- ;-----------------------------------------------------------------------------
- truncnum proc near
- cmp ax,VAR_SIZE ;VAR_SIZE = max string length
- jb trunc_1
- mov ax,VAR_SIZE
- trunc_1:
- ret
- truncnum endp
-
- ;-----------------------------------------------------------------------------
- ; FINDSTR determines if a string is in a list.
- ; Entry: DS:SI - Pointer to ASCII string to find.
- ; ES:DI - Pointer to list of ASCIIZ strings.
- ; CX - Size of string
- ; Exit: DI - Pointer to entry in list
- ; CF - Clear if string found
- ; BX - If CF clear, index into list
- ;-----------------------------------------------------------------------------
- findstr proc near
- push cx
- push dx
- xor dx,dx
- or dx,cx ;Save length of string
- je finds_3
- xor bx,bx ;Zero index counter
- finds_1:
- push di
- push si
- push cx
- repe cmpsb ;Compare command
- pop cx
- pop si
- pop di
- clc
- je findstr_exit
- inc bx ;Inc string count
-
- push cx
- call find_endl ;Find end of string.
- pop cx
- jne finds_3
- cmp byte ptr es:[di],0 ;See if second zero. If so
- jne finds_1 ; end of list.
- finds_3:
- stc ;Indicate string not found
- findstr_exit:
- pop dx
- pop cx
- ret
- findstr endp
-
- ;-----------------------------------------------------------------------------
- ; FIND END scans to the end of an ASCIIZ string.
- ; Entry: ES:DI - Pointer to ASCII string
- ; Exit: ES:DI - Pointers to character after string.
- ; CX - Length of string
- ; ZF - Clear if end not found in MAX length of characters
- ;-----------------------------------------------------------------------------
- find_end proc near
- push ax
- mov cx,VAR_SIZE
- xor al,al
- repne scasb
- pushf
- mov ax,VAR_SIZE
- sub ax,cx
- xchg ax,cx
- dec cx
- popf
- pop ax
- ret
- find_end endp
-
- ;-----------------------------------------------------------------------------
- ; FIND ENDL scans to the end of an ASCIIZ string. String can be up to 32K
- ; Entry: ES:DI - Pointer to ASCII string
- ; Exit: ES:DI - Pointers to character after string.
- ; CX - Length of string
- ; ZF - Clear if end not found in MAX length of characters
- ;-----------------------------------------------------------------------------
- find_endl proc near
- push ax
- mov cx,8000h
- xor al,al
- repne scasb
- pushf
- mov ax,8000h
- sub ax,cx
- xchg ax,cx
- dec cx
- popf
- pop ax
- ret
- find_endl endp
-
- ;-----------------------------------------------------------------------------
- ; CAPS STRING capitalizes ASCIIZ string
- ; Entry: SI - Pointer to ASCII string to capitalize
- ; Exit: CX - Length of string
- ;-----------------------------------------------------------------------------
- caps_string proc near
- assume ds:code,es:code
- push bx
- push dx
- mov bx,"za" ;Set filter limits
- mov dx,0df00h ;Set character filter
- call filter_string
- pop dx
- pop bx
- ret
- caps_string endp
-
- ;-----------------------------------------------------------------------------
- ; LC STRING makes an ASCIIZ string lower case
- ; Entry: SI - Pointer to ASCII
- ; Exit: CX - Length of string
- ;-----------------------------------------------------------------------------
- lc_string proc near
- assume ds:code,es:code
- push bx
- push dx
- mov bx,"ZA" ;Set filter limits
- mov dx,0ff20h ;Set character filter
- call filter_string
- pop dx
- pop bx
- ret
- lc_string endp
-
- ;-----------------------------------------------------------------------------
- ; FILTER STRING filters an ASCIIZ string
- ; Entry: DS:SI - Pointer to ASCII string
- ; BL - Lower limit of char range
- ; BH - Upper limit of char range
- ; DL - OR filter
- ; DH - AND filter
- ; Exit: CX - Length of string
- ;-----------------------------------------------------------------------------
- filter_string proc near
- assume ds:code,es:code
- push si
- push di
- push es
-
- mov di,si
- push ds
- pop es
- xor cx,cx ;Clear byte counter.
- filter_1:
- lodsb ;Get character
- or al,al ;Allow any non-space character
- je filter_exit
- cmp al,bl ;If between lower and upper
- jb filter_2 ; char limit it.
- cmp al,bh
- ja filter_2
- or al,dl ;Apply OR filter
- and al,dh ;Apply AND filter
- filter_2:
- stosb ;Save character
- inc cx ;Inc byte counter
- jmp short filter_1
- filter_exit:
- pop es
- pop di
- pop si
- ret
- filter_string endp
-
- ;-----------------------------------------------------------------------------
- ; COPY STRING copies an ASCIIZ string
- ; Entry: DS:SI - Pointer to source ASCIIZ string
- ; ES:DI - Pointer to destination buffer
- ; Exit: CX - Length of string
- ;-----------------------------------------------------------------------------
- copy_string proc near
- assume ds:code,es:code
- xor cx,cx
- copy_string_1:
- lodsb ;Move character
- stosb
- or al,al ;See if end of string
- je copy_string_exit ;If so, exit
- inc cx ;Inc count
- jmp short copy_string_1
- copy_string_exit:
- ret
- copy_string endp
-
- ;-----------------------------------------------------------------------------
- ; PRINT STRCR prints an ASCIIZ string then appends a CR LF to the end
- ; Entry: SI - pointer to ASCIIZ string.
- ;-----------------------------------------------------------------------------
- print_strcr proc near
- assume ds:nothing,es:nothing
- call print_str
- mov si,offset endmsg
- call print_str
- ret
- print_strcr endp
-
- ;-----------------------------------------------------------------------------
- ; PRINT STR prints an ASCIIZ string to the std output device
- ; Entry: SI - Pointer to ASCIIZ string.
- ;-----------------------------------------------------------------------------
- print_str proc near
- lodsb ;Get character
- or al,al ;See if end of string
- je print_str_exit
- mov ah,2 ;DOS print character
- mov dl,al
- int 21h ;Call DOS
- jmp short print_str
- print_str_exit:
- ret
- print_str endp
-
- ;-----------------------------------------------------------------------------
- ; HEX2ASC converts number in DX AX to ASCII
- ; Entry: DX AX - Number
- ; DI - Destination buffer
- ; CF - Clear
- ;-----------------------------------------------------------------------------
- hex2asc proc near
- assume ds:nothing,es:nothing
- push ax
- push bx
- push cx
- push dx
- push si
-
- mov si,10 ;Load number base
- mov bx,ax
- mov cx,dx
- mov dx,-1 ;Load end of number flag
- push dx
- hex_loop1:
- xchg ax,cx ;Get high word in AX
- xor dx,dx ;Clear high word
- div si ;Divide by base (10)
- xchg cx,ax ;Save result of high divide
- xchg ax,bx ;Get low word, leave remainder
- div si ; in DX.
- xchg bx,ax ;Save result of low divide
-
- add dl,30h ;Convert to ascii
- push dx ;Save digit on stack
- or bx,bx
- jne hex_loop1 ;See if number = 0. If not,
- or cx,cx ; continue divide loop.
- jne hex_loop1
-
- mov bl,"0" ;Set leading zero flag
- hex_loop2:
- pop dx ;Get digit off stack
- cmp dx,-1 ;See if end flag
- je hex_2
- 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 al,dl ;Write to buffer
- stosb
- hex_1:
- jmp short hex_loop2
- hex_2:
- cmp bl,"0" ;If number zero, write last
- jne hex_exit ; zero.
- mov al,bl
- stosb
- hex_exit:
- xor al,al ;Termainate with zero
- stosb
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- hex2asc endp
-
- ;-----------------------------------------------------------------------------
- ; ASC2HEX converts an ASCII number to hex
- ; Entry: SI - Pointer to ASCIIZ string, max 5 digits.
- ; Exit: DX,AX - Number
- ; CF - Set if overflow
- ;-----------------------------------------------------------------------------
- asc2hex proc near
- assume ds:nothing,es:nothing
- push bx
- push cx
- push bp
- xor cx,cx ;Zero result
- xor di,di
- xor bx,bx
- mov bp,10 ;Load number base
- asc_loop1:
- mov bl,[si] ;Get next digit
- inc si
- sub bl,"0" ;Convert digit from ASCII to
- jb asc_exit ; hex. If digit illegal
- cmp bl,9 ; character, exit.
- ja asc_exit
-
- xchg ax,di ;Shift result in DI CX by
- mul bp ; the base.
- jc asc_exit1
- xchg di,ax
- xchg ax,cx
- mul bp
- xchg cx,ax
- add di,dx
- jc asc_exit1
-
- add cx,bx ;Add new number to result.
- adc di,0
- jnc short asc_loop1
- asc_exit1:
- mov ax,cx ;Copy result
- mov dx,di
- pop bp
- pop cx
- pop bx
- ret
- asc_exit:
- clc
- jmp short asc_exit1
- asc2hex 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,
- ; 3 = find next space or =.
- ; 4 = find character in DL.
- ; 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.
- jne scan4_1
- scan4_eol:
- stc
- jmp short scan4_exit1
- scan4_1:
- cmp bl,4
- je scan4_dl
- cmp bl,3
- je scan4_equal
- cmp bl,1 ;Check if searching for space,
- je scan4_space ; character, or end of line.
- ja scan4loop
- cmp al," " ;Check for space or other
- jbe scan4loop ; 'white' characters.
- jmp short scan4_exit
- scan4_dl:
- cmp al,dl ;Check for parse character
- je scan4_exit
- jmp short scan4loop
- scan4_equal:
- cmp al,"=" ;Check for exit
- je scan4_exit
- scan4_space:
- cmp al," " ;Check for characters.
- ja scan4loop
- scan4_exit:
- dec si ;Back up before character
- clc
- scan4_exit1:
- ret
- scan4char endp
-
- ;-----------------------------------------------------------------------------
- ; PAUSE SCR Prints a 'press key' message then waits for one.
- ;-----------------------------------------------------------------------------
- pause_scr proc near
- mov si,offset pausemsg
- call print_strcr
- pause_1:
- int 28h ;Call Idle interrupt
- cld
- mov ah,01 ;Check for key press
- int 16h
- jz pause_1
- xor ax,ax ;Get key from buffer
- int 16h
- ret
- pause_scr endp
-
- ;-----------------------------------------------------------------------------
- ; FINDENV Finds the parent's environment block.
- ; Exit: AX - Segment of local command processor environment.
- ;-----------------------------------------------------------------------------
- findenv proc near
- assume cs:code,ds:code,es:code,ss:code
- push di
- push si
- push es
- findenv_1:
- mov ax,es:[16h] ;Get parent's PSP
- mov dx,ax ;Save PSP segment
- push ax
- dec ax ;Point to mcb
- mov es,ax
- cmp byte ptr es:[0],"M" ;check for mcb signature
- pop es
- jne findenv_error
-
- cmp dx,es:[16h] ;See if PSP is own parent
- jne findenv_1 ;No, keep looking
-
- mov cx,30
- mov es,ax
- findenv_2:
- add ax,es:[3] ;Add size of memory block
- inc ax
- mov es,ax
-
- cmp byte ptr es:[0],"M" ;check for mcb signature
- jne findenv_error
- cmp dx,es:[1] ;See if this owned by cmd proc
- je findenv_3
- loop findenv_2
- jmp short findenv_error
- findenv_3:
- inc ax
- clc
- findenv_exit:
- pop es
- pop si
- pop di
- ret
- findenv_error:
- mov si,offset errmsg16 ;Environment not found
- stc
- jmp short findenv_exit
- findenv endp
-
- ;-----------------------------------------------------------------------------
- ; FINDMASTER Finds the master environment block.
- ; Exit: AX - Segment of Master environment block
- ;-----------------------------------------------------------------------------
- findmaster proc near
- assume cs:code,ds:code,es:code,ss:code
- push di
- push si
- push es
-
- mov ah,52h ;Get address of first MCB
- int 21h
- mov ax,es:[bx-2] ;point ES to MCB
- mov cx,30 ;Allow only 30 loops.
- findmaster_1:
- mov es,ax
- cmp byte ptr es:[0],"M" ;check for mcb signature
- jne findmaster_exit
- inc ax ;point AX to memory block
- cmp ax,es:[1] ;See if this is a PSP block
- je findmaster_4
- findmaster_2:
- add ax,es:[3] ;Get size of memory block
- loop findmaster_1
- jmp short findmaster_error
-
- findmaster_4:
- cmp dos_version,0a00h ;If OS/2, use DOS 3.3 method.
- jae findmaster_5
- cmp dos_version,0400h ;If DOS 4.00 or greater,
- jb findmaster_5 ; COMMAND.COM may not be the
- push ds ; first program loaded. Look
- mov si,offset shell_name ; 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, keep
- jne findmaster_1 ; looking.
- findmaster_5:
- mov dx,ax ;Save PSP seg
- 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 findmaster_found
- mov ax,dx ;Get back cmd.com segment
- dec ax ;Point back to mcb
- mov es,ax
- findmaster_6:
- add ax,es:[3] ;If master env segment not
- inc ax ; saved at 2Ch of the PSP,
- mov es,ax ; scan the memory blocks
- cmp es:[1],dx ; for first segment owned
- je findmaster_7 ; above the PSP.
- loop findmaster_6
- findmaster_error:
- mov si,offset errmsg16 ;Master env not found msg
- stc
- jmp short findmaster_exit ;Master env not found.
- findmaster_7:
- inc ax ;Point AX to env segment
- findmaster_found:
- clc
- findmaster_exit:
- pop es
- pop si
- pop di
- ret
- findmaster endp
-
- ;-----------------------------------------------------------------------------
- ; SETENV Sets environment variables.
- ;
- ; Entry: DS:SI - pointer to env var name
- ; ES:DI - pointer to env var value
- ;-----------------------------------------------------------------------------
- setenv proc near
- push bp
- push ds
- push es
-
- push di ;Save ptr to var value
- push es
-
- call find_end ;Get length of var value
- mov dx,cx ;Copy length
- mov di,si
- push ds ;Add length of var name plus
- pop es ; room for the equals sign.
- call find_end
- mov word ptr es:[di-1],003dh ;Append = sign
- inc cx ;Add byte for =
- add dx,cx
- inc dx ;Add byte for terminating 0
-
- mov ax,environment_seg
- push ax
- dec ax
- mov es,ax
- mov bp,es:[3] ;Get size of env segment
- push cx
- mov cl,4 ;Convert paragraphs to bytes
- shl bp,cl
- pop cx
- pop es
-
- xor di,di ;Use find string routine to
- call findstr ; find the variable name.
-
- push si
- push ds
- jc setenv_2 ;Var not found, skip erase
- push es
- pop ds
-
- mov si,di ;Erase current var value by
- call find_endl ; copying the next env var
- xchg si,di ; over the current one.
- setenv_1:
- cmp byte ptr [si],0
- je setenv_2
- setenv_11:
- lodsb
- stosb
- or al,al
- jne setenv_11
- jmp short setenv_1
- setenv_2:
- pop ax ;Get ptr to var name
- pop cx
-
- pop ds ;Get ptr to var value
- pop si
-
- cmp byte ptr ds:[si],0 ;See if NULL variable, If so,
- je setenv_31 ; don't add to env block
-
- mov bx,di ;Get offset of end of env
- add bx,dx ;Add length of value
- inc bx ;Add length of terminating byte
- cmp bp,bx
- ja setenv_3
-
- push ax ;Save ptr to var name
- push cx
- mov dx,es
- dec dx
- mov es,dx
- push es:[1] ;Save current owner segment
- inc dx
- mov es,dx
- add bx,15 ;If no room in environemnt,
- mov cl,4 ; see if env segment can be
- shr bx,cl ; resized to make room for
- mov ah,4ah ; new variable.
- int 21h ;Reallocate memory
- pop bx ;Get old owner
- pop cx
- pop ax
- jc setenv_5
- push es
- dec dx
- mov es,dx
- mov es:[1],bx ;Restore old owner
- pop es
- setenv_3:
- push si
- push ds
-
- mov si,cx
- mov ds,ax
- call copy_string ;Copy var name to env
- dec di ;Back up over last zero
- pop ds
- pop si
-
- mov bl,"=" ;Since env vars can't have
- mov bh,bl ; the char '=', filter
- mov dl,-1 ; string to change = to
- mov dh,equalsub_char ; graphic char that looks
- call filter_string ; similar.
-
- call copy_string ;Copy var value to env
- setenv_31:
- xor al,al
- stosb ;Add 2 zeros to end env.
- setenv_4:
- clc ;Set pass flag
- setenv_5:
- pop es
- pop ds
- pop bp
- ret
- setenv endp
-
- initialize endp
- even ;Set stack on word boundry
- end_of_code = $
- code ends
-
- end main