Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Doing simple math from the command line (like PowerShell)

Aug
1,914
68
I like the way that one can do simple math from the PowerShell command line, example;
Code:
PS E:\utils> 52*4
208

Using the following alias;
Code:
e:\utils>alias unknown_cmd
echo %@eval[%@filter[0123456789.*+-/\,"%$"]]

...I can now do;
Code:
e:\utils>52*4
208
...from the TCC Command line.

Again, this is only for simple math, not for log(), fact(), MOD, etc.

When I enter an UNKNOWN_CMD, for example;
Code:
e:\utils>dze
TCC: No expression ""

...which is not pretty, but it works.

The next evolution of doing simple math from the TCC command line involved changing the alias to;
Code:
alias unknown_cmd=e:\utils\unknown_cmd.btm

...and creating UNKNOWN_CMD.BTM
Code:
@setlocal
@echo off
unalias unknown_cmd

set UseEval=N

iff %@isalpha[%$] eq 0 then
  iff %@isfloat[%$] eq 0 then
    iff %@isalnum[%$] eq 0 then
      set UseEval=Y
    endiff
  endiff
endiff

iff %UseEval eq Y then
  echo %@eval[%@filter[0123456789.*+-/\,"%$"]]
else
  on error gosub Catch
  %$
endiff

alias unknown_cmd=%_batchname

endlocal
quit

:Catch
echo       ?: %?
echo      _?: %_?
echo _Syserr: %_syserr

echo @isalpha: %@isalpha[%$]
echo @isfloat: %@isfloat[%$]
echo @isalnum: %@isalnum[%$]

Return

...returns;
Code:
e:\utils>dze
      ?: 0
     _?: 0
_Syserr: 536870913
@isalpha: 1
@isfloat: 0
@isalnum: 1

...which gives me more info than;
Code:
TCC: No expression ""

...but it works okay for me, as I use several AutoHotkey scripts for my non-conforming typing, for example;
Code:
e:\utils>type dre.ahk
:*:dre::dir

...which, when I type dre is automatically changed to dir.

Feel free to make modifications to this procedure for TCC command line math, but if you do, please share your modifications.

Joe
 
I have for a long time (and still do) just use an EVAL command, a wrapper for "ECHO %@EVAL[%$]". Once upon a time it was an alias; now it's a plugin. It gives the full power of @EVAL.

It's too bad an UNKNOWN_CMD alias or BTM can't invoke the default unknown command behavior. I wonder what would happen if a plugin UNKNOWN_CMD returned 0xFEDCBA98 (which means "I am disabled"). Would the default unknown command mechanism kick in? If so, perhaps one could capitalize on that.
 
Well, it does work. As a plugin, UNKNOWN_CMD can be selective and hand the job off to the built-in one. See my first test below. Now I have to think of a clever way to use it.

Code:
v:\> which unknown_cmd
unknown_cmd is a plugin command (4UTILS)

v:\> which foo
foo is an unknown command

v:\> foo
Aha! You issued "foo".

v:\> which bar
bar is an unknown command

v:\> bar
TCC: Unknown command "bar"
 
I've updated my script to work with my CALC.BTM script.
Code:
iff %UseEval eq Y then
  call e:\utils\calc.btm %$
  ::echo %@eval[%@filter[0123456789.*+-/\,"%$"]]
else
  on error gosub Catch
  %$
endiff

This allows me to use TAPE.BTM to view the history.

Posting mainly for my future reference, but others might also be interested.

Joe
 
Well, it does work. As a plugin, UNKNOWN_CMD can be selective and hand the job off to the built-in one. See my first test below. Now I have to think of a clever way to use it.

That turns out to be a whole lot trickier than I thought at first. For one thing, you can't rely on Evaluate()'s return code to tell you whether or not the string is a valid math expression.

For another, things like parentheses and angle brackets are long gone by the time an UNKNOWN_CMD handler sees the command line.
 
Yup! And testing the expression (with @EVAL[] or Evaluate()) could easily produce MAPM error messages. You can't even redirect those guys.

I think an UNKNOWN_CMD alias/plugin gets the whole command line. ... yes/no?
 
In the end, I use REXX. The basic calculator is fairly simple,
Code:
/* REXX */
numeric digits 15
parse arg chalk
interpret 'cheese=' chalk
say cheese
exit

If you want to add functions, you write these as subroutines. You can write specialised functions, or simply raid the AAT or some OS/2 bbs for the more generalised ones.

With little effort, you can add the likes of "datedif" to your calculator (add or subtract days, or the difference between two days).
 
Hey @Charles Dye;
I've decided that your CMath plugin is a much better method than my "unknown_cmd" method.

I've added it to my TCSTART.BTM file, so that it's available whenever I need it.

Thanks!

Joe
 
Hey @Charles Dye;
I've decided that your CMath plugin is a much better method than my "unknown_cmd" method.

I've added it to my TCSTART.BTM file, so that it's available whenever I need it.

Thanks!

Joe

Kind of a screwball approach, but it works.

For my part, mostly I use an EVAL alias. Similar to dcantor's, except it also saves the result to ANS.
 
The new %(()) syntax works as well. It is similar to Bash's $(()) syntax. An interesting side effect:
Code:
$ %((1+1))
TCC: Unknown command "2"
 
