{%%%%%%%%%
#
            demo program for directory listing

p5c translation of a simple directory lister taken from the gnu libc manual
https://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html
}

program dirDemo(output);

type
   dirPtr      = ^dir;
   dir         = record {hidden} end;
   dirEntry    = record {hidden} end;
   dirEntryPtr =  ^dirEntry;

{@@ #include <sys/types.h> @@}
{@@ #include <sys/stat.h> @@}
{@@ #include <dirent.h> @@}

var
   myDirPtr : dirPtr;
   ep       : dirEntryPtr;
   s        : packed array[1..20] of char;

#define STRINGPARAM packed array[one..len :integer] of char


{: check if a named file exists
   fname is a pascal string - either blank padded or null terminated is OK
   return true iff file exists
}
function fileExists(fname : STRINGPARAM ) : boolean;
begin
{@@ {}
    char filename[NAME_MAX+1];
    const char *s =  fname_2c;
    struct stat st;
    int i=0,l=0;
    while(i<len_2) {
       if(s[i]!=' ') l=i;
       if(i<NAME_MAX) {filename[i] = s[i]; i++;}
    } //while
    filename[l+1] = '\0';
    int result = stat(filename, &st);
    return result == 0;
@@}
   fileExists := true;  {unused}
end; { fileExists }


{: check if a named file exists and is a directory
   fname is a pascal string
   return true iff file exists and is a directory
}
function isDir(fname : STRINGPARAM ) : boolean;
begin
{@@ {}
    char filename[NAME_MAX+1];
    const char *s =  fname_2c;
    struct stat st;
    int i=0,l=0;
    while(i<len_2) {
       if(s[i]!=' ') l=i;
       if(i<NAME_MAX) {filename[i] = s[i]; i++;}
    } //while
    filename[l+1] = '\0';
    int result = stat(filename, &st);
    return (result == 0) && (S_ISDIR(st.st_mode) != 0);
@@}
   isDir := true;  {unused}
end; { isDir }


{: check if a named file exists and is a regular file
   fname is a pascal string
   return true iff file exists and is a regular file
}
function isRegularFile(fname : STRINGPARAM ) : boolean;
begin
{@@ {}
    char filename[NAME_MAX+1];
    const char *s =  fname_2c;
    struct stat st;
    int i=0,l=0;
    while(i<len_2) {
       if(s[i]!=' ') l=i;
       if(i<NAME_MAX) {filename[i] = s[i]; i++;}
    } //while
    filename[l+1] = '\0';
    int result = stat(filename, &st);
    return (result == 0) && (S_ISREG(st.st_mode) != 0);
@@}
   isRegularFile := true;  {unused}
end; { isRegularFile }


{: open a named directory
   dname is a pascal string
   return a pointer to a directory info block
}
function opendir(dname : STRINGPARAM) : dirPtr;
begin
   {@@ {}
    char dname[NAME_MAX+1];
    const char *s =  dname_2c;
    int i=0,l=0;
    while(i<len_2) {
       if(s[i]!=' ') l=i;
       if(i<NAME_MAX) {dname[i] = s[i]; i++;}
    } //while
    dname[l+1] = '\0';
   return (dirPtr_1)opendir(dname);
   @@}
   openDir := nil;  {unused}
end; { opendir }


{: create a named directory
   dname is a pascal string
   return - true if successful
          - false if unsuccessful
}
function mkDir(dname : STRINGPARAM) : boolean;
begin
   {@@ {}
    char dname[NAME_MAX+1];
    const char *s =  dname_2c;
    int i=0,l=0;
    while(i<len_2) {
       if(s[i]!=' ') l=i;
       if(i<NAME_MAX) {dname[i] = s[i]; i++;}
    } //while
    dname[l+1] = '\0';
   return mkdir(dname, S_IRWXU)==0;
   @@}
   mkDir := false;  {unused}
end; { opendir }


{: close a directory
   dp is a pointer to a directory info block
}
procedure closedir(dp : dirPtr);
begin
   {@@
   (void) closedir ((DIR * )dp_2);
   @@}
end; { closedir }


{: read next entry in a directory
   dp is a pointer to a directory info block
   return - a pointer to a directory entry info block
          - nil when there are no more entries
}
function readDir(dp : dirPtr): dirEntryPtr;
begin
   {@@
   return (dirEntryPtr_1)readdir((DIR * )dp_2);
   @@}
   readDir :=  nil; {unused}
end; { readDir }


{: get the name of a directory entry
   p is  a pointer to a directory entry info block
   name is a pascal string
}
procedure getName(p : dirEntryPtr; var name : STRINGPARAM );
begin
   {@@
   strncpy(name_2c, ((struct dirent * )p_2)->d_name, len_2);
   @@}
end; { getName }


begin

   {test make directory function}

   if mkDir('TestTest') then
      writeln('directory created')
   else
      writeln('couldn''t create directory');

   {list current directory}
   s := './';
   myDirPtr := opendir(s);
   if myDirPtr <> nil then begin
      writeln( 'reading dir ');

      {loop to get each directory entry}
      ep := readDir(myDirPtr);
      while ep <> nil do begin
         getName(ep, s);
         write('next file is ', s);
         if isDir(s) then write('/')
         else if not isRegularFile(s) then write('!');
         writeln;
         ep := readDir(myDirPtr);
      end; {while}

      closeDir(myDirPtr);
   end {if}
   else
      writeln('couldn''t open directory');
end.

{%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end of dirDemo.pas %%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
