Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VOL and...

14 views
Skip to first unread message

Benny Pedersen

unread,
Nov 18, 2000, 11:54:55 PM11/18/00
to
An previours question about the VOL command, was/is an opportunity to use and show the new feature as we discuss for some days ago: @echo off choice/n/c abcdefghijklmnopqrstuvwxyz Choose: if not errorlevel 17 goto end for %%b in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if errorlevel %%b set drive=%%b vol %drive%: | find "%drive% " :end set drive= --b.pedersen, PS. http://2dos.homepage.dk/batutil/help/VOL_S.HTM#bennylevel

Outsider

unread,
Nov 19, 2000, 2:38:41 AM11/19/00
to
Benny Pedersen wrote: > Hi, > An previours question about the VOL command, was/is an opportunity to use and show the new feature as we discuss for some days ago: > @echo off > choice/n/c abcdefghijklmnopqrstuvwxyz Choose: > if not errorlevel 17 goto end > for %%b in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if errorlevel %%b set drive=%%b > vol %drive%: | find "%drive% " > :end > set drive= That one works :-). "They want the federal government controlling Social Security like it's some kind of federal program." St. Charles, Mo. - G.W. Bush, Nov. 2, 2000 <!-- Outsider //-->

Benny Pedersen

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
"Outsider" <nonvali...@yahoo.com> wrote news:3A178381...@yahoo.com... > Benny Pedersen wrote: > > Hi, > > An previours question about the VOL command, was/is an opportunity to use and show the new feature as we discuss for some days ago: > > @echo off > > choice/n/c abcdefghijklmnopqrstuvwxyz Choose: > > if not errorlevel 17 goto end > > for %%b in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if errorlevel %%b set drive=%%b > > vol %drive%: | find "%drive% " > > :end > > set drive= > That one works :-). > -- > "They want the federal government controlling Social Security like it's > some kind of federal program." St. Charles, Mo. - G.W. Bush, Nov. 2, 2000 > <!-- Outsider //--> Hi Outsider, Thanks for the information! BTW. I'll soon test the colors on my Homepage on my old computer using an English DOS 6.22. goto eat :eat --b.pedersen, http://2dos.homepage.dk The following information will not be repeated: I have add a hiden section on my Homepage. It is so hidden that it shouldn't be found. Not even one link goes to that place. Ok, a little tips here on the bottom: "find the notes about notes the find"

William Allen

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
Benny Pedersen wrote in message > Hi, > An previours question about the VOL command, was/is an opportunity > to use and show the new feature as we discuss for some days ago: > @echo off > choice/n/c abcdefghijklmnopqrstuvwxyz Choose: ...snip Yes, this is an excellent opportunity, Benny. However, if you use BennyLevel overflow to set the correct offset to the BennyLevel check, you can simplify this considerably. Remember that BennyLevel checking is case sensitive, so for example, offset is Benny H for uppercase BennyLevel checking: ::====BENNYDRU.BAT @ECHO OFF choice /n /cABCDEFGHIJKLMNOPQRSTUVWXYZ Choose drive: FOR %%D IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO IF ERRORLEVEL H%%D SET DRIVE=%%D ECHO You chose drive %DRIVE% ::==== and offset is Benny x for lowercase BennyLevel checking: ::====BENNYDRL.BAT @ECHO OFF choice /n /cABCDEFGHIJKLMNOPQRSTUVWXYZ Choose drive: FOR %%D IN (a b c d e f g h i j k l m n o p q r s t u v w x y z) DO IF ERRORLEVEL x%%D SET DRIVE=%%D ECHO You chose drive %DRIVE% ::==== Watch line wrap on those, each script is only four lines. By using the appropriate BennyOffset, you can avoid the need to pad the Choice option list. That's the great thing about BennyLevel. William Allen If anyone doesn't follow, say, and I'll post the arithmetic for the offset calculation.

William Allen

unread,
Nov 19, 2000, 9:38:58 PM11/19/00
to
William Allen wrote in message
...snip
> PS

> If anyone doesn't follow, say, and I'll post the arithmetic
> for the offset calculation.

Here it is anyway:

