%+ in a function?

May 30, 2008
65
1
#1
I'm using TCC (not LE) 11.00.48.
Is this a bug or intentional?

Look at this one (ignore the actual contents as it is just an example, make note of the %+):
function aa=`set test=a%+echo testing`

if you try to call it on the commandline "%@aa[]" then it does what's
expected, i.e set test to "a" and output "testing"

However, try doing this as part of a PDIR command:

pdir /(@aa
[*])

Now that function displays the code of that function (with eventual expanded variables), and doesn't run it.
if the %+ isn't present, the function would run in similar manner as on the commandline.

I'm asking because I have a bit of need to use some temporary variables as recalculating CRC32 is slow, and PDIR should both display and compare with the crc contained in the filename) in a function.

Is there eventual alternatives which can be used to set a variable which would work in a function definition (AND work with PDIR)?
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,665
46
Albuquerque, NM
prospero.unm.edu
#2
I'm using TCC (not LE) 11.00.48.
Is this a bug or intentional?

Look at this one (ignore the actual contents as it is just an example, make note of the %+):
function aa=`set test=a%+mfix`

if you try to call it on the commandline "%@aa[]" then it does what's
expected, i.e set test to "a" and run mfix.

However, try doing this as part of a PDIR command:

pdir /(@aa
[*])

Now that function displays the code of that function (with eventual expanded variables), and doesn't run it.
Which is what PDIR is supposed to do, right -- display a string, not execute a command?

If you really want to execute commands within a function within PDIR, then it might be possible using @EXEC or @EXECSTR. I don't know, I haven't tried it, I'm not going to try it; it feels like a dodgy kludge to me. If the object of the game is to iterate over a series of filenames and execute a command, then a DO loop or a FOR loop would seem like the more natural approach.
 
May 30, 2008
65
1
#3
Which is what PDIR is supposed to do, right -- display a string, not execute a command?

If you really want to execute commands within a function within PDIR, then it might be possible using @EXEC or @EXECSTR. I don't know, I haven't tried it, I'm not going to try it; it feels like a dodgy kludge to me. If the object of the game is to iterate over a series of filenames and execute a command, then a DO loop or a FOR loop would seem like the more natural approach.
You DO know that for instance
PDIR /D /K /M /(dd.m.y th:m zc -40fn "CRC: "@crc32
[*])
is something that executes some code/function (crc32) for each file?

What I'm trying to do, and which is should easily do, is to do a similar thing, but with a userdefined function.

A proof that it CAN do the same with a userdefined function:
function nowampm=`%@if[%_hour lt 13,%@if[%_hour gt 0,%_hour,12],%@eval[%_hour-12]]:%_minute %@if[%_hour lt 12,a,p]m`

PDIR /D /K /M /(dd.m.y th:m zc -40fn @nowampm
[*])

HOWEVER, if a %+ is in that function, it displays the code rather than executing it.

Edit: btw, the function above is from the date and time functions in these forums, and is only used as an example here.
 
May 30, 2008
65
1
#4
My intention is that it, in addition to displaying the normal file information, should extract a crc32 value from the filename if it exists (between "[","(" or "{" and "}",")" or "]" using a regex), compare it with the actual crc32 value, then display the current crc32 value followed by either OK or FAILED.

The display crc32 and compare with the actual crc32 is the crux. Unless a variable is used it needs to calculate crc32 two times (which my function currently does, but it is seriously ineffective).
The trouble is, unless the SET statement is terminated by %+ , no variable can be set, as I know of anyway.
And when %+ seemingly cant be used in a function called by PDIR, then..

I want to use PDIR because it can show proper file information AND evaluate some code/function (with the result displayed within that list) without recreating the entire DIR command.
 
#5
On Tue, 27 Apr 2010 20:24:27 -0400, myarmor <> wrote:

|PDIR /D /K /M /(dd.m.y th:m zc -40fn @nowampm[*])
|
|HOWEVER, if a %+ is in that function, it displays the code rather than executing it.

A UDF must evaluate to an expression. UDF's seem unlikely places for command
separators. But used correctly, it does work:

v:\> function myfunc `%@execstr[echos foo %+ echos %@filesize[%1]]`

v:\> PDIR /D /K /M /(dd.m.y th:m zc -4fn @myfunc[*]) *.zip

Volume in drive V is DATA Serial number is c007:d3e4
Directory of V:\*.zip

