Add $readmempath to set a search path for $readmem{b,h}.

This patch add a new system function $readmempath. It accepts
a ":" separated list of directories that $readmem{b,h} will
use when trying to open a given file. If the file given to
$readmem{b,h} starts with a '/' (an absolute path) the search
list will not be used. A new call to $readmempath will replace
the previous search list with the given list. The search list
elements are check to see if they exist and are directories.
If not a warning will be displayed and they will not be added
to the list.
This commit is contained in:
Cary R 2009-04-09 11:34:56 -07:00 committed by Stephen Williams
parent 047828ded0
commit fc8549c9f8
1 changed files with 126 additions and 1 deletions

View File

@ -27,6 +27,10 @@
# include <stdio.h>
# include <assert.h>
# include "sys_readmem_lex.h"
# include <sys/stat.h>
char **search_list = NULL;
unsigned sl_count = 0;
static void get_mem_params(vpiHandle argv, vpiHandle callh, char *name,
char **fname, vpiHandle *mitem,
@ -291,8 +295,18 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
&start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0;
/* Open the data file. */
/* Open the data file. */
file = fopen(fname, "r");
/* Check to see if we have other directories to look for this file. */
if (file == 0 && sl_count > 0 && fname[0] != '/') {
unsigned idx;
char path[4096];
for (idx = 0; idx < sl_count; idx += 1) {
snprintf(path, 4096, "%s/%s", search_list[idx], fname);
if ((file = fopen(path, "r"))) break;
}
}
if (file == 0) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
@ -391,6 +405,102 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
return 0;
}
static PLI_INT32 free_readmempath(p_cb_data cb_data)
{
unsigned idx;
for(idx = 0; idx < sl_count; idx += 1) {
free(search_list[idx]);
}
free(search_list);
search_list = NULL;
sl_count = 0;
return 0;
}
static PLI_INT32 sys_readmempath_calltf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle paths = vpi_scan(argv);
s_vpi_value val;
unsigned len, idx;
char *path;
vpi_free_object(argv);
/* Get the search path string. */
val.format = vpiStringVal;
vpi_get_value(paths, &val);
/* Verify that we have a string and that it is not NULL. */
if (val.format != vpiStringVal || !*(val.value.str)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's argument (%s) is not a valid string.\n",
name, vpi_get_str(vpiType, paths));
return 0;
}
/*
* Verify that the search path is composed of only printable
* characters.
*/
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
char *esc_path = as_escaped(val.value.str);
snprintf(msg, 64, "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s's argument contains non-printable "
"characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_path);
free(esc_path);
return 0;
}
}
/* Clear the old list before creating the new list. */
free_readmempath(NULL);
/*
* Break the string into individual paths and add them to the list.
* Print a warning if the path is not valid.
*/
for (path = strtok(val.value.str, ":"); path; path = strtok(NULL, ":")) {
int res;
struct stat sb;
/* Warn the user if the path is not valid. */
res = stat(path, &sb);
if (res == 0) {
if (!S_ISDIR(sb.st_mode)) {
vpi_printf("WARNING: %s:%d: ",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's path element \"%s\" is not a "
"directory!\n", name, path);
continue;
}
} else {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s could not find directory \"%s\"!\n",
name, path);
continue;
}
/* Add a valid search path element to the list. */
sl_count += 1;
search_list = (char **) realloc(search_list,
sizeof(char **)*sl_count);
search_list[sl_count-1] = strdup(path);
}
return 0;
}
static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
{
int addr;
@ -455,6 +565,7 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
void sys_readmem_register()
{
s_vpi_systf_data tf_data;
s_cb_data cb_data;
tf_data.type = vpiSysTask;
tf_data.tfname = "$readmemh";
@ -472,6 +583,14 @@ void sys_readmem_register()
tf_data.user_data = "$readmemb";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$readmempath";
tf_data.calltf = sys_readmempath_calltf;
tf_data.compiletf = sys_one_string_arg_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$readmempath";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$writememh";
tf_data.calltf = sys_writemem_calltf;
@ -487,4 +606,10 @@ void sys_readmem_register()
tf_data.sizetf = 0;
tf_data.user_data = "$writememb";
vpi_register_systf(&tf_data);
cb_data.reason = cbEndOfSimulation;
cb_data.time = 0;
cb_data.cb_rtn = free_readmempath;
cb_data.user_data = "system";
vpi_register_cb(&cb_data);
}