I used to use the aforementioned alias. Lately I've been using a simple plugin.

Code:
INT WINAPI EVAL ( WCHAR *psz )
{
    INT rv = Evaluate(psz);
    Printf(L"%s\r\n", psz);
    return rv;
}

It (the plugin) seems equal in speed to %(()). I'd guess the alias would be the same speed but I'm running into something odd when I try to test (sending output to NUL). With this alias

Code:
v:\> alias eval_alias
echo %@eval[%$]

I get

Code:
v:\> eval_alias log(5) - 2**10 + 7 -cos(0) + exp(10) + abs(-5)
21015.0752327192

v:\> eval_alias log(5) - 2**10 + 7 -cos(0) + exp(10) + abs(-5) > nul
1

Does anyone know what's happening there?

I worked around that difficulty and all three methods seem to be the same speed.

I vaguely remembered %(()) but I couldn't find it in the help. Where is it (other that "What's new" for some old version)?
 
The redirection is being treated as a comparison operator. And the result of the comparison is true or 1.

I found this is the What's New section of V23:
Code:
Variables:

You can return the result of a command with %(command).  This is the same as @EXEC[command] but a little easier to write.

%@ will return the batch file arguments (like %*), but they will all be double quoted.

Numeric variable expressions - %((...)) will evaluate and substitute the expression. For example:

echo %((3+5)) is the answer.

Conditional expressions - %[[...]] will evaluate the conditional expression, and return 0 if the exit status is true; 1 if it is not. For example:

echo %[[5 == 6]]
 
BTW - I typed "Numeric variable expressions" in the search tab of V28's help and it doesn't show up in the list.
 
Does anyone know what's happening there?
Here's what's happening. I don't like it and I doubt the behavior will be changed.

Code:
v:\> alias test `echo %@len[%$]`

v:\> test foo
3

v:\> test foo > NUL
9

I can work around that on the command line with (test foo) > NUL. But can I build protection against that into the alias itself? It seems this would affect all aliases which use %$ among the arguments to a variabe function.
 
The redirection is being treated as a comparison operator. And the result of the comparison is true or 1.

I found this is the What's New section of V23:
Code:
Variables:

You can return the result of a command with %(command).  This is the same as @EXEC[command] but a little easier to write.

%@ will return the batch file arguments (like %*), but they will all be double quoted.

Numeric variable expressions - %((...)) will evaluate and substitute the expression. For example:

echo %((3+5)) is the answer.

Conditional expressions - %[[...]] will evaluate the conditional expression, and return 0 if the exit status is true; 1 if it is not. For example:

echo %[[5 == 6]]

I found it in the v28 help file, after finding it in the v27 help file;

1628901831108.png


Joe
 
The redirection is being treated as a comparison operator. And the result of the comparison is true or 1.

I found this is the What's New section of V23:
Code:
Variables:

You can return the result of a command with %(command).  This is the same as @EXEC[command] but a little easier to write.

%@ will return the batch file arguments (like %*), but they will all be double quoted.

Numeric variable expressions - %((...)) will evaluate and substitute the expression. For example:

echo %((3+5)) is the answer.

Conditional expressions - %[[...]] will evaluate the conditional expression, and return 0 if the exit status is true; 1 if it is not. For example:

echo %[[5 == 6]]
Doesn't that require the %[[conditional]] syntax. That's not in my example.

And what about these (below). The help for @EVAL does not contain the word "condition[al]".

Code:
v:\> echo %@eval[2 < 1]
0

v:\> echo %@eval[2 > 1]
1
 
I can work around that on the command line with (test foo) > NUL. But can I build protection against that into the alias itself? It seems this would affect all aliases which use %$ among the arguments to a variabe function.
I don't think old versions did that. I don't have an old version installed to test. I have similar aliases that are now not working with redirection. For example:

Code:
C:\>alias bc
echo %@eval[%$]

C:\>bc 2+2
4

C:\>bc 2+2 > clip:
TCC: Syntax error "2+2 > clip:"
 
I don't think old versions did that. I don't have an old version installed to test. I have similar aliases that are now not working with redirection.
Hmmm! It fails as far back as v16.

Code:
v:\> ver
TCC  16.03.55   Windows 7 [Version 6.1.7601]

v:\> alias eval_alias
echo %@eval[%$]

v:\> eval_alias 2+2 > clip:
TCC: Syntax error "2+2 > clip:"

When packaged like this, it's OK.

Code:
v:\> do i=1 to 1 ( %comspec /c eval_alias 3+3 ^> clip: ) & echo %@clip[0]
6

or even like this

Code:
v:\> do i=1 to 1 ( %comspec /c eval_alias 4+4 > clip: ) & echo %@clip[0]
8

And while redirection has problems, piping does not.

Code:
v:\> eval_alias 5+5 | findstr /r .
10
 
If you use %$ in a btm, you only get up to the redirection. Why should an alias be different?

Code:
C:\Junk>type Foo.btm
set Bar=%$

C:\Junk>Foo.btm 567

C:\Junk>echo %Bar
567

C:\Junk>Foo.btm 890 > clip:

C:\Junk>echo %Bar
890
 
Back
Top