1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Just an out-of-curiosity question re. "Do ... /P ..."

Discussion in 'Support' started by mathewsdw, Apr 20, 2012.

  1. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Here's the deal. This:
    Code:
    Do StartTime In /P Timer On /2()
    :: Something that takes some time...
    Do EndTime In /P Timer Off /2()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    
    works as I would hope, producing, for instance:
    Code:
    Start Time: 12:08:22
      End Time: 12:08:24  Elapsed Time: 0:00:02.06
    
    This:
    Code:
    Do StartTime In /P Timer On /2 ()
    :: Something that takes some time...
    Do EndTime In /P Timer Off /2 ()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    
    does not, producing only:
    Code:
    Start Time:
      End Time:    Elapsed Time:
    
    As you can see, no actual time(s) are output.

    The only differences between the two are the spaces between "/2" and the open parenthesis.
     
  2. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,178
    Likes Received:
    11
    That's an odd way to accomplish getting timing information.
    Code:
    set StartTime=%@execstr[timer /2 on]
    :: blah blah blah
    set Elapsed=%@timer[2]
    
    I assume your example is a simplified version of what you want to accomplish. Otherwise, I'd stick with the %_TIME variable and the %@TIMER[] function to get the start, stop, and elapsed time values.
     
  3. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Scott, "@ExecStr" does not work for the timer functions. This is simply because "Timer" commands run in "@ExecStr" run in a sub-shell and not in the "current" shell, i.e., the "Timer Off" turns a timer off that wasn't even on, and therefore elapsed time is always zero. Try it yourself with the following code segment:
    Code:
    Set StartTime=%@ExecStr[Timer On /2]
    Set I=
    Do While %I LT 10000
      Set /A I+=1
    EndDo
    Set EndTime=%@ExecStr[Timer Off /2]
    @Echo Start Time: %StartTime
    @Echo  End Time: %EndTime
    
    The displayed elapsed time is (always!) zero.

    Whereas:
    Code:
    Do StartTime In /P Timer On /2()
    Set I=
    Do While %I LT 10000
      Set /A I+=1
    EndDo
    Do EndTime In /P Timer Off /2()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    
    works, and produces (in one "sample" run):
    Code:
    Start Time: 18:50:50
      End Time: 18:50:57  Elapsed Time: 0:00:07.68
    
    And yes, the "@Time" and "@Timer" functions could also be used, but I find the "DO ... /P ... " technique to be more straightforward for my purposes. (Although the requirement that no space be used between the timer command(s) and the parenthesis enclosing the (null) expression is the oddity that I originally asked about.)
     
  4. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    Code:
    Do StartTime In /P Timer On /2 ()
    :: Something that takes some time...
    Do EndTime In /P Timer Off /2()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    
    Are you expecting StartTime and EndTime to remain set after their respective DOs are executed? I wouldn't expect that. As Scott said, that's an awkward way to (try to) capture the times. You could do it by making it even more awkward.

    Code:
    v:\> do line in /p timer on ( set StartTime=%@word[3,%line] )
    v:\> echo %StartTime
    20:03:14
     
  5. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Vince, I don't really understand your question because my solution works, and I have been using it for a very long time but with the oddity related to the space before the opening parenthesis that I originally asked about. But it was a purely "just out of curiosity" question because it's not really a problem. (And I don't find it to be even slightly difficult to code/understand, either.)
     
  6. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    Or:

    Code:
    v:\> set StartTime=%@word[3,%@execstr[timer /2 on]]
    v:\> echo %StartTime
    20:08:05
     
  7. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Vince, you are somehow missing the point. Your solution does not work with respect to the "Timer Off" command; the elapsed time is always zero. (Again, try it yourself it you don't believe me; I've previously included the exact code that both works and doesn't work.)
     
  8. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,178
    Likes Received:
    11
    I am not able to replicate your issue. I thought perhaps there was an issue with the order of the /2 and the ON/OFF.
    Code:
    do TimerStart in /p Timer /2 on (echo %TimerStart)
    Timer 2 on: 20:01:47
     
    do TimerEnd in /p Timer /2 off (echo %TimerEnd)
    Timer 2 off: 20:02:06  Elapsed: 0:00:19.57
     
    do TimerStart in /p Timer on /2 (echo %TimerStart)
    Timer 2 on: 20:02:44
     
    do TimerEnd in /p Timer off /2 (echo %TimerEnd)
    Timer 2 off: 20:02:47  Elapsed: 0:00:03.00
     
    do TimerStart in /p Timer on /2(echo %TimerStart)
    Usage : TIMER [/1 /2 /3 /Q /S] [ON | OFF]
     
    do TimerEnd in /p Timer off /2(echo %TimerEnd)
    Usage : TIMER [/1 /2 /3 /Q /S] [ON | OFF]
    
    So, without a space, I get a syntax error.

    And while I don't see the same issue you are seeing with @execstr, I definitely see an issue. The timer off call is not actually shutting off the timer.
    Code:
    timer /2
    Timer 2 on: 20:27:39
     
    set TimerEnd=%@execstr[timer /2 off]
     
    echo %timerend
    Timer 2 off: 20:27:42  Elapsed: 0:00:03.44
     
    set TimerEnd=%@execstr[timer /2 off]
     
    echo %timerend
    Timer 2 off: 20:27:52  Elapsed: 0:00:13.19
     
    timer /2 off
    Timer 2 off: 20:28:13  Elapsed: 0:00:33.61
     
    set TimerEnd=%@execstr[timer /2 off]
     
    echo %timerend
    Timer 2 off: 20:29:17  Elapsed: 0:00:00.00
    
     
  9. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    Oops! I suppose the TIMER command inside @execstr is happening in another TCC instance (and so the timer isn't actually running in the current instance).
     
  10. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Scott, I really don't understand why you are getting different results than I am. (I am using TCC 13.04.52 under Windows 7 [Version 6.1.7601]). But now that I think of it you really aren't because you have code in the parenthesized expression but for whatever strange reason(s) I somewhat prefer it the way I coded it. But it really doesn't matter since it was a just-out-of-curiosity question as my code has been working for a very long time. In fact, it's what you might call "boilerplate" code. Let's not waste any more time on it...

    And Vince, that was exactly my point.
     
  11. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,730
    Likes Received:
    80
    Your syntax is wrong (in multiple ways). The /2 has to come before the "ON" in the TIMER command, and without a space after the /2 you're passing "ON /2()" to the TIMER command, so there's no (explicit or implcit) ENDDO.
     
  12. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Rex,

    I'm really confused. From my original posting:
    Code:
    Do StartTime In /P Timer On /2()
    :: Something that takes some time...
    Do EndTime In /P Timer Off /2()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    
    The above came directly from a listing I produced using the "File/Save to File" menu option.

    But it gets worse. Now:
    Code:
    [Z:\]Do StartTime In /P Timer /2 On ()
    [Z:\]Echo %StartTime
    ECHO is OFF
    
    Now it doesn't work at all (not even using your syntax!).

    But I certainly won't argue about the syntax issue (for one thing, nothing I had works any longer! 4 different .btm files), both because I trust that you are correct about the syntax but even more because that's almost irrelevant, anyway. And here's the complete transcript of a TCC session (with only the full results of the "Dir" command and entirely blank lines excised):
    Code:
      Tue  Apr 24, 2012  6:28:59p
     
    ISO8601 plugin v1.2.3 loaded.
    SafeChars plugin v1.6.4 loaded.
     
    TCC  13.04.61  Windows 7 [Version 6.1.7601]
    Copyright 2012 JP Software Inc.  All Rights Reserved
    Registered to Daniel Mathews
     
    [Z:\]Do StartTime In /P Timer /2 ON ()
    [Z:\]Echo %StartTime
    ECHO is OFF
    [Z:\]Do StartTime In /P *Dir /K /M ()
    [Z:\]Echo %StartTime
    ECHO is OFF
    [Z:\]Dir
    Volume in drive Z is RAMDisk        Serial number is 4cce:7e9a
    Directory of  Z:\*
    2/22/2012  21:19        <DIR>    7Z'S
    3/23/2012  23:25        <DIR>    ABC-TopLevel
    3/23/2012  23:06        <DIR>    Attributes
    ...
    4/22/2012  12:44        <DIR>    Work Area.V2012-04-22
    3/18/2012  0:56        <DIR>    WorkSheets
    1/23/2012  0:51        <DIR>    Zip-7z-Comparison
    3/09/2012  15:29        <DIR>    Zip7zComparisons
    3/14/2012  0:58        <DIR>    Zips
    4/20/2012  17:31        879,226  Complete Song List.txt
    4/23/2012  14:21            574  Crud.btm
    4/23/2012  14:21            144  Crud.txt
    4/20/2012  18:50            973  Extract Timer Values.btm
    ...
    4/20/2012  11:43          1,661  URL's.V2012-04-20.txt
    2/18/2012  8:41            357  Z-Drive .xls Files.V2012-02-16Q.txt
            15,308,973 bytes in 30 files and 80 dirs    15,380,480 bytes allocated
          210,083,840 bytes free
    [Z:\]Do StartTime In /P Echo Something ()
    [Z:\]Echo %StartTime
    ECHO is OFF
    
    It is quite possible that I am doing something wrong, of course, but the "Do ... /P" is now not working for me at all.

    As always, TCC 13.04.61 Windows 7 [Version 6.1.7601].

    - Dan
     
  13. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    Code:
    [Z:\]Do StartTime In /P Timer /2 On ()
    [Z:\]Echo %StartTime
    ECHO is OFF
    The StartTime variable is temporary, existing only during the DO command. It happens in other forms of the DO command:

    Code:
    v:\> do x in /l a b c ()
    
    v:\> echo %x
    ECHO is OFF
    
    v:\> do x in /c abc ()
    
    v:\> echo %x
    ECHO is OFF
    Either use the DO variable variable while it exists ...

    Code:
    v:\> Do x In /P Timer /2 ON (set StartTime=%x)
    
    v:\> echo %StartTime
    Timer 2 on: 20:10:59
    ... or leave the DO command prematurely so it doesn't have a chance to clean up:

    Code:
    v:\> Do StartTime In /P Timer /2 ON ( leave )
    
    v:\> echo %StartTime
    Timer 2 on: 20:12:20
     
  14. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,730
    Likes Received:
    80
    DO variables are NOT environment variables, and do not exist outside of the DO loop. (The same is true of FOR variables.)
     
  15. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    Doesn't that need some qualification? It appears that in fact the DO variables **are** environment variables and that they stay in the environment in many cases ... always for "DO var=start to end" ... and for other forms of DO if you LEAVE prematurely.

    Code:
    v:\> do i=1 to 3 (echo %i)
    1
    2
    3
    
    v:\> echo %i
    4
    
    v:\> do x in /l a b c (leave)
    
    v:\> echo %x
    a
    
    v:\> do z in /c abc (leave)
    
    v:\> echo %z
    a
     
  16. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Guys, I think I'm just going to let this issue die because it ain't working now despite the fact it at least used to work in the context in which I was doing it. (The output that I showed in the start of this thread was real!, and I have been doing this for at least 6 months based on the modification dates of .btm files that, again used to work because they don't work no more.) But thank you for your input.

    To save me some time (because I'm pathetically slow), is there some (easy) way to convert the results of @Timer to a more human-readable hours:minutes:seconds.fraction format? I'm kind of guessing there probably is one, but I haven't found it looking in the help file as of this minute.
     
  17. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Update: I'm can't quite yet just leave this alone because I am unable at the present moment to get "Dir ... /P" to work in any circumstances. Examples:
    Code:
      Tue  Apr 24, 2012  10:58:40p
     
    ISO8601 plugin v1.2.3 loaded.
    SafeChars plugin v1.6.4 loaded.
     
    TCC  13.04.61  Windows 7 [Version 6.1.7601]
    Copyright 2012 JP Software Inc.  All Rights Reserved
    Registered to Daniel Mathews
    [Z:\]Do Var In /P *Dir /K /M
    Usage : DIR [/: /124 /A[[:][-][+]rhsdaecjot] /BCDEFGH /I"text" /JKLM /N[defhjlsv] /O[[:][-]adeginorsu] /PQR /Sn /T[:acw[u]] /U[12] /VWXZ] [file...]
    [Z:\]Do Var In /P (*Dir /K /M)
    Usage : DO [n | FOREVER]
    [Z:\]Do Var In /P Echo Somthing
    Usage : ECHO [ON | OFF | message]
    [Z:\]Do Var In /P (Echo Somthing)
    Usage : DO [n | FOREVER]
    [Z:\]
    
    As you can readily see, absolutely none of the above worked.

    I'll be the first to admit that I'm evidently too stupid to understand what is going on here/what I am doing wrong...
     
  18. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    I don't think so but the question makes me imagine a plugin variable function, say @TCONVERT[spec[,t|s|m|h]] which might work like this:
    If spec contains a colon (:) it is interpreted as (some subset of) hh:mm:ss.ttt and is converted to a decimal number of seconds (or optionally thousandths, minutes, hours). If spec does not contain a colon it's interpreted as a decimal number of seconds (optionally thousandths, minutes, hours) and is converted to the hh:mm:ss.ttt format. That's not at all well thought-out; comments are welcome.
     
  19. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Nevermind re the above! I've finally figured it out. (Again, I'm pathetically slow.) Sorry...
     
  20. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    DO needs a command group (...) to execute (even an empty one as in your original post) for each line of output.

    Code:
    do var in /p *dir /l /m ([command])
    It does seem wrong that your first example above gives the DIR syntax message. It would seem that the DO command is malformed, not the DIR command.
     
  21. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    And this is the final one! Really!!! :) I (stupidly!) hadn't tried @Timer with no "precision" argument!
     
  22. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    I don't see this in the Help. In fact, the Help says, "The TIMER command accepts its parameters in any order".
     
  23. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    You know, Rex, since Dave re-awoke the whole issue, I decided to revisit it. So therefore (and I had put this in a previous post in this thread) here is the full and complete code from a routine I simply called "Timer Sample That Worked.btm":
    Code:
    @Echo Off
    SetLocal
    Do StartTime In /P Timer On /2()
    Set I=
    Do While %I LT 10000
      Set /A I+=1
    EndDo
    Do EndTime In /P Timer Off /2()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    EndLocal
    Quit 0
    
    The above is the complete contents of the batch file, unmodified in any way.

    Here are the results of running the above batch file:
    Code:
    [Z:\]"Timer Sample That Worked"
    Start Time: 23:22:31
    End Time: 23:22:35  Elapsed Time: 0:00:03.86
    
    Again complete and unmodified in any way.

    I really don't think it's necessary to say that it worked fine, but it obviously did without any reservations whatsoever. (And if I double the loop count, the elapsed time approximately doubles, as expected.)

    However, if the batch file looks like this:
    Code:
    @Echo Off
    SetLocal
    Do StartTime In /P Timer On /2 ()
    Set I=
    Do While %I LT 10000
      Set /A I+=1
    EndDo
    Do EndTime In /P Timer Off /2 ()
    @Echo Start Time: %@Word[3,%StartTime]
    @Echo  End Time: %@Word[3,%EndTime]  Elapsed Time: %@Word[5,%EndTime]
    EndLocal
    Quit 0
    
    Here's the output, again unmodified in any way:
    Code:
    [Z:\]"Timer Sample That Worked"
    Start Time:
    End Time:  Elapsed Time:
    
    This clearly doesn't work at all, and the only difference between this and the first version (above, of course) are the spaces between the "/2"'s and the open parenthesis.

    Bottom line: Since complete code above is shown above in full without any modification(s) of any kind whatsoever, I challenge you to copy it out of the above and put it in a batch file that you then run yourself so that you can prove to yourself that what I say is completely true in full without any modifications or exceptions of any kind whatsoever.

    As always, TCC 13.04.61 Windows 7 [Version 6.1.7601]

    - Dan

    P. S. And yes, I'm a little irritated (at myself, mostly) that you managed to convince me that what was, in fact, provably true was not true. (And, as I said, I had five .btm files that used that technique without any issue(s) whatsoever other than the slight syntax weirdness I asked about as an "just out of curiosity" question in my original question that started this thread.)
     
  24. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    I suspect this is what's happening. Because of the lack of the space, TCC is seeing the () as part of the TIMER command. TCC does not find a () (command to execute for each line) so it presumes it's a multi-line DO construct. Since it never finds a matching ENDDO, the variable StartTime remains set (and, later, for the same reason EndTime). The correct behavior is for StartTime to disappear when the DO command is finished.

    You can test this in several ways. For example if you replace the first DO line with

    Code:
    Do StartTime In /P echo foo^r^nbar()[/CODE
     
    TCC doesn't see a parenthesized (command)  and thinks it's in a multi-line DO loop.  Later, all you seeis
     
    [CODE]StartTime=foo
    It didn't reach a corresponding ENDDO and never looped for the second line of "echo foo^r^nbar()",

    To see it another way, replace the same statement with

    Code:
    Do StartTime In /P Timer On /2() ()
    Now TCC knows it's in a one-line DO and later, StartTime is not set (which is the correct behavior).
     
  25. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    If you're not convinced, replace the same line with
    Code:
    Do StartTime In /P echo foo()
    Later you'll see

    Code:
    StartTime=foo()
    The bottom line is that your syntax is wrong and (serendipitously) something you like happens. In many other instances that faulty syntax would cause disasters. And the correct syntax will not have (is not meant to have) the result you desire.
     
  26. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Vince, you may certainly be right but it doesn't matter to me in the slightest. The above code does what I want it to do, and I'll just summarize by saying that it has been extensively tested as of this moment (I wrote a batch file that I ran overnight last night in which said code was executed 100 times over a total of 8 hours and 15 minutes for times ranging from roughly .01 second to 12.5 minutes and everything makes sense, including the total time (gotten by comparing the sum of the individual times for each test to the total time that the batch file as a whole took) it took to execute those 100 tests. And, has been much discussed previously, "@ExecStr" just doesn't do the job and, for my purposes and everyone is welcome to disagree with me, I prefer this approach over using the @Time function and the %_Time internal variable. The real point of the posting was that what I had done worked (and had been working for a long time as in a couple of months) so I was completely happy with it regardless of the "technical" merits it may or may not have; and I was somewhat irritated with myself for allowing myself to be convinced otherwise. (And, again, the only question had to do with why it didn't work if the space was included.)

    - Dan
     
  27. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    It didn't work WITH the space because it was working correctly. The DO variable is not supposed to be set after the do command completes. Use your syntax if it suits you. But don't complain it it fails in other circumstances; it's wrong.

    I suggested two other ways

    Code:
    DO x in /P Timer /2 on (set StartTime=%x)
    That's probably more kosher than

    Code:
    DO StartTime in /P Timer /2 on (leave)
    which also works. But it's not clear whether Rex intends that the DO variable remain after LEAVE so it's quite possible that way could disappear in the future.
     
  28. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Quick update: It turns out that neither the open (and therefore the close) parenthesis is required. And it really comes down to that just "Do ... /P" is (without any parenthesis at all) equivalent to running the specified command in the current shell and not in a "subshell" as does "@ExecStr". For example, "Do Var In /P Echo This works!" sets the variable "Var" to "This works!". Evidently undocumented but absolutely reliable as of this version of TCC behavior. (And I see no reason why Rex would "break" it in a future release other than to "break" some of my code...) (Although your suggestion is certainly viable if and when that happens...)
     
  29. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,788
    Likes Received:
    29
    It's not undocumented. Without the () or an ENDDO somewhere, the entire remainder of the batch file is inside that DO loop (very bad programming and I'm sure not what you meant (even though it does something you like)).
    ...

    DO var in /p command
    now I'm in a DO loop
    still in a DO loop
    in a DO loop until a matching ENDDO!!!!!
     
  30. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    No argument, Vince; it's just that I thought that the open parenthesis was required and, in testing, that certainly appears to be the case because if there is no open parenthesis nothing in the supposed "loop" gets executed as part of a "loop". I would have to guess that that means that a "Do" formed in this way is not actually the start of a "loop"; it truly stands on its own with no later "side-effects" of any kind I would postulate. (In fact, if the open parenthesis that should be at the top of the loop is omitted the contents of what would have been the loop gets executed exactly once and a close parenthesis at what should have been at the bottom of the loop produces TCC: xxxx[nn] Unknown command ")". And, in my opinion, arguing about this is just a matter of style. (I will note here that one "aspect" of my reputation in this field when I was still actually working in it was doing things in the absolutely simplest, most direct, way; in fact, one of my credos when teaching this stuff was "KISS" - "Keep It Simple Stupid". I even had a poster I had gotten from someplace that stated just this posted on the wall in the classroom. And I also often noted that there was an generally an inverse relationship between the skill of a programmer and the complexity of the code that he produced. And to put it simply, simple code is generally better in all respects than is complex code) - Dan
     

Share This Page