• Print

Author Topic: Traverse filesystem in QB64 (using Posix?)  (Read 120 times)

TimV

  • Newbie
  • *
  • Posts: 7
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #15 on: May 07, 2013, 02:19:59 PM »
Well, it looks like we're done because the example also works in Windows. I tested it running the Windows version of QB64[GL] (V0.980) on Wine and compiled the example without changes, without any problems. Running direntry.exe with Wine shows a fine directory listing. No need for Windows API. :-)

DSMan195276

  • Hero Member
  • *****
  • Posts: 1971
  • Yes
    • Email
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #16 on: May 07, 2013, 02:28:33 PM »
Quote from: TimV on May 07, 2013, 02:19:59 PM
Well, it looks like we're done because the example also works in Windows. I tested it running the Windows version of QB64[GL] (V0.980) on Wine and compiled the example without changes, without any problems. Running direntry.exe with Wine shows a fine directory listing. No need for Windows API. :-)

Hmm... Is Windows POSIX compliant? I think that it partially is/was, but 7 and 8 aren't anymore without an extra add-ons. I'm not entirely sure that a Wine version can actually test this since it's technically not running in a Windows environment (Wine doesn't do emulation, it's just a 'layer'). I don't know enough about Wine to know specifics on that. The part that I think won't work is that 'stat()' returns info about a Unix file-system, which includes things on the inodes and such, which Windows simply doesn't have. dirent.h is also not supposed to be supported.

But, I'm way to curious now. I'm going to reboot into Windows 7 and see what happens.

Matt

Edit. Cool stuff, it does work. Looking online, it looks like MinGW provides a compatible dirent.h for us to use. Even better, the dirent works with unix paths as well as Window's paths :D
« Last Edit: May 07, 2013, 02:37:45 PM by DSMan195276 »
"Cast your cares on the Lord and he will sustain you; he will never let the righteous be shaken" -- Psalm 55:22
QB64 Linux Installer

TimV

  • Newbie
  • *
  • Posts: 7
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #17 on: May 07, 2013, 02:37:59 PM »
Doesn't MinGW include partial support for POSIX stuff? You think I may have ended up with a Windows executable that only works on OS X in Wine? :-) I'll copy it over to my Win7 pc to see if it works.

Edit. Ok so the executable works fine on Win7. (unrelated: It does look like the window that gets created is too large and then it resizes to the proper width and height)
« Last Edit: May 07, 2013, 02:45:37 PM by TimV »

DSMan195276

  • Hero Member
  • *****
  • Posts: 1971
  • Yes
    • Email
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #18 on: May 07, 2013, 02:48:06 PM »
Quote from: TimV on May 07, 2013, 02:37:59 PM
Doesn't MinGW include partial support for POSIX stuff? You think I may have ended up with a Windows executable that only works on OS X in Wine? :-) I'll copy it over to my Win7 pc to see if it works.

Yes, see my edit, you're right, which is great news since that means less work ;D I'm putting this code into my FTP program's git repo in its file handling library so I don't forget about it. Thank you for bringing up the idea, this code is going to be very useful.

I have now noticed though, it doesn't seem like DECLARE LIBRARY checks the path where the QB64 code file is in for the header, it just checks the path QB64 is in and then the /usr/lib directories. Perhaps I'm just doing something wrong, but I think it should check where ever the source is located if it's not doing that already.

Matt
"Cast your cares on the Lord and he will sustain you; he will never let the righteous be shaken" -- Psalm 55:22
QB64 Linux Installer

Clippy

  • Hero Member
  • *****
  • Posts: 16423
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #19 on: May 07, 2013, 03:15:26 PM »
Subscript out of range, Line 141 in Windows XP.
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

DSMan195276

  • Hero Member
  • *****
  • Posts: 1971
  • Yes
    • Email
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #20 on: May 07, 2013, 03:16:56 PM »
Quote from: Clippy on May 07, 2013, 03:15:26 PM
Subscript out of range, Line 141 in Windows XP.

Are you talking about my filebrowser that uses SHELL? I wouldn't be amazingly surprised, I've never gotten the chance to test it in WindowsXP. All the more reason to use the solution here instead of SHELL.

Matt
"Cast your cares on the Lord and he will sustain you; he will never let the righteous be shaken" -- Psalm 55:22
QB64 Linux Installer

DSMan195276

  • Hero Member
  • *****
  • Posts: 1971
  • Yes
    • Email
Re: Traverse filesystem in QB64 (using Posix?)
« Reply #21 on: May 09, 2013, 06:37:36 AM »
TimV:

I modified the 'file library' that I have in my ftp client program to use what we posted here. It has some nice features and combines all of this into a pretty easy to use setup that I think you may find handy. It does use my mem_lib.bi/bm but in general I don't think that should be to big of an issue (It's fairly small, I just use it so you can store string's in TYPE's). The code here allows for an easy way to get the list of files in a directory via the code here, as well as get the current directory via another POSIX function, and also can sort the list of files and DIR's with directories first, files second, and both in alphabetical order (It doe sit by a slightly modified quick-sort alg):

file_helpers.bi:
Code: [Select]
CONST FILE_IS_DIR = 1
CONST FILE_IS_FILE = 2

DECLARE CUSTOMTYPE LIBRARY "direntry"
  FUNCTION FILE_load_dir& ALIAS load_dir (s as STRING)
  FUNCTION FILE_has_next_entry& alias has_next_entry()
  SUB FILE_close_dir alias close_dir()
  SUB FILE_get_next_entry alias get_next_entry(s as STRING, flags AS LONG, file_size AS LONG)
END DECLARE

DECLARE LIBRARY "unistd"
  SUB FILE_getcwd alias getcwd(s as STRING, BYVAL l as LONG)
END DECLARE

TYPE FILE_filedir
  nam AS MEM_string
  flags AS _BYTE
  size AS LONG
  lin AS MEM_string
END TYPE

file_helpers.bm:
Code: [Select]
SUB FILE_get_files (di$, fil() as FILE_filedir, count as long)
DIM flags AS LONG, file_size AS LONG
IF FILE_load_dir&(di$) then
  count = 0
  DO
    length = FILE_has_next_entry
    if length > -1 then
      nam$ = space$(length)
      FILE_get_next_entry nam$, flags, file_size
      count = count + 1
      fil(count).flags = flags
      fil(count).size = file_size
      MEM_put_str fil(count).nam, nam$
    end if
  LOOP until length = -1
  FILE_close_dir
end if
END SUB

SUB FILE_sort_dir_listing (f() AS FILE_filedir, file_num)
'quicksort type of thing. First, move all of the DIR's to the top
nex = 0
DO: nex = nex + 1: LOOP UNTIL ((f(nex).flags AND FILE_IS_DIR) = 0) OR nex = file_num 'loop until f(nex) is not a directory
m = nex + 1
IF m < file_num THEN
  FOR x = m TO file_num 'loop through files
    IF f(x).flags AND FILE_IS_DIR THEN 'found a directory
      SWAP f(nex), f(x) 'swap the directory we found with the first entry that's not a directory, so we move the directory to the top
      DO: nex = nex + 1: LOOP UNTIL ((f(nex).flags AND FILE_IS_DIR)= 0) OR nex > file_num 'find the next non-directory
      x = nex + 1
    END IF
  NEXT x
END IF
'nex now equals the very last DIRectory
IF nex > 4 AND nex < file_num - 1 THEN
  FILE_quick_sort_filedir_type f(), 2, nex - 1
END IF
IF nex < file_num - 1 THEN
  FILE_quick_sort_filedir_type f(), nex, file_num
END IF
END SUB

SUB FILE_quick_sort_filedir_type (f() AS FILE_filedir, low, high)
IF low < high THEN
  IF high - low = 1 THEN
    IF LCASE$(MEM_get_str$(f(low).nam)) > LCASE$(MEM_get_str$(f(high).nam)) THEN
      SWAP f(low), f(high)
    END IF
  ELSE
    pivot = INT(RND * (high - low + 1)) + low
    SWAP f(high), f(pivot)
    p$ = LCASE$(MEM_get_str$(f(high).nam))
    DO
      l = low
      h = high
      DO WHILE (l < h) AND (LCASE$(MEM_get_str$(f(l).nam)) <= p$)
        l = l + 1
      LOOP
      DO WHILE (h > l) AND (LCASE$(MEM_get_str$(f(h).nam)) >= p$)
        h = h - 1
      LOOP
      IF l < h THEN
        SWAP f(l), f(h)
      END IF
    LOOP WHILE l < h
    SWAP f(l), f(high)
    FILE_quick_sort_filedir_type f(), low, l - 1
    FILE_quick_sort_filedir_type f(), l + 1, high
  END IF
END IF
END SUB

FUNCTION get_new_dir$ ()
s$ = SPACE$(1024)
FILE_getcwd s$, len(s$)
get_new_dir$ = s$
END FUNCTION

Example code:
Code: [Select]
'$include:'mem_library/mem_lib.bi'
'$include:'file_library/file_helpers.bi'

DIM file_list(200) AS FILE_filedir, count AS LONG

print "CWD:"; get_new_dir$
sleep

FILE_get_files ".", file_list(), count

FILE_sort_dir_listing file_list(), count

FOR x = 0 to count
  print MEM_get_str$(file_list(x).nam); file_list(x).flags
  if x mod 22 = 0 then sleep
next x
end

'$include:'mem_library/mem_lib.bm'
'$include:'file_library/file_helpers.bm'

It of course needs the 'direntry.h' file, but I believe I didn't make any modifications to it at all so the one posted before should work.

Matt
"Cast your cares on the Lord and he will sustain you; he will never let the righteous be shaken" -- Psalm 55:22
QB64 Linux Installer

  • Print