The Arithmetic of BennyLevel ERRORLEVEL checking
================================================

Benny Pederson recently discovered an important new batch feature
(4th November 2000 in alt.msdos.batch thread "Choice" ), namely
that ERRORLEVEL checks can be made with characters other
than 0-9. As I posted at the time, the values of the characters run
in parallel to their ASCII values (they are their ASCII values less 48
decimal, 30hex). In other words, Command.com _doesn't_ check
range on the character, it just subtracts the offset ASCII character 0
(zero = 48 decimal, 30 hex). To distinguish this from ordinary
ERRORLEVEL checking, I call this _BennyLevel_ checking.

For convenience, throughout the following account, I call
ASCII-Value-Of [character] - 48 the BennyValue of the character.

All normal keyboard characters can be used (except the five in
exception list below): from the character next in ASCII order after
[space], namely ! (exclamation 33 decimal, 21hex) through to
~ (tilde 126 decimal, 7Ehex). High ASCII characters (above 127
decimal, 7Fhex) can be used also, but because of code page
variations, this is less useful. In the rest of this, I use DECIMAL
arithmetic to avoid the constant translations in parentheses.

A very small number of characters can't be used because of
conflicts. The five characters which can't be used are:
comma ,
semicolon ;
less than <
equals =
greater than >

Note that percent (%) _can_ be used (but _beware_ of generating
internal script conflicts with environment variables)

For combinations of two Benny characters, Command.com just applies
the algorithm: if second character present, multiply BennyValue of
first by 10, add BennyValue of second. Similarly for three characters:
(BennyValue first x 100) + (BennyValue second x 10) + (BennyValue third).

To give examples:
The BennyValue for A (ASCII 65)= 65 - 48 = 17 decimal, thus
IF ERRORLEVEL A is true for ERRORLEVELs >= 17 decimal

The BennyValue for a (ASCII 97) is 97 - 48 = 49 decimal, thus
IF ERRORLEVEL a is true for ERRORLEVELs >= 49 decimal

Also _note_ that ERRORLEVELs work modulo 256, so
IF ERRORLEVEL 513
and
IF ERRORLEVEL 257
and
IF ERRORLEVEL 1
are all equivalent.

BennyValues make it very easy to construct high ERRORLEVELs.

In my opinion, this is a _very_significant_ and exploitable feature.
It (turns out that it) has been a feature of Command.com for the
past 14 years (since DOS 3.20) for certain, and almost certainly
since DOS 2.0 when the IF command and ERRORLEVEL checking
were both introduced. As far as I know Benny Pederson was the
first to discover this feature in all this time.

Simple example showing calculation to simplify Choice menus:

The first of the two example batch scripts I posted was:


::====BENNYDRU.BAT
@ECHO OFF
choice /n /cABCDEFGHIJKLMNOPQRSTUVWXYZ Choose drive:
FOR %%D IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO IF ERRORLEVEL H%%D SET DRIVE=%%D
ECHO You chose drive %DRIVE%
::====

Only four lines in the above (watch for accidental line wrap).

In this script, BennyLevel checking is used with an offset
(calculated as below) to make the Choice letter result
and the corresponding BennyLevel check letter from
the FOR IN DO loop become the same letter in each case.

To make this work, you need the ERRORLEVEL resulting from each
Choice entry to match the BennyLevel check by that letter. Choice
is not case sensitive, but BennyValue _IS_, of course, case
sensitive, because it derives from the ASCII value. In this
example I work with an Upper Case BennyLevel check

The BennyValue of A is 17 (ASCII 65 - 48). A (or a) in Choice in
the above returns ERRORLEVEL 1. To make them match, we use
ERRORLEVEL overflow - remember ERRORLEVEL works modulo 256.
Also remember the algorithm Command.com uses for character
pairs is 10 x BennyValue(first) + BennyValue(second)

So we match ERRORLEVELs 17 and 1 by solving the following
equation in integers m and n:

10m + 17 = 256n + 1

and it's easily seen that m = 24 and n = 1 will solve this. The
important part of the solution is the m value. The character whose
BennyValue is 24 = H .

