home *** CD-ROM | disk | FTP | other *** search
- A major idea here is the use of the VALUE of an environment variable
- whose NAME is passed by the caller. The result is something like a
- function in a high level programming language.
-
-
- if either argument is omitted or the variable is not in the environment
- ("%[%2]" == ""), put up the help text and quit with an errorlevel.
-
- if "%1" == "" .or. "%2" == "" .or. "%[%2]" == "" goto help
-
- Make all letters upper case to get away from case sensitivity.
- set $foo=%@upper[%1]
-
- Make a string of all the digits from 0 to 35.
- set $wstr=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
-
- Use the semantic equivalent of a "case" statement to check what
- number base the user wants (specified in %1). The numbers 2 to 36
- are allowed, along with certain mnemonic letters, such as "H" for
- hexadecimal. "A"lpha is a special case where only the letters of
- the alphabet are used -- not numeric digit characters.
-
- iff %$foo = A then ^ gosub alpha
- elseiff %$foo = B then ^ gosub binary
- elseiff %$foo = O then ^ gosub octal
- elseiff %$foo = H then ^ gosub hex
- elseiff %$foo = D then ^ gosub dec
- elseiff %$foo = N then ^ gosub an
- elseiff %$foo gt 1 .and. %$foo lt 37 then ^ gosub base
- else goto help
- endiff
-
- iff %$val ne 0 then^unset %2 ^ gosub cleanup ^ goto helpval
- else set %2=%$foo ^gosub cleanup^quit 0
- endiff
-
- We actually finish here. Everything else is subroutines.
- quit
-
- :cleanup
- Can't use SETLOCAL because we're modifying the immediate caller's
- environment on purpose. Therefore, we have to UNSET our own stuff.
- unset $foo $wstr $val $max >& nul
- return
-
- Each of the following little subroutines just sets a key parameter
- for the main "bumpit" subroutine.
-
- :alpha
- set $max=25
- set $wstr=%@substr[%$wstr,10,26]
- gosub bumpit
- return
-
- :binary
- set $max=1
- gosub bumpit
- return
-
- :octal
- set $max=7
- gosub bumpit
- return
-
- :hex
- set $max=15
- gosub bumpit
- return
-
- :dec
- set $max=9
- gosub bumpit
- return
-
- :an
- set $max=35
- gosub bumpit
- return
-
- :base
- set $max=%@eval[%$foo-1]
- gosub bumpit
- return
-
- Here's the beef! All of the above just set the parameters for this.
-
- :bumpit
-
- Make sure all the characters in the input string are valid for this
- number base so the result will be meaningful.
-
- gosub validate
- if %$val ne 0 return
-
- Aw, shucks, it's valid. Get to work.
-
- Standardize character case
- set $foo=%@upper[%[%2]]
-
- Limit the loop to the length of the variable for carry propagation
- set $i=%@len[%$foo]
- set $j=%@eval[%$i-1]
- set $k=%$j
-
- :bumploop
-
- Break the string into three parts: front, target, and rear. "Target"
- is the character to be incremented (usually the rightmost unless we
- are propagating a carry leftward). "Front" is the part of the string
- up to but not including "target". "Rear" is the part of the string
- which follows "target". Either "front" or "rear" may be empty. "Rear"
- is usually empty unless propagating a carry. If "front" is empty, there
- is no place to propagate a carry, even if it is necessary. The latter
- could be changed easily if desired.
-
- set $front=
- if %$j gt 0 set $front=%@substr[%$foo,0,%$j]
- set $targ=%@substr[%$foo,%$j,1]
- set $rear=
- if %$j lt %$k set $rear=%@substr[%$foo,%@eval[%$j+1],%@eval[%$k-%$j]]
-
- Check to see if "targ" is already at the limit for the number system.
- Zero it and keep going if necessary.
-
- set $l=%@index[%$wstr,%$targ]
- iff %$l lt %$max then ^ set $targ=%@substr[%$wstr,%@eval[%$l+1],1]^set $j=0
- else set $targ=%@substr[%$wstr,0,1]
- endiff
-
- Put the string back together
-
- set $foo=%[$front]%[$targ]%[$rear]
-
- See if another iteration one character to the left is needed.
-
- if %$j gt 0 (set $j=%@eval[%$j-1]^goto bumploop)
- rem unset $i $j $k $l $front $rear $targ >& nul
- return
-
-
-
-
- Check whether all the characters in the environment variable are
- OK in this number base. Return 0 if OK, base of the number system
- if not.
-
- :validate
- set $i=0
- :valloop
-
- A valid character will have an index in the "wstr" digit string less
- than the base of the number system in question ("max") and greater
- than -1 (i.e., not a character completely outside the "wstr" set).
-
- set $val=%@index[%$wstr,%@substr[%[%2],%$i,1]]
- if %$val lt 0 .or. %$val gt %$max (set $val=%$max^return)
-
- Keep looping through all the characters in the input string.
- set $i=%@eval[%$i+1]
-
- Check for end of loop
- iff %$i lt %@len[%[%2]] then ^ goto valloop
- else set $val=0^return
- endiff
- return
-
- :helpval
- echo Invalid character detected.
- echo .
- goto help
-
- :help
- echo Usage BUMP mode var
- echo
- echo ! !
- echo ! Any environment variable of the correct type
- echo A=alpha [A-Z]
- echo B=binary [0-1]
- echo D=decimal [0-9]
- echo H=hex [0-F]
- echo N=alph/num [0-9,A-F]
- echo O=octal [0-7]
- echo [2-36] [0-(n-1)]
- echo New value returned in var
- echo Carry propagates left, overflow is ignored
- quit 4