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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*
|
||||
|
|
@ -804,8 +941,8 @@ static int scan_format_four_state(vpiHandle callh, vpiHandle argv,
|
|||
* 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 an opcode boundary. Which may not be
|
||||
* an error in the data stream. */
|
||||
* 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),
|
||||
|
|
@ -883,8 +1020,6 @@ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv,
|
|||
* found just return EOF. */
|
||||
len = vpi_get(vpiSize, item);
|
||||
words = ((len + 31) / 32) - 1;
|
||||
/* The mask is defined to be 32 bits. */
|
||||
mask = 0xffffffff >> (32 - ((len - 1) % 32 + 1));
|
||||
val.format = vpiVectorVal;
|
||||
vpi_get_value(item, &val);
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
/* The mask is defined to be 32 bits. */
|
||||
mask = UINT32_MAX >> (32U - ((len - 1U) % 32U + 1U));
|
||||
/* Check the top word for an undefined bit. */
|
||||
if (match && (val.value.vector[words].bval & mask)) {
|
||||
match = 0;
|
||||
|
|
@ -1046,6 +1183,15 @@ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv,
|
|||
break;
|
||||
|
||||
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':
|
||||
vpi_printf("SORRY: %s:%d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
|
|
|
|||
Loading…
Reference in New Issue