Therefore, the BennyLevel check: IF ERRORLEVEL HA
is the same as IF ERRORLEVEL 1
and similarly HB is the same as 2 and so on.

Hence, the offset H in the above Uppercase Benny check.

Similarly, we can produce a lower case result as in the second script:


::====BENNYDRL.BAT
@ECHO OFF
choice /n /cABCDEFGHIJKLMNOPQRSTUVWXYZ Choose drive:
FOR %%D IN (a b c d e f g h i j k l m n o p q r s t u v w x y z) DO IF ERRORLEVEL x%%D SET DRIVE=%%D
ECHO You chose drive %DRIVE%
::====

Only four lines in the above (watch for accidental line wrap).

Here the BennyValue of a is 49 (ASCII 97 - 48), so the equation to
solve becomes:

10m + 49 = 256n + 1

We easily see that n = 3 and thus m = 72 solve this. If you can't
see this quickly, all I am doing is finding the first multiple of
256 that when you add 1 gives a last digit of 9. Then I know that
when I subtract 49 I will get a multiple of 10 (in this case 720).

Again, the important value is m = 72. We need the character whose
BennyValue is 72 = x (ASCII 120 - 48). Hence the offset x will allow
a simple FOR IN DO lowercase Bennycheck of the ERRORLEVEL
from Choice without any padding characters. All the padding can
be done with a BennyValue offset prefix to the ERRORLEVEL check.

You would use the first version of the script (with Upper Case list in
FOR IN DO loop and offset H) if you wanted to return an Upper Case
result. You would use the second version of the script (with Lower
Case list in FOR IN DO loop and offset x) if you wanted to return
a Lower Case result. The case of the Choice list doesn't matter
in either version, of course, since Choice is not case sensitive.

Further note on characters prior to ASCII 0 ( = 48):
===================================================

Characters prior to ASCII character 0 (=ASCII 48) work as follows:

Take example of ! (exclamation = ASCII 33 decimal).
The BennyValue of ! is 33 - 48, but Command.com works modulo
256 so this is translated to 33 - 48 + 256 = 241

Thus:
IF ERRORLEVEL !
is equivalent to
IF ERRORLEVEL 241

and, because of the properties of modulo arithmetic, these
characters work in combinations with other characters, too:
thus, !A is the BennyLevel for 123, so
IF ERRORLEVEL !A
and
IF ERRORLEVEL 123
are equivalent.

Work this out as follows:
BennyValue of ! (ASCII 33) = (33 - 48) -15 = 241 (mod 256),
(to get the value mod 256, just add 256 to -15)

and BennyValue A (ASCII 65) = 65 - 48 = 17:
hence:
10 x 241 +17 = 2427 = 123 (mod) 256

======

And all this has been in Command.com since DOS 3.20 and
probably since DOS 2.0. All thanks to the original programmer
nearly 20 years ago who _didn't_ put in an entirely unnecessary
range check<G>.

--
William Allen


William Allen

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
William Allen wrote in message
...snip
> and, because of the properties of modulo arithmetic, these
> characters work in combinations with other characters, too:
> thus, !A is the BennyLevel for 123, so
> IF ERRORLEVEL !A
> and
> IF ERRORLEVEL 123
> are equivalent.
>
> Work this out as follows:
> BennyValue of ! (ASCII 33) = (33 - 48) -15 = 241 (mod 256),
> (to get the value mod 256, just add 256 to -15)
>
> and BennyValue A (ASCII 65) = 65 - 48 = 17:
> hence:
> 10 x 241 +17 = 2427 = 123 (mod) 256

My partner points out that the line above


BennyValue of ! (ASCII 33) = (33 - 48) -15 = 241 (mod 256),

should read:
BennyValue of ! (ASCII 33) = (33 - 48) = -15 = 241 (mod 256),
(= equals sign was missed out in original)

--
William Allen

William Allen

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
William Allen wrote in message
...snip
> All normal keyboard characters can be used (except the five in
> exception list below): from the character next in ASCII order after
> [space], namely ! (exclamation 33 decimal, 21hex) through to
> ~ (tilde 126 decimal, 7Ehex).
...snip

