Jeval.bat : command line calculator using native code

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
catalinnc
Posts: 39
Joined: 12 Jan 2015 11:56

Re: Jeval.bat : command line calculator using native code

#16 Post by catalinnc » 29 Jan 2015 16:03

thank you very much for your answer...
_

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Jeval.bat : command line calculator using native code

#17 Post by misol101 » 04 Feb 2018 16:50

This calculator script was just what I was looking for, but I found it cumbersome that I would have to remember jscript API syntax just to use operations such as sin,cos etc.

E.g: jeval "Math.sin(Math.PI/2)"

Here, both sin and PI are case sensitive in addition.
Also, I wanted the possibility to show the output as hex.

Below is math.bat, which would allow something like:

math "sin(pi/2)" /H

Output: 0x1

Let me know of any issues.

Code: Select all

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment

::************ Documentation ***********
:::
:::math "JScriptExpression" [/N] [/H] [/B] [/P]
:::math /?
:::
:::  Evaluates a JScript expression and writes the result to stdout.
:::
:::  A newline is not appended to the result unless /N is used.
:::
:::  Use /H for hexadecimal output, /B for binary output, /P to pad.
:::
:::  Enclose any JScript string literals with single quotes.
:::
:::  Math functions (case insensitive):
:::  abs acos asin atan atan2 ceil cos exp floor log max min pow random round sin sqrt tan
:::
:::  Math constants (case insensitive):
:::  LN2 LN10 LOG2E LOG10E PI SQRT1_2 SQRT2
:::
:::  Bitwise operators:
:::  & | ^ ~ << >>
:::
:::  Example:
:::    math "sin(pi/2) | 0xe" /H /P
:::
:::  Output:
:::    0x0000000F
:::

::************ Batch portion ***********
@echo off

if "%~1" equ "" (
  call :err "Insufficient arguments"
  exit /b
)
if "%~2" neq "" if /i "%~2" neq "/N" if /i "%~2" neq "/H" if /i "%~2" neq "/B" if /i "%~2" neq "/P" (
  call :err "Invalid option"
  exit /b
)
if "%~1" equ "/?" (
  setlocal enableDelayedExpansion
  for /f "delims=" %%A in ('findstr "^:::" "%~f0"') do (
    set "ln=%%A"
    echo(!ln:~3!
  )
  exit /b
)
cscript //E:JScript //nologo "%~f0" %*
exit /b

:err
>&2 echo ERROR: %~1. Use math /? to get help.
exit /b 1


************ JScript portion ***********/

String.prototype.replaceI = function(strReplace, strWith) {
    // See http://stackoverflow.com/a/3561711/556609
    var esc = strReplace.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    var reg = new RegExp(esc, 'ig');
    return this.replace(reg, strWith);
};

var inp = WScript.Arguments.Unnamed(0)
var find = ["abs(", "acos(", "asin(", "atan(", "atan2(", "ceil(", "cos(", "exp(", "floor(", "log(", "max(", "min(", "pow(", "random(", "round(", "sin(", "sqrt(", "tan(", "LN2", "LN10", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2"]
var repl = ["abs(", "mathAcs(", "mathAsn(", "mathAtn(", "mathAtn2(", "ceil(", "cos(", "exp(", "floor(", "log(", "max(", "min(", "pow(", "random(", "round(", "sin(", "sqrt(", "tan(", "LN2", "LN10", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2"]

for (var i = 0; i < find.length; i++) {
	inp = inp.replaceI(find[i], "Math." + repl[i]);
}

find = ["mathAcs(", "mathAsn(", "mathAtn(", "mathAtn2("]
repl = ["acos(", "asin(", "atan(", "atan2("]

for (var i = 0; i < find.length; i++) {
	inp = inp.replaceI(find[i], repl[i]);
}

outp = eval(inp);
if (WScript.Arguments.Named.Exists("h")) {
	outp = eval(Math.floor(outp))
	if (outp < 0)
		outp = 0xFFFFFFFF + outp + 1;
	outp = outp.toString(16).toUpperCase()
	if (WScript.Arguments.Named.Exists("p")) {
		var pad="00000000"
		outp = "0x" + pad.substring(0, pad.length - outp.length) + outp
	} else
		outp = "0x" + outp
} else if (WScript.Arguments.Named.Exists("b")) {
	outp = eval(Math.floor(outp))
	if (outp < 0)
		outp = 0xFFFFFFFF + outp + 1;
	outp = outp.toString(2)
	if (WScript.Arguments.Named.Exists("p")) {
		var pad="00000000000000000000000000000000"
		outp = pad.substring(0, pad.length - outp.length) + outp
	}
}

if (WScript.Arguments.Named.Exists("n")) {
	WScript.StdOut.WriteLine(outp);
} else {
	WScript.StdOut.Write(outp);
}
Last edited by misol101 on 17 Feb 2018 11:41, edited 1 time in total.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Jeval.bat : command line calculator using native code

#18 Post by misol101 » 16 Feb 2018 15:23

I suppose everyone else realized already, but it just hit me that eval can do intermediate calculations as well! Like:

math "a=2*1.5, b=a-2, b+a*a"
Output: 10

Of course the orginal jeval.bat can do exactly the same, but I just felt like pointing this "trick" out since I think it makes for a more useful calculator.

Post Reply