vhdlpp: read() takes into account the size of the destination variable.

This commit is contained in:
Maciej Suminski 2016-02-26 10:43:37 +01:00
parent 94f7504372
commit 7c10de918e
1 changed files with 38 additions and 29 deletions

View File

@ -61,6 +61,9 @@ enum file_open_status_t { FS_OPEN_OK, FS_STATUS_ERROR, FS_NAME_ERROR, FS_MODE_ER
/* bits per vector, in a single s_vpi_vecval struct */
static const size_t BPW = 8 * sizeof(PLI_INT32);
/* string buffer size */
static const size_t STRING_BUF_SIZE = 1024;
static int is_integer_var(vpiHandle obj)
{
PLI_INT32 type = vpi_get(vpiType, obj);
@ -224,11 +227,18 @@ static int read_time(const char *string, s_vpi_value *val, PLI_INT32 scope_unit)
return processed_chars;
}
static int read_string(const char *string, s_vpi_value *val) {
char buf[1024];
static int read_string(const char *string, s_vpi_value *val, int count) {
char buf[STRING_BUF_SIZE];
int processed_chars;
char format_str[32];
if(sscanf(string, "%1024s%n", buf, &processed_chars) != 1)
/* No string length limit imposed */
if(count == 0)
count = STRING_BUF_SIZE;
snprintf(format_str, 32, "%%%ds%%n", count);
if(sscanf(string, format_str, buf, &processed_chars) != 1)
return 0;
val->format = vpiStringVal;
@ -473,8 +483,7 @@ static PLI_INT32 ivlh_readline_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
PLI_UINT32 fd;
FILE *fp;
char *text;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
char buf[STRING_BUF_SIZE];
/* Get the file descriptor. */
arg = vpi_scan(argv);
@ -496,7 +505,7 @@ static PLI_INT32 ivlh_readline_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
/* Read in the bytes. Return 0 if there was an error. */
if(fgets(buf, BUF_SIZE, fp) == 0) {
if(fgets(buf, STRING_BUF_SIZE, fp) == 0) {
show_error_line(callh);
vpi_printf("%s reading past the end of file.\n", name);
@ -509,7 +518,7 @@ static PLI_INT32 ivlh_readline_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
show_error_line(callh);
vpi_printf("%s read 0 bytes.\n", name);
return 0;
} else if(len == BUF_SIZE - 1) {
} else if(len == STRING_BUF_SIZE - 1) {
show_warning_line(callh);
vpi_printf("%s has reached the buffer limit, part of the "
"processed string might have been skipped.\n", name);
@ -625,19 +634,15 @@ static PLI_INT32 ivlh_read_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle stringh, varh, formath;
s_vpi_value val;
PLI_INT32 type, format;
PLI_INT32 type, format, dest_size;
char *string = 0;
int processed_chars = 0, fail = 0;
unsigned int processed_chars = 0, fail = 0;
/* Get the string */
stringh = vpi_scan(argv);
val.format = vpiStringVal;
vpi_get_value(stringh, &val);
/* Get the destination variable */
varh = vpi_scan(argv);
type = vpi_get(vpiType, varh);
if(strlen(val.value.str) == 0) {
show_error_line(callh);
vpi_printf("%s cannot read from an empty string.\n", name);
@ -646,6 +651,11 @@ static PLI_INT32 ivlh_read_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
string = strdup(val.value.str);
/* Get the destination variable */
varh = vpi_scan(argv);
type = vpi_get(vpiType, varh);
dest_size = vpi_get(vpiSize, varh);
/* Get the format (see enum format_t) */
formath = vpi_scan(argv);
val.format = vpiIntVal;
@ -679,7 +689,7 @@ static PLI_INT32 ivlh_read_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
break;
case vpiStringVar:
processed_chars = read_string(string, &val);
processed_chars = read_string(string, &val, dest_size / 8);
break;
default:
@ -719,7 +729,7 @@ static PLI_INT32 ivlh_read_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
break;
case FORMAT_STRING:
processed_chars = read_string(string, &val);
processed_chars = read_string(string, &val, dest_size / 8);
break;
}
@ -727,7 +737,7 @@ static PLI_INT32 ivlh_read_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
show_error_line(callh);
vpi_printf("%s could not read a valid value.\n", name);
fail = 1;
} else if(val.format == vpiStringVar && processed_chars == 1024) {
} else if(val.format == vpiStringVar && processed_chars == STRING_BUF_SIZE) {
show_warning_line(callh);
vpi_printf("%s has reached the buffer limit, part of the "
"processed string might have been skipped.\n", name);
@ -815,9 +825,8 @@ static PLI_INT32 ivlh_write_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
s_vpi_value val;
PLI_INT32 type, format;
char *string = 0;
int fail = 0, res = 0;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
unsigned int fail = 0, res = 0;
char buf[STRING_BUF_SIZE];
/* Get the string */
stringh = vpi_scan(argv);
@ -869,7 +878,7 @@ static PLI_INT32 ivlh_write_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
case vpiIntegerVar:
val.format = vpiIntVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%d", string, val.value.integer);
res = snprintf(buf, STRING_BUF_SIZE, "%s%d", string, val.value.integer);
break;
case vpiBitVar: /* bit, bit vector */
@ -881,19 +890,19 @@ static PLI_INT32 ivlh_write_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
for(size_t i = 0; i< strlen(val.value.str); ++i)
val.value.str[i] = toupper(val.value.str[i]);
res = snprintf(buf, BUF_SIZE, "%s%s", string, val.value.str);
res = snprintf(buf, STRING_BUF_SIZE, "%s%s", string, val.value.str);
break;
case vpiRealVar:
val.format = vpiRealVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%lf", string, val.value.real);
res = snprintf(buf, STRING_BUF_SIZE, "%s%lf", string, val.value.real);
break;
case vpiStringVar:
val.format = vpiStringVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%s", string, val.value.str);
res = snprintf(buf, STRING_BUF_SIZE, "%s%s", string, val.value.str);
break;
default:
@ -907,7 +916,7 @@ static PLI_INT32 ivlh_write_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
case FORMAT_BOOL:
val.format = vpiIntVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%s", string,
res = snprintf(buf, STRING_BUF_SIZE, "%s%s", string,
val.value.integer ? "TRUE" : "FALSE");
break;
@ -923,29 +932,29 @@ static PLI_INT32 ivlh_write_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
break;
}
res = snprintf(buf, BUF_SIZE, "%s%s", string, tmp);
res = snprintf(buf, STRING_BUF_SIZE, "%s%s", string, tmp);
}
break;
case FORMAT_HEX:
val.format = vpiIntVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%X", string, val.value.integer);
res = snprintf(buf, STRING_BUF_SIZE, "%s%X", string, val.value.integer);
break;
case FORMAT_STRING:
val.format = vpiStringVal;
vpi_get_value(varh, &val);
res = snprintf(buf, BUF_SIZE, "%s%s", string, val.value.str);
res = snprintf(buf, STRING_BUF_SIZE, "%s%s", string, val.value.str);
break;
}
if(res > BUF_SIZE)
if(res > STRING_BUF_SIZE)
fail = 1;
if(!fail) {
/* Strip the read token from the string */
char* tmp = strndup(buf, BUF_SIZE);
char* tmp = strndup(buf, STRING_BUF_SIZE);
val.format = vpiStringVal;
val.value.str = tmp;
vpi_put_value(stringh, &val, 0, vpiNoDelay);