18.07.2009 13:19 5,543,374 4console.zip foo5543374
29.08.2009 10:13 53,817 4utils.zip foo53817
03.10.2009 20:50 119 a b.zip foo119
16.09.2009 17:39 5,195,737 gcolon.zip foo5195737
02.08.2009 17:28 404,824 ipv4.zip foo404824
06.10.2009 09:24 123 jlc.zip foo123
13.02.2008 00:00 14,501,646 jpnews.zip foo14501646
18.01.2010 11:25 58,024 minitabcd.zip foo58024
26.10.2009 14:51 55,502 sysutils.zip foo55502
--
- Vince
 
May 30, 2008
65
1
#6
A UDF must evaluate to an expression. UDF's seem unlikely places for command
separators. But used correctly, it does work:
--
- Vince
In other words, it can't use a variable for temporary storage while performing the evaluation, such as in this case, store the crc32 value to avoid calculating it twice.

Somehow it seems like a strange limitation as multiple statements in a userfunction apparently is allowed (through %+), but apparently not in PDIR.
Everything I described above can be done as long as I recalculate crc32 twice rather than using a variable.
However, that is slooow..
 
#7
My intention is that it, in addition to displaying the normal file information, should extract a crc32 value from the filename if it exists (between "[","(" or "{" and "}",")" or "]" using a regex), compare it with the actual crc32 value, then display the current crc32 value followed by either OK or FAILED.
Are you saying the file name may contain a CRC? How do you propose to determine if the filename contains a CRC? Does this filename contain a CRC: "CBDB99D8FED.txt"? If so, what CRC does it contain?
 
May 30, 2008
65
1
#8
Are you saying the file name may contain a CRC? How do you propose to determine if the filename contains a CRC? Does this filename contain a CRC: "CBDB99D8FED.txt"? If so, what CRC does it contain?
Yes.. Most often in the format "filename [12345678].dat"
The text between [] is the crc32, which are then compared to the actual crc32, resulting in a OK or FAILED.

And to answer how, some rather basic use of @regexsub (this is where I'd like a second variable as I use it first to check if it contains a crc32 value, next I compare with the actual crc32).
 

rconn

Administrator
Staff member
May 14, 2008
10,627
97
#9
> I'm using TCC (not LE) 11.00.48.
> Is this a bug or intentional?
>
> Look at this one (ignore the actual contents as it is just an example,
> make note of the %+):
> function aa=`set test=a%+mfix`
>
> if you try to call it on the commandline "%@aa[]" then it does what's
> expected, i.e set test to "a" and run mfix.
>
> However, try doing this as part of a PDIR command:
>
> pdir /(@aa[*])
>
> Now that function displays the code of that function, and doesn't run
> it.
> if the %+ isn't present, the function would properly.
This has nothing to do with %+ -- this won't work with or without %+. (BTW,
why the sudden fascination with %+, which has been obsolete for years??)

The [*] UDF syntax in PDIR supports functions that take a single filename
argument, by passing the current filename and printing the output of that
function.

What you're doing is passing "%aa[filename]" to the parser, which duly
substitutes "set test=a&mfix" and passes that back to be printed by PDIR.
It does *not* execute random commands embedded in the UDF. (That would be a
very, very bad thing -- you really wouldn't want PDIR to be executing every
filename as though it were a command!)

Rex Conn
JP Software
 
#10
On Tue, 27 Apr 2010 22:21:50 -0400, myarmor <> wrote:

|Yes.. Most often in the format "filename [12345678].dat"
|The text between [] is the crc32, which are then compared to the actual crc32, resulting in a OK or FAILED.

Here's a crude attempt. There is no problem with %+ if you use it correctly.

v:\test7> function CRCCHECK `%@execstr[set CRC=%@regexsub[0,(?i)[0-9A-F]{8},%1]
%+ if defined CRC echos %@if[%crc == %@crc32[%1],OK,FAILED] %+ unset CRC]`

v:\test7> PDIR /(dd.m.y th:m zc -4fn @crccheck[*]) *.dat
27.04.2010 22:37 0 filename[00000000].dat OK
27.04.2010 22:44 23 filename[9E1A2E5F].dat OK
27.04.2010 22:23 0 filename[12345678].dat FAILED

As you can see below, it worked.

v:\test7> for %f in (*) echo %f %@crc32[%f]
filename[00000000].dat 00000000
filename[12345678].dat 00000000
filename[9E1A2E5F].dat 9E1A2E5F
--
- Vince
 
May 30, 2008
65
1
#11
This has nothing to do with %+ -- this won't work with or without %+. (BTW,
why the sudden fascination with %+, which has been obsolete for years??)

The
[*] UDF syntax in PDIR supports functions that take a single filename
argument, by passing the current filename and printing the output of that
function.

What you're doing is passing "%aa[filename]" to the parser, which duly
substitutes "set test=a&mfix" and passes that back to be printed by PDIR.
It does *not* execute random commands embedded in the UDF. (That would be a
very, very bad thing -- you really wouldn't want PDIR to be executing every
filename as though it were a command!)