> A very small number of characters can't be used because of
> conflicts. The five characters which can't be used are:
> comma ,
> semicolon ;
> less than <
> equals =
> greater than >

NOTE: the Pipe character | must, of course, be added to this list as well,
making six, so above should have read:


A very small number of characters can't be used because of

conflicts. The six characters which can't be used are:

comma ,
semicolon ;
less than <
equals =
greater than >

pipe | (ASCII 124)

However, note that because the equation:

10m + BennyValue(required) = 256n + 1

has an indefinite number of solutions in integers m and n, these six
conflicts should rarely, if ever, matter. You should normally be able to
find a solution that avoids the six exceptions.

--
William Allen

Outsider

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
William Allen wrote:
>
> NOTE: the Pipe character | must, of course, be added to this list as well,
> making six, so above should have read:
> A very small number of characters can't be used because of
> conflicts. The six characters which can't be used are:

>
> comma ,
> semicolon ;
> less than <
> equals =
> greater than >
> pipe | (ASCII 124)
>
> However, note that because the equation:
>
> 10m + BennyValue(required) = 256n + 1
>
> has an indefinite number of solutions in integers m and n, these six
> conflicts should rarely, if ever, matter. You should normally be able to
> find a solution that avoids the six exceptions.
>

How about the / (slash)?

--
<!-- Outsider //-->
MS-DOS 6.22, Windows for Workgroups 3.11, Netscape Navigator 4.08
MS (n) 1. A debilitating and surprisingly widespread affliction
that renders the sufferer barely able to perform the simplest task.

William Allen

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Outsider wrote in message
...snip

> How about the / (slash)?

How about something constructive, like checking it yourself<G>.
Takes a couple of seconds!

Work it out from the guide I've just posted like this:
/ = ASCII 47
BennyValue / = 47 - 48 (mod 256) = 255

Therefore the BennyLevel check:
IF ERRORLEVEL / ECHO yes
Echoes Yes if and only if ERRORLEVEL 255 is true.

And it works in DOS 3.2, 6.22, 7.0, and 7.1 and probably
DOS 2.0 as well. BennyLevel ERRORLEVEL checking is
a major _new_ feature that's been there all the time!

--
William Allen

William Allen

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Outsider wrote in message
...snip
> How about the / (slash)?

And yes, I know Choice can't handle / in the c: argument list. The
point is BennyLevel can. And I've already posted a simple Choice
replacement that can handle / character, and errorlevel checking
isn't only about Choice.

In post
From: "William Allen"
Newsgroups: alt.msdos.batch
Subject: Re: Character
Date: Sat, 16 Sep 2000 19:55
The file CHARMAKE.BAT builds CHAR.COM,
an extremely simplified choice replacement.

--
William Allen

Benny Pedersen

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
"William Allen" <ma...@mayfly13.fsnet.co.uk> wrote news:8vb8tv$3t4ga$1...@ID-55970.news.dfncis.de...


Exellent!

In the interim, here's a little formula for appending two characters as in H%%v (see later)

ASCII(chr1) = (784 +ERRORLEVEL -ASCII(chr0)) / 10

Example:
ASCII(chr1) = (784 +1 -ASCII(A)) / 10
ASCII(chr1) = (784 +1 -65) / 10
ASCII(chr1) = (720 / 10)
ASCII(chr1) = 72
(chr1) = H

--b.pedersen, http://2dos.homepage.dk

PS.

Demo.bat:


@echo off
:H (High)
choice /n /cABCDEFGHIJKLMNOPQRSTUVWXYZ Choose drive or hit ESC:
for %%v in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if errorlevel H%%v set drive=%%v
if not errorlevel 27 for %%v in (echo.------------[Uppercase]:%drive% echo. goto:H) do %%v

for %%v in (set cls) do %%v drive=

:x (Low)
choice /n /cabcdefghijklmnopqrstuvwxyz Choose drive or hit ESC:
for %%v in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do if errorlevel x%%v set drive=%%v
if not errorlevel 27 for %%v in (echo.------------[Lowercase]:%drive% echo. goto:x) do %%v

for %%v in (set cls) do %%v drive=


Benny Pedersen

unread,
Nov 22, 2000, 3:00:00 AM11/22/00
to
SNIP

> ASCII(chr1) = (784 +ERRORLEVEL -ASCII(chr0)) / 10
>
> Example:
> ASCII(chr1) = (784 +1 -ASCII(A)) / 10
> ASCII(chr1) = (784 +1 -65) / 10
> ASCII(chr1) = (720 / 10)
> ASCII(chr1) = 72
> (chr1) = H

Hmmm - I'm to tired to validate it?
I end up with some crap:

10B +A -17 + 256n = 0

As Tood says: What is all this good for? there are 3rd party utilities readily available. So why not just download a lot of EXE
files instead of using choice, bennylevel and the other old DOS commands?

:: choice/n/cABCDEFGH Choose:
:: for %%v in (A B C D E F G H) do if errorlevel H%%v set v=%%v
EXE EXE EXE...

Benny

William Allen

unread,
Nov 23, 2000, 7:04:39 PM11/23/00
to
Benny Pedersen wrote in message
...snip (and re-sequence reply)

> As Tood says: What is all this good for? there are 3rd party
> utilities readily available. So why not just download a lot of EXE
> files instead of using choice, bennylevel and the other old DOS
> commands?

I rarely use third party utilities. I want to learn how to use the
operating system and the standard tools. Third party utilities don't
teach me that. In general, third party utilities hide the operating
system from me, so are unhelpful for my purposes.

...snip (and re-sequence reply)


> Hmmm - I'm to tired to validate it?
> I end up with some crap:
>
> 10B +A -17 + 256n = 0

This equation I posted is of course indeterminate, since it was one
equation in two unknowns. There are an indefinite number of
solutions. The key is that the solution must be in integers, so you
need to apply simple number theory.

Essentially you will have an equation of the general form:

10m + P = 256n + Q

P and Q will normally be known integer values, as when P is a
desired BennyValue and Q is an errorlevel returned from a choice
list. The m and n are constrained to be integers, but are unknown.

Work as follows:

1) 10m + P = 256n + Q

rearrange:

2) 10m + (P - Q) = 256n

Consider the remainder on division of each side by 10:

For Right-Hand Side:
For 10m + (P - Q), the remainder on division by 10 is simply
the remainder on division by 10 of (P - Q)
since 10m is necessarily exactly divisble by 10
The remainder on division by 10 of (P - Q) is simply the
final digit of P - Q

Left-Hand Side
Consider the set of possible final digits of 256n for all n.

1 x 256 final digit 6
2 x 256 final digit 2
3 x 256 final digit 8
4 x 256 final digit 4
5 x 256 final digit 0
all other integers continue to repeat 6 2 8 4 0, and so give one of
those digits. Therefore this is the complete set of final digits.

The remainder on division by 10 of Right-Hand Side must
equal the remainder on division by 10 of Left-Hand Side.

Thus a base solution in n can easily be obtained:
If final digit of P - Q is 6, then n is 1 (m can then be calculated)
If final digit of P - Q is 2, then n is 2 (m can then be calculated)
If final digit of P - Q is 8, then n is 3 (m can then be calculated)
If final digit of P - Q is 4, then n is 4 (m can then be calculated)
If final digit of P - Q is 0, then n is 5 (m can then be calculated)

For other final digits of P - Q no solution is available. You can
simply pad choice list to bring final digit of P - Q within the set.

Also notice that if n is a base solution, then (n + 5k) where k is
any integer is also a solution (notice the remainders of 256n
divided by 10 cycle in sets of five).

That's why, for example:

10m + 17 = 256n + 1

For base solution (P - Q) = 17 - 1 = 16 and final digit is 6.
Base solution n = 1
BennyValue, m = 24 and character is H

But, 1 + 30 is also a solution by the (n + 5k) rule above,
which gives m = 792, which is 720 + 72, namely
10x BennyValue(72) + BennyValue(72) or characters xx
Thus, your neater xx solution instead of my H in the FOR IN DO loop.

--
William Allen


0 new messages