I wanted to relive the nostalgia of good old dos.
I've been testing a few batch commands but I've noticed /a
isn't usable in dos.
Is there another method I can use to add two variables without including /a
?
@echo off
::this is how I would originally add two numbers
set /p number1=
set /p number2=
set /a "number1=number1+number2"
echo %number1%
pause >nul
exit
dos states "invalid switch. - /a"
when I run this program.
It's a bit more tricky than using set /a
, but it can be solved with MS-DOS 6.22.
One part is to write a function to add single digits and one function that can add multiple digits.
The main problem is to split a number into single digits, because MS-DOS doesn't support string manipulation.
But it exists a tiny flaw in the FOR-Loop handling, /
splits a text into three parts.
for %%a in (`abcdef/ghijklmno`) do echo %%a
Outputs
abcdef g hijklmno
With this trick a number can be split into single digits
split.bat
@echo off
for %%P in (/%1.) do if %%P==: goto %1
set _idx=
set _remain=%2
set _splitRev=
set _splitRev_comma=
:loop
set _loop=1
for %%a in (/%_remain%) do call %0 :split %1 %%a
if NOT "%_remain%"=="" goto :loop
set %1=%_splitRev%
set %1_comma=%_splitRev_comma%
REM Clear temp vars
FOR %%v in (_remain _idx _loop _splitRev _splitRev_comma) do set %%v=
goto :eof
:split
if %_loop%%==2 goto :split_2
set _loop=2
set _remain=
set _splitRev=%3%_splitRev%
set _splitRev_comma=%3,%_splitRev_comma%
goto :eof
:split_2
set _remain=%3
goto :eof
:eof
And the add.bat looks like
@echo off
for %%P in (/%1.) do if %%P==: goto %1
call split _valueRev1 %1
call split _valueRev2 %2
set _result=
set _carry=
for %%d in (%_valueRev1_comma%,0,0,0,0,0) do call %0 :getDig1 %%d
REM Remove leading zeros
:zeroLoop
for %%z in (/%_result%) do set _remain=%%z
if not %_result%==0%_remain% goto :finish
set _result=%_remain%
goto :zeroLoop
:finish
echo %1+%2=%_result%
REM Clear temp vars
FOR %%v in (_result _carry _len _digit1 _digit2 _remain _valueRev1 _valueRev1_comma _valueRev2 _valueRev2_comma) do set %%v=
goto :eof
:getDig1
set _digit1=%2
set _digit2=
for %%d in (/%_valueRev2%0) do call %0 :getDig2 %%d
set _len=%_carry%
call %0 :lenAddDigit %_digit1%
call %0 :lenAddDigit %_digit2%
call %0 :len2val
set _result=%_val%%_result%
goto :eof
:getDig2
if not "%_digit2%"==" set _valueRev2=%2
if "%_digit2%"=="" set _digit2=%2
goto :eof
:lenAddDigit
if %2==1 set _len=%_len%#
if %2==2 set _len=%_len%##
if %2==3 set _len=%_len%###
if %2==4 set _len=%_len%####
if %2==5 set _len=%_len%#####
if %2==6 set _len=%_len%######
if %2==7 set _len=%_len%#######
if %2==8 set _len=%_len%########
if %2==9 set _len=%_len%#########
goto :eof
:len2val
set _carry=
set _val=
if %_len%.==. set _val=0
if %_len%.==. goto :eof
if %_len%==# set _val=1
if %_len%==## set _val=2
if %_len%==### set _val=3
if %_len%==#### set _val=4
if %_len%==##### set _val=5
if %_len%==###### set _val=6
if %_len%==####### set _val=7
if %_len%==######## set _val=8
if %_len%==######### set _val=9
if NOT "%_val%"=="" goto :eof
set _carry=#
if %_len%==########## set _val=0
if %_len%==########### set _val=1
if %_len%==############ set _val=2
if %_len%==############# set _val=3
if %_len%==############## set _val=4
if %_len%==############### set _val=5
if %_len%==################ set _val=6
if %_len%==################# set _val=7
if %_len%==################## set _val=8
if %_len%==################### set _val=9
goto :eof
:eof
Tested successfully on a MS-DOS 6.22 (VMWare)
#Limitations of MS-DOS 6.22
IF
doesn't support ELSE
Workaround:
IF %1==b echo It is equal
IF NOT %1==b echo It isn't equal
Only goto
can jump to a label, CALL
can only start another batch.
Workaround:
Put something like this into the first line of your batch
FOR %%P in (/%1) do IF %%P==: goto %1
...
REM This calls the current batch file and jumps to a label
CALL %0 :myLabel arg1
...
:myLabel
echo arg1=%2
echo Action1
echo Action2
goto :eof
No code blocks, like
FOR %%a in (1 2 3 ) do (
set concat=%%a
echo %concat%
)
Workaround:
FOR %%a in (1 2 3 ) do CALL %0 :myFunc %%a
No indirect expansion of variables
Workaround:
set var=content
set indirect=var
> temp$$$.bat echo set result=%%%indirect%%%
call temp$$$.bat
echo result=%result%
If you're trying to do this from actual DOS (and not Windows's emulation from the 32-bit era), it's simply not possible, unless you manually handle each possible pair of numbers you could have as input (which grows unmanageable when you go above the single-digits).
This was always a large deficiency in DOS's batch files, which was usually remedied by calling small scripts in actual scripting languages (such as BASIC), often being written out by the same .bat file that called them. This, of course, requires having an interpreter for your language of choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With