vhdlpp: Added file_open() variant that returns status.
This commit is contained in:
parent
0f3f8907c3
commit
34b5834a84
|
|
@ -318,6 +318,17 @@ void preload_std_funcs(void)
|
||||||
perm_string::literal("$ivlh_file_open"),
|
perm_string::literal("$ivlh_file_open"),
|
||||||
args, NULL));
|
args, NULL));
|
||||||
|
|
||||||
|
/* procedure file_open (status: out file_open_status, file f: text; filename: in string, file_open_kind: in mode);
|
||||||
|
*/
|
||||||
|
args = new list<InterfacePort*>();
|
||||||
|
args->push_back(new InterfacePort(&type_FILE_OPEN_STATUS, PORT_OUT));
|
||||||
|
args->push_back(new InterfacePort(&primitive_INTEGER, PORT_IN));
|
||||||
|
args->push_back(new InterfacePort(&primitive_STRING, PORT_IN));
|
||||||
|
args->push_back(new InterfacePort(&type_FILE_OPEN_KIND, PORT_IN));
|
||||||
|
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("file_open"),
|
||||||
|
perm_string::literal("$ivlh_file_open"),
|
||||||
|
args, NULL));
|
||||||
|
|
||||||
/* std.textio library
|
/* std.textio library
|
||||||
* procedure file_close (file f: text);
|
* procedure file_close (file f: text);
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
# include <errno.h>
|
||||||
# include "ivl_alloc.h"
|
# include "ivl_alloc.h"
|
||||||
|
|
||||||
/* additional parameter values to distinguish between integer, boolean and
|
/* additional parameter values to distinguish between integer, boolean and
|
||||||
|
|
@ -55,6 +56,7 @@
|
||||||
enum format_t { FORMAT_STD, FORMAT_BOOL, FORMAT_TIME, FORMAT_HEX, FORMAT_STRING };
|
enum format_t { FORMAT_STD, FORMAT_BOOL, FORMAT_TIME, FORMAT_HEX, FORMAT_STRING };
|
||||||
|
|
||||||
enum file_mode_t { FILE_MODE_READ, FILE_MODE_WRITE, FILE_MODE_APPEND, FILE_MODE_LAST };
|
enum file_mode_t { FILE_MODE_READ, FILE_MODE_WRITE, FILE_MODE_APPEND, FILE_MODE_LAST };
|
||||||
|
enum file_open_status_t { FS_OPEN_OK, FS_STATUS_ERROR, FS_NAME_ERROR, FS_MODE_ERROR };
|
||||||
|
|
||||||
/* bits per vector, in a single s_vpi_vecval struct */
|
/* bits per vector, in a single s_vpi_vecval struct */
|
||||||
static const size_t BPW = 8 * sizeof(PLI_INT32);
|
static const size_t BPW = 8 * sizeof(PLI_INT32);
|
||||||
|
|
@ -67,6 +69,11 @@ static int is_integer_var(vpiHandle obj)
|
||||||
type == vpiIntVar || type == vpiLongIntVar);
|
type == vpiIntVar || type == vpiLongIntVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_const(vpiHandle obj)
|
||||||
|
{
|
||||||
|
return vpi_get(vpiType, obj) == vpiConstant;
|
||||||
|
}
|
||||||
|
|
||||||
static void show_error_line(vpiHandle callh) {
|
static void show_error_line(vpiHandle callh) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
|
@ -281,40 +288,44 @@ static int write_time(char *string, const s_vpi_value* val,
|
||||||
static PLI_INT32 ivlh_file_open_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
static PLI_INT32 ivlh_file_open_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv;
|
vpiHandle argv, arg;
|
||||||
assert(callh != 0);
|
assert(callh != 0);
|
||||||
|
int ok = 1;
|
||||||
|
|
||||||
argv = vpi_iterate(vpiArgument, callh);
|
argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
|
||||||
/* Check that there is a file name argument and that it is a string. */
|
/* Check that there is a file name argument and that it is a string. */
|
||||||
if (argv == 0) {
|
if (argv == 0)
|
||||||
show_error_line(callh);
|
ok = 0;
|
||||||
vpi_printf("%s requires a string file name argument.\n", name);
|
|
||||||
vpi_control(vpiFinish, 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_integer_var(vpi_scan(argv))) {
|
arg = vpi_scan(argv);
|
||||||
show_error_line(callh);
|
if (!arg || !is_integer_var(arg))
|
||||||
vpi_printf("%s's first argument has to be an integer variable (file handle).\n", name);
|
ok = 0;
|
||||||
vpi_control(vpiFinish, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_string_obj(vpi_scan(argv))) {
|
arg = vpi_scan(argv);
|
||||||
show_error_line(callh);
|
if (arg && is_integer_var(arg))
|
||||||
vpi_printf("%s's second argument argument must be a string (file name).\n", name);
|
arg = vpi_scan(argv);
|
||||||
vpi_control(vpiFinish, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When provided, the type argument must be a string. */
|
// no vpi_scan() here, if we had both 'status' and 'file' arguments,
|
||||||
if(!vpi_scan(argv)) {
|
// then the next arg is read in the above if, otherwise we are going
|
||||||
|
// to check the second argument once again
|
||||||
|
if (!arg || !is_string_obj(arg))
|
||||||
|
ok = 0;
|
||||||
|
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (arg && !is_const(arg))
|
||||||
|
ok = 0;
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
show_error_line(callh);
|
show_error_line(callh);
|
||||||
vpi_printf("%s's third argument must be an integer (open mode).\n", name);
|
vpi_printf("%s() function is available in following variants:\n", name);
|
||||||
|
vpi_printf("* (file f: text; filename: in string, file_open_kind: in mode)\n");
|
||||||
|
vpi_printf("* (status: out file_open_status, file f: text; filename: in string, file_open_kind: in mode)\n");
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure there are no extra arguments. */
|
/* Make sure there are no extra arguments. */
|
||||||
check_for_extra_args(argv, callh, name, "three arguments", 1);
|
check_for_extra_args(argv, callh, name, "four arguments", 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -330,15 +341,25 @@ static PLI_INT32 ivlh_file_open_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
int mode;
|
int mode;
|
||||||
char *fname;
|
char *fname;
|
||||||
|
|
||||||
|
vpiHandle fstatush = vpi_scan(argv);
|
||||||
vpiHandle fhandleh = vpi_scan(argv);
|
vpiHandle fhandleh = vpi_scan(argv);
|
||||||
vpiHandle fnameh = vpi_scan(argv);
|
vpiHandle fnameh = vpi_scan(argv);
|
||||||
vpiHandle modeh = vpi_scan(argv);
|
vpiHandle modeh = vpi_scan(argv);
|
||||||
|
|
||||||
|
if(!modeh) {
|
||||||
|
/* There are only three arguments, so rearrange handles */
|
||||||
|
modeh = fnameh;
|
||||||
|
fnameh = fhandleh;
|
||||||
|
fhandleh = fstatush;
|
||||||
|
fstatush = 0;
|
||||||
|
} else {
|
||||||
|
vpi_free_object(argv);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the mode handle */
|
/* Get the mode handle */
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
vpi_get_value(modeh, &val);
|
vpi_get_value(modeh, &val);
|
||||||
mode = val.value.integer;
|
mode = val.value.integer;
|
||||||
vpi_free_object(argv);
|
|
||||||
|
|
||||||
if(mode < 0 || mode >= FILE_MODE_LAST) {
|
if(mode < 0 || mode >= FILE_MODE_LAST) {
|
||||||
show_error_line(callh);
|
show_error_line(callh);
|
||||||
|
|
@ -355,21 +376,51 @@ static PLI_INT32 ivlh_file_open_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open file and save the handle */
|
/* Open file and save the handle */
|
||||||
|
PLI_INT32 result = -1;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case FILE_MODE_READ:
|
case FILE_MODE_READ:
|
||||||
val.value.integer = vpi_fopen(fname, "r");
|
result = vpi_fopen(fname, "r");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_MODE_WRITE:
|
case FILE_MODE_WRITE:
|
||||||
val.value.integer = vpi_fopen(fname, "w");
|
result = vpi_fopen(fname, "w");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_MODE_APPEND:
|
case FILE_MODE_APPEND:
|
||||||
val.value.integer = vpi_fopen(fname, "a");
|
result = vpi_fopen(fname, "a");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(fstatush) {
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
switch(errno) {
|
||||||
|
case ENOENT:
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
val.value.integer = FS_NAME_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EINVAL:
|
||||||
|
case EACCES:
|
||||||
|
case EEXIST:
|
||||||
|
case EISDIR:
|
||||||
|
val.value.integer = FS_MODE_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
val.value.integer = FS_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val.value.integer = FS_OPEN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpi_put_value(fstatush, &val, 0, vpiNoDelay);
|
||||||
|
}
|
||||||
|
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
|
val.value.integer = result;
|
||||||
vpi_put_value(fhandleh, &val, 0, vpiNoDelay);
|
vpi_put_value(fhandleh, &val, 0, vpiNoDelay);
|
||||||
free(fname);
|
free(fname);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue