Commodore
Commodore
1779 views

Confirm native vs managed CBL_DIR_SCAN_READ behavior?

Jump to solution
In native COBOL since at least Net Express 3.0 through VC 2.3.2, the first two calls to CBL_DIR_SCAN_READ after a call to CBL_DIR_SCAN_START will return file names "." and ".." respectively. In VC 2.3.2 managed COBOL these two "file names" don't seem to get returned. Am I seeing the correct (and permanent) managed COBOL behavior? Don't get me wrong, this isn't a complaint or issue. I just want confirmation because if true then I can remove the IF test for these from my code.
0 Likes
1 Solution

Accepted Solutions
Micro Focus Expert
Micro Focus Expert

The length field in CBL_DIR_SCAN_START is definitely supposed to reflect the actual size of the search string text itself and not the max length of the field. You can set this to any value up to the actual length of the field but that assumes that the pattern string is that size.

What you are getting back from the READ call would be categorized as "undefined" behavior and there would be no guarantee that it would continue to return these same values in the future.

I would recommend just setting the length to 0 and null terminating the string used.

In managed code you could do this with one line like:

       01 my-field              pic x(256)  value "c:\temp\*".

          set pattern-text to my-field::TrimEnd & X"00"

View solution in original post

0 Likes
10 Replies
Micro Focus Expert
Micro Focus Expert

This may be OS dependent. I just tested here under Windows 7 using a managed console program compiled in 2.3.2 and I get the . and .. directories returned. Because it is managed code I also get the directory name returned along with it, i.e C:\TEMP\. and C:\TEMP\..

Under which OS are you testing?

0 Likes
Commodore
Commodore

Sorry.  Windows 7 SP 1, VCVS 2013 2.3.2, COBOL Managed Procedural Multi-Output Project, console application, .NET 4.5.

The pattern-content for the CBL_DIR_SCAN_START call contains the path to the desired folder plus "\*"; ex., "C:\test\*".  I'm starting several directory scans (consecutive, not "nested"), some for files (search-attribute set to 1) and some for folders (search-attribute set to 2).  The flags parameter is always set to 2 (turns on use of wildcards).

In native COBOL I get "." and ".." returned only when scanning for folders.

0 Likes
Micro Focus Expert
Micro Focus Expert

My program does the same thing. I use "c:\temp\*" as my search string.

If I set the flags to 1 I get only the filenames.

If I set flags to 2 or 3 then the following will be returned:

native code:
.

..

managed code

c:\temp\.

c:\temp\..

The program I am using is:

       id division.
       program-id. plainscan.
       working-storage section.
       01 any-key pic x.
       01 f-entry.         
          03 f-attribute        pic x(4) comp-5.
          03 f-date-stamp.  
             05 f-year          pic x(4) comp-5.
             05 f-month         pic x(2) comp-5.
             05 f-day           pic x(2) comp-5.
             05 f-hour          pic x(2) comp-5.
             05 f-minute        pic x(2) comp-5.
             05 f-second        pic x(2) comp-5.
             05 f-millisec      pic x(2) comp-5.
             05 f-dst           pic x    comp-5.
             05 f-size          pic x(8) comp-5.
             05 f-name.     
                07 f-max-len    pic x(2) comp-5 value 256.
                07 f-entry-name pic x(256).
       
       01 scan-pattern.
           05 pattern-len       pic x(2) comp-5  value 0.
           05 pattern-text      pic x(256)       value spaces.
       01 scan-attrib           pic x(4) comp-5  value 1.      
       01 scan-flags            pic x(4) comp-5  value 2.
       01 scan-status           pic x(2) comp-5  value 0.
       01 scan-handle           pointer.
       procedure division.
           
           move z"c:\temp\*" to pattern-text
           move 0 to pattern-len
           move 3 to scan-attrib
           move 2 to scan-flags
           
           call "CBL_DIR_SCAN_START" 
              using by reference scan-handle,
                    by reference scan-pattern,
                    by value scan-attrib,
                    by value scan-flags,
              returning scan-status
           end-call
           
           perform until exit           
              move spaces to f-entry-name
              call "CBL_DIR_SCAN_READ"
                 using  by reference scan-handle
                                     f-entry
                 returning scan-status
              end-call
              if scan-status = 0
                 display f-entry-name(1:30) 
              else
                 call "CBL_DIR_SCAN_END" using scan-handle
                 exit perform
              end-if
           end-perform.
           accept any-key
           goback.
0 Likes
Commodore
Commodore

Thank you, I've found the difference.  We set pattern-length to the length (in bytes) of pattern-text and we don't null-terminate the character string in pattern-text prior to calling _START.

I modified my program to zero pattern-length and null-terminate the string of characters in pattern-text before calling  _START and I now get "." and "..", with full path, in f-entry-name for the first two _READs.

We like "our way" better for the following reasons:

1. The length of pattern string placed in pattern-text varies.  "You're way" would require us add code to locate the end of the character string in pattern-text and append a null byte prior to calling _START.

2. We don't want "." and "..".  "You're way" would require us to add code to loop back to the _READ immediately after the first to executions.

So the question is: Can we rely on Micro Focus to retain this behavior for "our way" in future releases?  Or is this disparity in behavior between null-terminated pattern strings and space-padded pattern strings going to be considered a bug and be standardized?

Again, we like it the way it is.  We just need to know if it will stay this way?

0 Likes
Micro Focus Expert
Micro Focus Expert

I am still seeing the identical behavior whether I null terminate the string or set the length explicitly. Are you sure you are setting the length correctly?

If I change my sample program to use:

          move "c:\temp\*" to pattern-text

          move 9 to pattern-len

          move 2 to scan-attrib

          move 2 to scan-flags

I still get the "C:\temp\." and "C:\temp\.." directories as the first ones returned.

Can you try my test program and see if you get the same behavior?

0 Likes
Commodore
Commodore

Try setting pattern-len to 256.

I see where the documentation says "Length of pattern string in the pattern-content field."  But it also says "You can set pattern-length to less than the length of the pattern-content field, but not to more."  In other Micro Focus library calls these length parameters specify the length of the associated buffer, not the length of the string in the buffer.  Since our string lengths vary, we defaulted to always using the buffer length rather than finding the end of the string.  And it has worked for our purposes since NE 3.0.  Of course in native COBOL we got just "." and ".." as the file names, no path.  So we would IF f-entry-name (1:2) = ". " OR ".." EXIT to skip these two returns from _READ.

0 Likes
Micro Focus Expert
Micro Focus Expert

The length field in CBL_DIR_SCAN_START is definitely supposed to reflect the actual size of the search string text itself and not the max length of the field. You can set this to any value up to the actual length of the field but that assumes that the pattern string is that size.

What you are getting back from the READ call would be categorized as "undefined" behavior and there would be no guarantee that it would continue to return these same values in the future.

I would recommend just setting the length to 0 and null terminating the string used.

In managed code you could do this with one line like:

       01 my-field              pic x(256)  value "c:\temp\*".

          set pattern-text to my-field::TrimEnd & X"00"

View solution in original post

0 Likes
Commodore
Commodore

I understand.  I've made the appropriate changes to my program and it is functioning as expected and required.  A couple of observations:

1. I used "STRING ... x"00" INTO pattern-text" vice your "SET ..." as this will work on native and managed platforms with no code changes.

2. I identify "." and ".." returned by _READ when scanning for folders by counting the iteration of _READ, the first two returns will be "." and ".." respectively?

3. A suggestion for an enhancement to the _READ behavior that would probably help users of this call on the native platform (those that don't have access to "my-field::TrimEnd"): Could the length of the string returned in f-entry-name be returned in f-max-len?  I realize that it would mean f-max-len would have to be set to the length of f-entry-name prior to every call to _READ, but it would make any program that has to know the location of the end of the returned string within f-entry-name cross-platform with no differences in code.

As always, thank you so much for your assistance.

0 Likes
Micro Focus Expert
Micro Focus Expert

The only way that I see your enhancement request working would be if we added a new flag bit that had to be turned on in order to cause this behavior. Otherwise we would be breaking current applications that expect the functionality as it currently exists.

If you wanted a compatible method of finding the length of the returned string you could use the following:

     inspect f-entry-name tallying char-count for trailing " "

     compute char-count = length of f-entry-name - char-count

or

     perform varying char-count from length of f-entry-name by -1 until char-count < 1

           if f-entry-name(char-count:1) not = " "

               exit perform

           end-if

      end-perform

0 Likes
Commodore
Commodore

I figured the enhancement might be clumsy at this point and a long shot.

I had already thought of the "PERFORM VARYING ... BY -1" for finding the end of a string in a buffer (we've used it in a number of other places), but I never thought of using "INSPECT TALLYING FOR TRAILING"!

I like it.  Thank you!

Any guess as to which method is more efficient?

0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.