Rex Conn
JP Software
As I said, that was an example. the real one only uses rather basic variable functions (@IF,@REGEX, @REGEXSUB and @CRC32 and the usual %1), but in some cases, such as the above it is nice to be able to store some temporary data in a variable.

Btw, what is the new name (if it exists) for %+ ?

%+ is described under the header "Multiple Commands" in the current helpfile, and somewhere else I've read that you should use it rather than & as it changes if the command separator changes.
It says nothing about being deprecated/obsolete under the header "+ (pseudovariable)"
 
May 30, 2008
65
1
#12
@vefatica, thank you so much..
It was enough to achieve what I wanted to do more or less:

function pdir_aa=`%@execstr[set pdirCRC=%@regexsub[1,(?i)[\[({]([0-9A-F]{8})[\])}],%1] %+ if defined pdirCRC echos %@if[%pdirCRC == %@crc32[%1],OK,FAILED] %+ unset pdirCRC]`

pdir /D /K /M /(dd.m.y th:m zc -40fn @pdir_aa
[*]) %1

I'm scratching my head about what conditions there are when pdir decides to print rather than execute the code though.

I have alot of these files, so multiple runs of crc32 to check and display a crc32 value wasn't what I wanted, but this one seems to work nicely.
 
May 30, 2008
65
1
#14
On Tue, 27 Apr 2010 23:10:32 -0400, myarmor <> wrote:

|Btw, what is the new name (if it exists) for %+ ?

It's the command separator, the ampersand, "&".
--
- Vince
First line of the documentation for + (Pseudo variable):
+ is the current command separator. Use this pseudovariable, instead of the actual command separator, if you want your batch files and aliases to work in other users' environment regardless of how the command separator is defined.

But if it's obsolete in favor of instead being dependent on the current command separator (i.e if I change the command separator to something else, good luck trying to run the batchfiles), well..
 
#15
>
> This has nothing to do with %+ -- this won't work with or without %+.
> (BTW,
> why the sudden fascination with %+, which has been obsolete for years??)
>
I still use %+, especially when posting to this group, since my own setup
requires ^ as the command separator. When I copy/paste my examples, it
confuses folk when I use my ^ character.

I have a lot of batch files that were created eons ago now, and ^ was _the_
way to do it then. I try to migrate, when I can, but there is no good way to
transition all at once from ^ to &.

In short, please do not remove the %+ nor the ability to use ^. I know you
did that in TCCLE, but I forgive that as being one more reason to convince
others to use the full version.

--
Jim Cook
2010 Sundays: 4/4, 6/6, 8/8, 10/10, 12/12 and 5/9, 9/5, 7/11, 11/7.
Next year they're Monday.
 
#16
On Tue, 27 Apr 2010 23:22:16 -0400, myarmor <> wrote:

|function pdir_aa=`%@execstr[set pdirCRC=%@regexsub[1,(?i)([0-9A-F]{8}),%1] %+ if defined pdirCRC echos %@if[%crc == %@crc32[%1],OK,FAILED] %+ unset pdirCRC]`

I believe you want match 0.

And you are not requiring the ()s in the file name. To do so, escape them as
(?i)\([0-9A-F]{8}\) and compare the result to (%@crc32[%1]).
--
- Vince
 
May 30, 2008
65
1
#17
On Tue, 27 Apr 2010 23:22:16 -0400, myarmor <> wrote:

|function pdir_aa=`%@execstr[set pdirCRC=%@regexsub[1,(?i)([0-9A-F]{8}),%1] %+ if defined pdirCRC echos %@if[%crc == %@crc32[%1],OK,FAILED] %+ unset pdirCRC]`

I believe you want match 0.

And you are not requiring the ()s in the file name. To do so, escape them as
(?i)\([0-9A-F]{8}\) and compare the result to (%@crc32[%1]).
--
- Vince
No need.. :)
I guess 0 would include [({ and })], in other words the entire match, 1 only includes whats in the first group.
() usually doesn't need to be escaped in a character class/set, and apparently doesn't need it in tcc :)
I've used () both in a character class, and for grouping.

I corrected what you quoted a few minutes after I posted it.
 
#18
On Tue, 27 Apr 2010 23:54:57 -0400, myarmor <> wrote:

|I guess 0 would include [({ and })], in other words the entire match, 1 only includes whats in the first group.
|() usually doesn't need to be escaped in a character class, and apparently doesn't need it in tcc :)

Don't you want to require the literal ()s? I don't think you are doing so:

These aren't doing what you want:

v:\> echo %@regexsub[0,(?i)([0-9A-F]{8}), a12345678b.txt]
a1234567

