Add %u support to the scanf routines.
This commit is contained in:
parent
61cfb9e1fd
commit
1f6aec6e26
154
vpi/sys_scanf.c
154
vpi/sys_scanf.c
|
|
@ -716,6 +716,143 @@ static int scan_format_string(vpiHandle callh, vpiHandle argv,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routine to return a two state value (implements %u).
|
||||||
|
*
|
||||||
|
* Note: Since this is a binary routine it also does not check for leading
|
||||||
|
* space characters or use space as a boundary character.
|
||||||
|
*
|
||||||
|
* Return: 1 for a match, 0 for no match/variable and -1 for a
|
||||||
|
* suppressed match. No variable is fatal.
|
||||||
|
*/
|
||||||
|
static int scan_format_two_state(vpiHandle callh, vpiHandle argv,
|
||||||
|
struct byte_source *src, unsigned width,
|
||||||
|
unsigned suppress_flag, PLI_BYTE8 *name)
|
||||||
|
{
|
||||||
|
vpiHandle arg;
|
||||||
|
p_vpi_vecval val_ptr;
|
||||||
|
s_vpi_value val;
|
||||||
|
unsigned words, word;
|
||||||
|
PLI_INT32 varlen;
|
||||||
|
|
||||||
|
/* If we are being asked for no data then return a match fail. */
|
||||||
|
if (width == 0) return 0;
|
||||||
|
|
||||||
|
/* Since this is a binary format we do not have an ending sequence.
|
||||||
|
* Consequently we need to use the width to determine how many word
|
||||||
|
* pairs to remove from the input stream. */
|
||||||
|
if (suppress_flag) {
|
||||||
|
/* If no width was given then just remove one word pair. */
|
||||||
|
if (width == UINT_MAX) words = 1;
|
||||||
|
else words = (width+31)/32;
|
||||||
|
for (word = 0; word < words; word += 1) {
|
||||||
|
unsigned byte;
|
||||||
|
/* For a suppression we do not care about the endian order
|
||||||
|
* of the bytes. */
|
||||||
|
for (byte = 0; byte < 4; byte += 1) {
|
||||||
|
int ch = byte_getc(src);
|
||||||
|
/* See the EOF comments below for more details. */
|
||||||
|
if (ch == EOF) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s() only found %u of %u bytes "
|
||||||
|
"needed by %%u format code.\n", name,
|
||||||
|
word*4U + byte, words*4U);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must have a variable to put the bits into. */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (! arg) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s() ran out of variables for %%u format code.", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract either the given number of word pairs or enough to fill
|
||||||
|
* the variable. */
|
||||||
|
varlen = (vpi_get(vpiSize, arg)+31)/32;
|
||||||
|
assert(varlen > 0);
|
||||||
|
val_ptr = (p_vpi_vecval) malloc(varlen*sizeof(s_vpi_vecval));
|
||||||
|
if (width == UINT_MAX) words = (unsigned)varlen;
|
||||||
|
else words = (width+31)/32;
|
||||||
|
for (word = 0; word < words; word += 1) {
|
||||||
|
int byte;
|
||||||
|
PLI_INT32 bits = 0;
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
for (byte = 3; byte >= 0; byte -= 1) {
|
||||||
|
#else
|
||||||
|
for (byte = 0; byte <= 3; byte += 1) {
|
||||||
|
#endif
|
||||||
|
int ch = byte_getc(src);
|
||||||
|
/* If there is an EOF while reading the bytes then treat
|
||||||
|
* that as a non-match. It could be argued that the bytes
|
||||||
|
* should be put back, but that is not practical and since
|
||||||
|
* a binary read should be treated as an atomic operation
|
||||||
|
* it's not helpful either. An EOF while reading is an
|
||||||
|
* error in the data stream so print a message to help the
|
||||||
|
* user debug what is going wrong. The calling routine has
|
||||||
|
* already verified that there is at least one byte
|
||||||
|
* available so this message is not printed when an EOF
|
||||||
|
* occurs at a format code boundary. Which may not be an
|
||||||
|
* error in the data stream. */
|
||||||
|
if (ch == EOF) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s() only found %d of %u bytes needed by "
|
||||||
|
"%%u format code.\n", name, word*4 +
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
(3-byte),
|
||||||
|
#else
|
||||||
|
byte,
|
||||||
|
#endif
|
||||||
|
words*4U);
|
||||||
|
free(val_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bits |= (ch & 0xff) << byte*8;
|
||||||
|
}
|
||||||
|
/* Only save the words that are in range. */
|
||||||
|
if (word < (unsigned)varlen) {
|
||||||
|
val_ptr[word].aval = bits;
|
||||||
|
val_ptr[word].bval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mask the upper bits to match the specified width when required. */
|
||||||
|
if (width != UINT_MAX) {
|
||||||
|
PLI_INT32 mask = UINT32_MAX >> (32U - ((width - 1U) % 32U + 1U));
|
||||||
|
val_ptr[words-1].aval &= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough words were read to fill the variable so zero fill the
|
||||||
|
* upper words. */
|
||||||
|
if (words < (unsigned)varlen) {
|
||||||
|
for (word = words; word < varlen ; word += 1) {
|
||||||
|
val_ptr[word].aval = 0;
|
||||||
|
val_ptr[word].bval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the two-state value into the variable. */
|
||||||
|
val.format = vpiVectorVal;
|
||||||
|
val.value.vector = val_ptr;
|
||||||
|
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||||
|
free(val_ptr);
|
||||||
|
|
||||||
|
/* One variable was consumed. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routine to return a four state value (implements %z).
|
* Routine to return a four state value (implements %z).
|
||||||
*
|
*
|
||||||
|
|
@ -804,8 +941,8 @@ static int scan_format_four_state(vpiHandle callh, vpiHandle argv,
|
||||||
* debug what is going wrong. The calling routine has
|
* debug what is going wrong. The calling routine has
|
||||||
* already verified that there is at least one byte
|
* already verified that there is at least one byte
|
||||||
* available so this message is not printed when an
|
* available so this message is not printed when an
|
||||||
* EOF occurs at an opcode boundary. Which may not be
|
* EOF occurs at a format code boundary. Which may
|
||||||
* an error in the data stream. */
|
* not be an error in the data stream. */
|
||||||
if (ch == EOF) {
|
if (ch == EOF) {
|
||||||
vpi_printf("WARNING: %s:%d: ",
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
vpi_get_str(vpiFile, callh),
|
vpi_get_str(vpiFile, callh),
|
||||||
|
|
@ -883,8 +1020,6 @@ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv,
|
||||||
* found just return EOF. */
|
* found just return EOF. */
|
||||||
len = vpi_get(vpiSize, item);
|
len = vpi_get(vpiSize, item);
|
||||||
words = ((len + 31) / 32) - 1;
|
words = ((len + 31) / 32) - 1;
|
||||||
/* The mask is defined to be 32 bits. */
|
|
||||||
mask = 0xffffffff >> (32 - ((len - 1) % 32 + 1));
|
|
||||||
val.format = vpiVectorVal;
|
val.format = vpiVectorVal;
|
||||||
vpi_get_value(item, &val);
|
vpi_get_value(item, &val);
|
||||||
/* Check the full words for an undefined bit. */
|
/* Check the full words for an undefined bit. */
|
||||||
|
|
@ -895,6 +1030,8 @@ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* The mask is defined to be 32 bits. */
|
||||||
|
mask = UINT32_MAX >> (32U - ((len - 1U) % 32U + 1U));
|
||||||
/* Check the top word for an undefined bit. */
|
/* Check the top word for an undefined bit. */
|
||||||
if (match && (val.value.vector[words].bval & mask)) {
|
if (match && (val.value.vector[words].bval & mask)) {
|
||||||
match = 0;
|
match = 0;
|
||||||
|
|
@ -1046,6 +1183,15 @@ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
|
match = scan_format_two_state(callh, argv, src,
|
||||||
|
max_width,
|
||||||
|
suppress_flag, name);
|
||||||
|
/* If a binary match fails and it is the first item
|
||||||
|
* matched then treat that as an EOF. */
|
||||||
|
if ((match == 0) && (rc == 0)) rc = EOF;
|
||||||
|
if (match == 1) rc += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
vpi_printf("SORRY: %s:%d: ",
|
vpi_printf("SORRY: %s:%d: ",
|
||||||
vpi_get_str(vpiFile, callh),
|
vpi_get_str(vpiFile, callh),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue