Skip to content

Commit

Permalink
Implement DIR_OPEN and DIR_CLOSE
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Jul 30, 2023
1 parent aaeee95 commit ea457d5
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 9 deletions.
24 changes: 16 additions & 8 deletions lib/std.19/env-body.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,11 @@ package body env is
return trec + (-delta);
end function;

function "-" (delta : real; trec : time_record) return time_record is
begin
-- It's not really clear what this is for
report "not implemented" severity failure;
end function;
-- function "-" (delta : real; trec : time_record) return time_record is
-- begin
-- -- It's not really clear what this is for
-- report "not implemented" severity failure;
-- end function;

function "-" (tr1, tr2 : time_record) return real is
function impl (tr1, tr2 : in time_record) return real;
Expand Down Expand Up @@ -251,19 +251,27 @@ package body env is
procedure dir_open (dir : out directory;
path : in string;
status : out dir_open_status) is
procedure impl (path : in string;
dir : out directory;
status : out dir_open_status);
attribute foreign of impl : procedure is "_std_env_dir_open";
begin
report "not implemented" severity failure;
impl(path, dir, status);
end procedure;

impure function dir_open (dir : out directory;
path : in string) return dir_open_status is
variable status : dir_open_status;
begin
report "not implemented" severity failure;
dir_open(dir, path, status);
return status;
end function;

procedure dir_close (variable dir : inout directory) is
begin
report "not implemented" severity failure;
-- No-op with garbage collection
dir.name := null;
dir.items := null;
end procedure;

impure function dir_itemexists (path : in string) return boolean is
Expand Down
2 changes: 1 addition & 1 deletion lib/std.19/env.vhdl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ package ENV is
function "+"(TREC: TIME_RECORD; DELTA: REAL) return TIME_RECORD;
function "+"(DELTA: REAL; TREC: TIME_RECORD) return TIME_RECORD;
function "-"(TREC: TIME_RECORD; DELTA: REAL) return TIME_RECORD;
function "-"(DELTA: REAL; TREC: TIME_RECORD) return TIME_RECORD;
--function "-"(DELTA: REAL; TREC: TIME_RECORD) return TIME_RECORD;

-- Time difference in seconds. TR1, TR2 must both be in local
-- time, or both in UTC.
Expand Down
71 changes: 71 additions & 0 deletions src/rt/stdenv.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>

Expand All @@ -53,6 +54,11 @@ typedef struct {
int64_t dayofyear;
} time_record_t;

typedef struct {
ffi_uarray_t *name;
ffi_uarray_t *items;
} directory_t;

typedef enum {
DIR_OPEN_STATUS_OK = 0,
DIR_OPEN_STATUS_NOT_FOUND = 1,
Expand Down Expand Up @@ -439,6 +445,71 @@ void _std_env_deletefile(const uint8_t *path_ptr, int64_t path_len,
*status = FILE_DELETE_STATUS_OK;
}

DLLEXPORT
void _std_env_dir_open(const uint8_t *path_ptr, int64_t path_len,
directory_t *dir, int8_t *status)
{
char *path LOCAL = to_cstring(path_ptr, path_len);

DIR *d = opendir(path);
if (d == NULL) {
*status = errno_to_dir_open_status();
return;
}

char resolved[PATH_MAX];
realpath(path, resolved);

const size_t resolvedsz = strlen(resolved);
size_t memsz = sizeof(ffi_uarray_t)*2 + resolvedsz;
struct dirent *e;
int count = 0;
while ((e = readdir(d))) {
const size_t nchars = strlen(e->d_name);
memsz += sizeof(ffi_uarray_t) + ALIGN_UP(nchars, 8);
count++;
}
memsz += count * sizeof(ffi_uarray_t *);

rewinddir(d);

void *mem = jit_mspace_alloc(memsz), *next = mem;
dir->items = next;
dir->items->dims[0].left = 0;
dir->items->dims[0].length = count;
dir->items->ptr = dir->items + 1;

next += sizeof(ffi_uarray_t) + count * sizeof(ffi_uarray_t *);

for (int nth = 0; (e = readdir(d)); nth++) {
const size_t nchars = strlen(e->d_name);

ffi_uarray_t *u = next;
u->ptr = u + 1;
u->dims[0].left = 1;
u->dims[0].length = nchars;
memcpy(u->ptr, e->d_name, nchars);

*((ffi_uarray_t **)dir->items->ptr + nth) = u;

next += sizeof(ffi_uarray_t) + ALIGN_UP(nchars, 8);
}

closedir(d);

dir->name = next;
dir->name->ptr = dir->name + 1;
dir->name->dims[0].left = 1;
dir->name->dims[0].length = resolvedsz;

memcpy(dir->name->ptr, resolved, resolvedsz);

next += sizeof(ffi_uarray_t) + resolvedsz;
assert(next == mem + memsz);

*status = 0;
}

DLLEXPORT
void _std_env_get_call_path(ffi_uarray_t **ptr)
{
Expand Down
1 change: 1 addition & 0 deletions src/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
_std_env_createdir;
_std_env_deletefile;
_std_env_diff_trec;
_std_env_dir_open;
_std_env_epoch;
_std_env_epoch_trec;
_std_env_file_line;
Expand Down
18 changes: 18 additions & 0 deletions test/regress/stdenv6.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,30 @@ begin
p1: process is
file f : text;
variable status : file_delete_status;
variable dir : directory;
variable found : boolean;
begin
file_open(f, "tmp.txt", write_mode);
file_close(f);

assert dir_itemexists("tmp.txt");

assert dir_open(dir, ".") = STATUS_OK;

for i in dir.items'range loop
report dir.items(i).all;
if dir.items(i).all = "tmp.txt" then
assert not found;
found := true;
end if;
end loop;

assert found report "missing tmp.txt";

report dir.name.all;

dir_close(dir);

dir_deletefile("tmp.txt", status);
assert status = STATUS_OK;

Expand Down

0 comments on commit ea457d5

Please sign in to comment.