Announcement

Collapse
No announcement yet.

DIR$ behavior vs online help

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DIR$ behavior vs online help

    It's been a long while since I programmed in PBCC, and I decided to just jump into PBCC 5.0. I have not tried this in any prior versions...

    Objective:
    Rename a subdirectory, BUT FIRST check it for the presence of a specific file.

    Code:

    Code:
    x = DIR$("c:\MySub\IS_THE_ONE.txt")
    IF x <> "" THEN
       NAME "c:\MySub" AS "c:\MySub_Other"
    END IF
    The NAME command always fails on Error 70: Permission Denied. If I just run the NAME command without the DIR$ test (and without the IF), the command completes without any error. So DIR$ is somehow locking the subdir...?


    ...OK, so I located the DIR$ CLOSE statement, and if executed before the NAME command, there is no error.

    HOWEVER, this necessary follow-up step is not explained under DIR$ in the Help File. I think it should be mentioned there, and under other affected commands, such as NAME... Also, the DIR$ explanation should mention how other commands can be affected. (Is NAME the only command so affected?)



    Also, I have not been able to get DIR$(Mask$, ONLY %SUBDIR) to work.
    The compiler complains that the %SUBDIR equate is not defined. If I define it myself, it works just fine.

    HOWEVER, from the chart presented in the DIR$ help section, I thought that the DIR$-specific equates are pre-defined to PBCC; nothing indicates the programmer needs to define them (or of any requirement to INCLUDE Win32API.INC?).

    Here, too, I believe such requirements imposed on the programmer should be mentioned explicitly.



    Or am I just so far behind the times that everyone else already knows these things?

    -John

  • #2
    Also...

    Also,

    Although the DIR$ help entry says:

    This definition (DIRDATA) is built into PowerBASIC, and need not necessarily be included in your source code.
    I had to include the TYPE in order to get access to the UDT members.


    Again, is this a problem with the compiler, the Help file, or me?

    -John


    ALSO2:
    Having access to read DIRDATA members via DIR$, I'm wondering if there's a related mechanism to modify and write any of them? For example, to change attributes or LastAccessTime...

    I know there are other commands for attributes, and API calls for file times, but I was just wondering... since we've got them through this mechanism, can we change them through this mechanism??
    Last edited by John Montenigro; 23 Oct 2008, 10:52 AM. Reason: also2

    Comment


    • #3
      DIR$ CLOSE before NAME
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Duh, you already did that. How did I miss that?

        Also, the DIR$ explanation should mention how other commands can be affected. (Is NAME the only command so affected?)
        yes it should and no it's not.

        RMDIR is affected.

        Basically, DIR$ obtains a search handle to a DIRECTORY (aka 'folder'). Any operation which would affect the directory itself is going to be prevented by the open search handle, much as you can't remove (KILL) or rename (NAME) a FILE which is open.

        DIR$ CLOSE closes the search handle, making the directory available for removal or renaming.

        This is all speculation of course. DIR$, NAME and RMDIR are proprietary functions so we don't know how they work under the hood. That said, I would think any proprietary function's documentation should include all limitations and restrictions.

        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Bottom line: "Use DIR$ CLOSE because it can never hurt and sometimes help."

          ????
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Michael, thanks.

            Yes, I did find and learn how to use DIR$ CLOSE, and I understand that it can't hurt to use it. It's just that if you didn't know in advance that it was needed at all, you wouldn't think to use it! (How that for a good use of tautology?)


            I did a scan of my old code, and I see that this is the first time I’ve ever checked for a particular file in a subdirectory before doing a rename. In all other code, I’ve either done the rename without checking for a particular file, or have performed the typical DIR$ action of finding and opening one or more files but never with an interest in renaming the subdirectory.


            I sent a message to support about giving this information more visibility in the DIR$ help page, and I got a response that it's been passed along to the documentation team.



            I am still curious about the problems I had with the DIR$-related equates and the DIRDATA Type. It seems I need to explicitly include them in my code, whereas the DIR$ Help page implies that PB knows them internally.

            Am I mis-reading the Help page?

            -John

            Comment


            • #7
              Code:
              LOCAL DData AS DIRDATA , dr AS STRING   
              
              dr = DIR$("*.*", 0&,TO ddata)
              
              ...
              ...compiles fine here. Too bad the DIRDATA structure members are not documented so there is no way to know if it works, although I suspect the doc will (when included) look a LOT like the doc for the WIN32_FIND_DATA structure in your WinAPI documentation.

              You know that is a strange choice of syntax. Not only do you have a function returning TWO values, but the "TO" being inside the parentheses is totally different from all the other PB syntax which uses "TO." I would have thought it would have been:
              Code:
              dr = DIR$(mask, attribute)  [ TO dirdatavar]
              BTW the syntax diagram is wrong in PB/CC help
              All three of these compile:
              Code:
                   dr = DIR$("*.*", 0&, TO ddata)
                   
                   dr = DIR$("*.*")  ' compiles OK
                   
                   dr = DIR$("*.*", 0&)
              The syntax in help reads....
              file$ = DIR$(mask$ [, [ONLY] attribute&, TO DirDataVar])
              .. which implies when using Attriubute&, "TO DataDirVar" is required.. but it ain't.

              Based on above, it should read
              file$ = DIR$(mask$ [, [ONLY] attribute& [,TO DirDataVar]])

              MCM
              Last edited by Michael Mattias; 26 Oct 2008, 11:56 AM.
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                IsFile?

                Hi John,

                I completely agree on the documentation side, but as you're using PBCC5, why not avoid this issue entirely? Just use:

                Code:
                IF ISTRUE(ISFILE("c:\MySub\IS_THE_ONE.txt")) THEN
                   NAME "c:\MySub" AS "c:\MySub_Other"
                END IF
                Regards,

                Pete.

                Comment


                • #9
                  Huh? The DIRDATA structure is documented in the DIR$ help topic (emphasis added):
                  The DIR$ function may optionally assign the complete directory entry to an appropriate UDT variable if you include the TO clause as a parameter. The complete directory entry contains 318 bytes of data, corresponding to the following TYPE definition. This definition (DIRDATA) is built into PowerBASIC, and need not necessarily be included in your source code.
                  TYPE DirData
                  FileAttributes AS DWORD
                  CreationTime AS QUAD
                  LastAccessTime AS QUAD
                  LastWriteTime AS QUAD
                  FileSizeHigh AS DWORD
                  FileSizeLow AS DWORD
                  Reserved0 AS DWORD
                  Reserved1 AS DWORD
                  FileName AS ASCIIZ * 260
                  ShortName AS ASCIIZ * 14
                  END TYPE
                  You can declare a variable as DIRDATA for this purpose, or use any other user-defined type of at least 318 data bytes. The additional data may be used for any other purpose in your program.
                  Perhaps allowing a 318 bye long UDT might be for some who really are just wanting to transfer the bytes to another file or perhaps a memory block. The actual definition in the help file reflects the WIN32_FIND_DATA structure, so you could assign that as well. The only nit difference is that instead of specifying a FILETIME structure for the files 3 times, it instead specifies a QUAD allocation ... which is in line with what FILETIME really ends up being (see Win32.hlp).

                  In the case of DIR$, there are other nuances that separate this function from others that use a TO keyword. First, it returns a left side value, file$. Second it returns a 318 byte block that contains the information per the DIRDATA documented structure, which is of course equivalent to the API documented WIN32_FIND_DATA structure. Off the top, can you think of another PB BASIC function that (1) has a left side return value and (2) a TO clause that can optionally return a 318 byte UDT structured data block in this manner and which documents it?

                  I do agree DIR$ CLOSE needs tto be flagged in the DIR$ help.

                  It is also apparent that the syntax documentation could use improvement to:
                  file$ = DIR$(mask$ [, [ONLY] attribute& [,TO DirDataVar]])
                  to avoid any confusion.
                  Rick Angell

                  Comment


                  • #10
                    Documented, huh?
                    Code:
                      CreationTime AS QUAD
                      LastAccessTime AS QUAD
                      LastWriteTime AS QUAD
                    And those times are in what unit of measure? CCYYMMHHMMSSTT perhaps?
                    Code:
                       FileAttributes AS DWORD
                    Let me guess, if this equals 65231 it means the file is "really big?"

                    DIRDATA documented structure, which is of course equivalent to the API documented WIN32_FIND_DATA structure
                    So say you.

                    MCM
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      First, look at WIN32_FIND_DATA structure you posted Michael. Keep in mind the help first said "The DIR$ function may optionally assign the complete directory entry to an appropriate UDT variable if you include the TO clause as a parameter. " So that sure sounds like what the set of wrapped FindFirstFile and FindNextFile APIs would do to as well. No real guessing when you compare. The "complete directory entry" is assigned TO the UDT variable of 318 bytes. Perhaps you want the help to reference the API or say "for more information, see the Win32 help" or something along those lines. Send it in. However, it seems a bit inane to suggest dwFileAttributes could be the file size given there are other members referencing size.

                      Emphasis added.
                      typedef struct _WIN32_FIND_DATA { // wfd
                      DWORD dwFileAttributes;
                      FILETIME ftCreationTime;
                      FILETIME ftLastAccessTime;
                      FILETIME ftLastWriteTime;
                      DWORD nFileSizeHigh;
                      DWORD nFileSizeLow;
                      DWORD dwReserved0;
                      DWORD dwReserved1;
                      TCHAR cFileName[ MAX_PATH ];
                      TCHAR cAlternateFileName[ 14 ];
                      } WIN32_FIND_DATA;
                      Emphasis added.
                      The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.

                      typedef struct _FILETIME { // ft
                      DWORD dwLowDateTime;
                      DWORD dwHighDateTime;
                      } FILETIME;
                      ...
                      It is not recommended that you add and subtract values from the FILETIME structure to obtain relative times. Instead, you should
                      · Copy the resulting FILETIME structure to a LARGE_INTEGER structure.
                      · Use normal 64-bit arithmetic on the LARGE_INTEGER value.
                      PB already has the value in an appropriate QUAD.

                      That said, I would agree the text in this area of the help could be improved so less experienced users would not have to immediately look things up in the Win32.hlp to understand how the ""complete directory entry" data is organized.
                      Rick Angell

                      Comment


                      • #12
                        My point is, nowhere in the PB doc does it say a "DIRDATA" is really a WIN32_FIND_DATA.

                        How would Billy (or Billie, for the politically correct who require either a single gender-neutral or equal numbers of gender-specific references) the new user have a clue that those times were really FILETIME structures? Or for that matter what a FILETIME structure is in the first place? Or, to even know to try to look it up in the WIN32 help?

                        Just because you recognized it as a WIN32_FIND_DATA does not mean everyone will.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          Carry it one step further ... what would make it likely that a new user of the expertise level alluded to would even know WIN32_FIND_DATA or a FILETIME ore maybe even a "structure" is. At some point the help has to draw a line, ot we end up with a Petzoldian size tome on each command, not to mention increasing the help file to rather gigantic proportions. Here perhaps a reference to the Win32.help topics might help some, but sometimes some others may need a little intro and help from PB and users. Perhaps just adding comments to the type members could be enough as well.
                          Rick Angell

                          Comment


                          • #14
                            Originally posted by Michael Mattias View Post
                            ...
                            You know that is a strange choice of syntax. Not only do you have a function returning TWO values, but the "TO" being inside the parentheses is totally different from all the other PB syntax which uses "TO." I would have thought it would have been:
                            Code:
                            dr = DIR$(mask, attribute)  [ TO dirdatavar]
                            BTW the syntax diagram is wrong in PB/CC help
                            All three of these compile:
                            Code:
                                 dr = DIR$("*.*", 0&, TO ddata)
                                 
                                 dr = DIR$("*.*")  ' compiles OK
                                 
                                 dr = DIR$("*.*", 0&)
                            The syntax in help reads....

                            .. which implies when using Attriubute&, "TO DataDirVar" is required.. but it ain't.

                            ...
                            MCM
                            Interesting - I had a feeling that I was not reading the syntax correctly, but I hadn't tried the variations. I'll give them each a try, just to get a better feel for them.

                            I just started using PBCC 5.0, and I did find the DIRDATA structure described in the Help, under DIR$. However, I had to actually cut and paste the TYPE definition into my code before it would compile. That's what I meant in my last post about thinking PB was supposed to be aware internally - that's what I got from my reading of the DIR$ Help...

                            So in your tests of the "TO ddata" clause, did you have to explicitly include the DIRDATA structure? If not, how did you get the compiler to recognize your "DIM ddata as DIRDATA" ???

                            -John

                            Comment


                            • #15
                              Originally posted by Peter Jinks View Post
                              Hi John,

                              I completely agree on the documentation side, but as you're using PBCC5, why not avoid this issue entirely? Just use:

                              Code:
                              IF ISTRUE(ISFILE("c:\MySub\IS_THE_ONE.txt")) THEN
                                 NAME "c:\MySub" AS "c:\MySub_Other"
                              END IF
                              Regards,

                              Pete.
                              Ah! A new instruction I didn't know about! Yes, that would handle the situation nicely. Thanks for the eye-opener!
                              -John

                              Comment


                              • #16
                                As for the UDT, I did a few successful experiments:

                                Code:
                                      DIM FileInfo AS DIRDATA    
                                      dim lTemp as dword, sTemp as ASCIIZ * 260
                                      lTemp = FileInfo.FileAttributes
                                      sTemp = FileInfo.FileName
                                      STDOUT "FileAttribs: " & STR$(lTemp)
                                      STDOUT "FileName: " & sTemp
                                      waitkey$
                                I'm not familiar with WIN32_FIND_DATA and so did not recognize any equivalents. I just used what was in the Help file under DIR$.

                                The problem I had was that the first line failed to compile until I cut and pasted the DIRDATA type from the Help into my code. I thought (from reading the Help file) that the compiler knew it internally.

                                This definition (DIRDATA) is built into PowerBASIC, and need not necessarily be included in your source code.
                                If that is indeed the case, then I am missing something.

                                ALSO, that's the same understanding I got about the Equates in the chart, but I had to also explicitly put them into my code:

                                Code:
                                'DIR$ equates
                                %NORMAL = 0
                                %HIDDEN = 2
                                %SYSTEM = 4
                                %VLABEL = 8
                                %SUBDIR = 16
                                The compiler did not succeed until I had copied them into my code.

                                My concern is whether I am reading the Help incorrectly and making bad assumptions, or if the Help is inaccurate, or if the compiler is not behaving properly. It's been my experience that most of my difficulties arise from my own ignorance; the compilers are rarely the problem.

                                I just need confirmation that the compilers DO know the equates and the DIRDATA structure, and that there's something I'm not doing right that I can fix.

                                Thanks,
                                -John
                                Last edited by John Montenigro; 27 Oct 2008, 07:07 AM. Reason: fixed CODE tags

                                Comment


                                • #17
                                  I'm not familiar with WIN32_FIND_DATA and so did not recognize any equivalents. I just used what was in the Help file under DIR$ [italics mine]
                                  The prosecution rests, your honor.
                                  Michael Mattias
                                  Tal Systems (retired)
                                  Port Washington WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    I wasn't trying to make anyone's case.

                                    Someone asked to see my code, so I was showing what I did, and that I was actually able to display such things as the FileInfo.FileName, based on what was in the Help, PROVIDED THAT I EXPLICITLY COPIED the DIRDATA type definition into my code (although I didn't think I had to, based on the Help)...

                                    Please remember that my days as a professional programmer pretty much ended with PBDOS, and that since, I've been programming just as a hobbyist.

                                    There are many things I've never mastered, and I'm willing to learn. I'm asking, not arguing.

                                    -John

                                    Comment


                                    • #19
                                      Folks--

                                      The DIRDATA structure is built into PowerBASIC. There is never, ever a need to include its definition a second time. There is never, ever a need to reference another structure such as WIN32_FIND_DATA. The PowerBASIC Help File states that DIRDATA is included in the compiler because it is included in the compiler. Please... Let's stop misleading the thousands of people who read these forum messages?

                                      The five (5) equates listed under DIR$() are not included in the compiler. That's why the PowerBASIC Help file does not tell you they are included. Equates which are not present in the Help file equate list are not included in the compiler. However, the equated value for each of the equates is included in the help file, so it's easy enough to add it yourself, or include another file which defines them. Please... Let's stop misleading the thousands of people who read these forum messages?

                                      Thank you.

                                      Bob Zale
                                      PowerBASIC Inc.

                                      Comment


                                      • #20
                                        Some examples

                                        Bob's post which just came up as I was ready to post this indicates the official PB position about WIN32_FIND_DATA being mentioned in the DIR$ help topic. At the end of the day this is really not about proving points. but helping each other get the job done. Here the point is that this help file topic could use some improvement regarding when DIR$ CLOSE would be needed in certain DIR$ use situations; and perhaps that the 5 equates are not in the built-in compiler equates. Also it would be nice for folks to know how to how to avail themselves of them using PB's standard include files.

                                        The DIRDATA definition is built in, and here is an example that uses it. Maybe you tried it while using the equates versus just the numeric quantity, so of course it did not compile. See the commented line for alternate syntax without a specified attribute value, using the built in default, but sill returning the variable of the DIRDATA type. MyFile. These examples have all compiled and been tested with PBCC5. (note revision to mask as "*.*", since you might not have a .txt file in your directory.)
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        
                                        FUNCTION PBMAIN () AS LONG
                                        
                                            LOCAL MyFile AS DIRDATA
                                            LOCAL fn AS STRING
                                            'fn = DIR$("*.*",TO MyFile)  'using default attribute so only TO option used
                                            fn = DIR$("*.*",0,TO MyFile)
                                            ? fn
                                            ? MyFile.ShortName
                                            WAITKEY$
                                        
                                        END FUNCTION
                                        The standard operating system code equates (for attributes which can be used by DIR$) are not in the compilers included equates. The help does not say they are. only the structure is, if you read it carefully. This is logically why the text and its example indicate to use the numeric value (sum) of the equate(s). The equates are present in the PB furnished standard Win32API include file. So, in order to use them you would need to include the file where they are located.
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        %USEMACROS = 1            'keep included size to a minimum
                                        #INCLUDE "WIN32API.INC"  'includes equates not in the compiler
                                        
                                        FUNCTION PBMAIN () AS LONG
                                        
                                            LOCAL MyFile AS DIRDATA
                                            LOCAL fn AS STRING
                                            fn = DIR$("*.*",%NORMAL,TO MyFile)
                                            ? fn
                                            ? MyFile.ShortName
                                            WAITKEY$
                                        
                                        END FUNCTION
                                        However if you are only using the attributes for DIR$, as opposed to other included information in the Win32API.inc, simply use the direct numeric quantity to keep the program size small. When you do include the equates and you need several combined then they would be ORed: e.g. %HIDDEN OR %SYSTEM
                                        Last edited by Richard Angell; 27 Oct 2008, 06:10 PM. Reason: added emphasis and small textual changes
                                        Rick Angell

                                        Comment

                                        Working...
                                        X