v:\> echo %@regexsub[1,(?i)([0-9A-F]{8}), a12345678b.txt]
a1234567

You want the literals in there somehow:

v:\> echo %@regexsub[0,(?i)\([0-9A-F]{8}\), a(12345678)b.txt]
(12345678)

v:\> echo %@regexsub[1,(?i)\(([0-9A-F]{8})\), a(12345678)b.txt]
12345678
--
- Vince
 
#19
I still use %+, especially when posting to this group, since my own setup requires ^ as the command separator.
I'm also somewhat puzzled by referring to %+ as being obsolete. To me, it's the perfect way of rendering different command separators in different installations a non-issue.

I haven't used the default command separator character in years due to occasional issues with filenames that have ampersands in them. I always use the %+ pseudovariable when writing aliases and .btm files since my own installation is customized but others might not be (and usually aren't). To my way of thinking, its use is a *much* better practice than assuming that the default character hasn't been changed. Whether or not it's still the ampersand makes no difference when you're in the habit of using %+. (And thanks to AutoHotKey for allowing me to generate it much more easily than the ampersand.)

My apologies for taking this thread even farther afield. I just thought I'd chime in in case Rex is thinking of retiring this excellent feature. Please don't.


-- Dan McMullin
 
May 30, 2008
65
1
#20
On Tue, 27 Apr 2010 23:54:57 -0400, myarmor <> wrote:

Don't you want to require the literal ()s? I don't think you are doing so:

These aren't doing what you want:

You want the literals in there somehow:

v:\> echo %@regexsub[1,(?i)\(([0-9A-F]{8})\), a(12345678)b.txt]
12345678
--
- Vince
If you study my regex you'll notice that there are a character class [\[({] before, and [\])}] after. Those are literals that is tested for.

The one I linked to does what I want..
In other words, require a "[","(", or "{" followed by a 8 char hex number, followed by "]","}", or ")".
The prefix and suffix are only indicators for where the number is, they doesn't have any use beyond that.

Note the filename example:
"This Is a Test [ADDAADDA].dat"

For a comparison I can't use the prefix and suffix (they aren't part of a generated crc32 value, so they would always create a failed match if they were included), so I use the value between them for the comparison.
 

rconn

Administrator
Staff member
May 14, 2008
10,627
97
#22
> I'm scratching my head about what conditions there are when pdir
> decides to print rather than execute the code though.
PDIR will *never* execute the code. If you want to execute it, you have to
specify something like @EXEC or @EXECSTR inside the UDF.

The argument in the UDF is passed to the variable expansion routine and then
returned to PDIR to be printed. It is NOT passed to the command parser for
execution.

Rex Conn
JP Software
 
May 30, 2008
65
1
#23
PDIR will *never* execute the code. If you want to execute it, you have to
specify something like @EXEC or @EXECSTR inside the UDF.

The argument in the UDF is passed to the variable expansion routine and then
returned to PDIR to be printed. It is NOT passed to the command parser for
execution.

Rex Conn
JP Software
Thank you for alt least that..

At least it seems to execute such things as @execstr, @crc32[] and similar, which made it possible to get what I needed (vefatica was so kind as to point very much in the right direction).

You probably should say that %+ is deprecated/obsolete if it is.. When you mentioned it in the earlier post, that was the first time I've heard about it (it doesn't say so in the docs etc).
 
May 30, 2008
65
1
#24
@rconn,you may want to keep %+ though as it changes when the command separator changes.

I think that kludge probably has a life of its own as it is most often used to guarantee that a batchfile will run on matter what the user has defined as commandseparator..
And with no indication that it's obsolete I'd think it is still very much in use.
 
#25
On Wed, 28 Apr 2010 08:10:56 -0400, myarmor <> wrote:

|At least it seems to execute such things as @execstr, @crc32[] and similar

Read what Rex said carefully. PDIR does not execute user COMMANDS. It merely
asks the parser "What is the value of (what should be substituted for)
@FUNCTION. The only FUNCTIONS that will execute user COMMANDS are @EXEC[] and
@EXECSTR[].
--
- Vince
 
May 30, 2008
65
1
#27
But there are other reasons to change the default command separator, e.g. handling arbitrary text which may contain ampersands.
Agreed, and %+ is easier to remember than remembering what is the current command separator at any one time. i.e no matter how much you change the command separator, the %+ follows, & does not.
 
#28
> It's the command separator, the ampersand, "&".

I, too, was surprised by Rexx's comment. I have always used a different
command separator, and while I could change my habits, I just use %+ in
all aliases to guarantee that they will work no matter what the
separator is. Why is that "obsolete"?

-- Jay