Add the scanf functions.
This commit is contained in:
parent
5bcf083662
commit
382c4d74fd
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.58 2004/10/04 01:09:22 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.59 2006/08/03 05:06:04 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -65,7 +65,7 @@ dep:
|
|||
|
||||
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
||||
sys_finish.o sys_plusargs.o sys_random.o sys_random_mti.o \
|
||||
sys_readmem.o sys_readmem_lex.o \
|
||||
sys_readmem.o sys_readmem_lex.o sys_scanf.o \
|
||||
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o priv.o stringheap.o
|
||||
|
||||
ifeq (@HAVE_LIBZ@,yes)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_scanf.c,v 1.1 2006/08/03 05:06:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include "sys_priv.h"
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
struct byte_source {
|
||||
const char*str;
|
||||
FILE*fd;
|
||||
};
|
||||
|
||||
static int byte_getc(struct byte_source*byte)
|
||||
{
|
||||
if (byte->str) {
|
||||
if (byte->str[0] == 0)
|
||||
return EOF;
|
||||
else
|
||||
return *(byte->str)++;
|
||||
}
|
||||
|
||||
return fgetc(byte->fd);
|
||||
}
|
||||
|
||||
static void byte_ungetc(struct byte_source*src, int ch)
|
||||
{
|
||||
if (ch == EOF)
|
||||
return;
|
||||
|
||||
if (src->str) {
|
||||
src->str -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(src->fd);
|
||||
ungetc(ch, src->fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The $fscanf and $sscanf functions are the same except for the first
|
||||
* argument, which is the source. The wrapper functions below peel off
|
||||
* the first argument and make a byte_source object that then gets
|
||||
* passed to this function, which processes the rest of the function.
|
||||
*/
|
||||
static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle item;
|
||||
|
||||
char*fmt, *fmtp;
|
||||
int rc = 0;
|
||||
int ch;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiStringVal;
|
||||
vpi_get_value(item, &val);
|
||||
fmtp = fmt = strdup(val.value.str);
|
||||
|
||||
while ( fmtp && *fmtp != 0 ) {
|
||||
|
||||
if (isspace(*fmtp)) {
|
||||
/* White space matches a string of white space in
|
||||
the input. The number of spaces is not
|
||||
relevent, and the match may be 0 or more
|
||||
spaces. */
|
||||
while (*fmtp && isspace(*fmtp))
|
||||
fmtp += 1;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (isspace(ch))
|
||||
ch = byte_getc(src);
|
||||
|
||||
if (ch != EOF)
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
} else if (*fmtp != '%') {
|
||||
/* Characters other then % match themselves. */
|
||||
ch = byte_getc(src);
|
||||
if (ch != *fmtp) {
|
||||
byte_ungetc(src, ch);
|
||||
break;
|
||||
}
|
||||
|
||||
fmtp += 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* We are at a pattern character. The pattern has
|
||||
the format %<N>x no matter what the x code, so
|
||||
parse it generically first. */
|
||||
|
||||
int suppress_flag = 0;
|
||||
int length_field = -1;
|
||||
int code = 0;
|
||||
int sign_flag = 1;
|
||||
PLI_INT32 value;
|
||||
|
||||
char*tmp;
|
||||
|
||||
fmtp += 1;
|
||||
if (*fmtp == '*') {
|
||||
suppress_flag = 1;
|
||||
fmtp += 1;
|
||||
}
|
||||
if (isdigit(*fmtp)) {
|
||||
length_field = 0;
|
||||
while (isdigit(*fmtp)) {
|
||||
length_field *= 10;
|
||||
length_field += *fmtp - '0';
|
||||
fmtp += 1;
|
||||
}
|
||||
}
|
||||
|
||||
code = *fmtp;
|
||||
fmtp += 1;
|
||||
|
||||
switch (code) {
|
||||
case '%':
|
||||
ch = byte_getc(src);
|
||||
if (ch != '%') {
|
||||
byte_ungetc(src, ch);
|
||||
fmtp = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
/* binary integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("01xXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiBinStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'd':
|
||||
/* Decimal integer */
|
||||
ch = byte_getc(src);
|
||||
if (ch == '-') {
|
||||
sign_flag = -1;
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
value = 0;
|
||||
while ( isdigit(ch) ) {
|
||||
value *= 10;
|
||||
value += ch - '0';
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = value;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'x':
|
||||
/* Hex integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("0123456789abcdefABCDEFxXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiHexStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
/* binary integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("01234567xXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiOctStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("$scanf: Unknown format code: %c\n", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(fmt);
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = rc;
|
||||
vpi_put_value(sys, &val, 0, vpiNoDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fscanf_compiletf(char*name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fscanf_calltf(char*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item;
|
||||
|
||||
struct byte_source src;
|
||||
FILE*fd;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(item, &val);
|
||||
|
||||
fd = vpi_get_file(val.value.integer);
|
||||
assert(fd);
|
||||
|
||||
src.str = 0;
|
||||
src.fd = fd;
|
||||
scan_format(sys, &src, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_sscanf_compiletf(char*name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_sscanf_calltf(char*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item;
|
||||
|
||||
struct byte_source src;
|
||||
char*str;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiStringVal;
|
||||
vpi_get_value(item, &val);
|
||||
str = strdup(val.value.str);
|
||||
|
||||
src.str = str;
|
||||
src.fd = 0;
|
||||
scan_format(sys, &src, argv);
|
||||
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the Xscanf functions return a 32bit value.
|
||||
*/
|
||||
static int sys_fscanf_sizetf(char*x)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
void sys_scanf_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
//============================== fscanf
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$fscanf";
|
||||
tf_data.calltf = sys_fscanf_calltf;
|
||||
tf_data.compiletf = sys_fscanf_compiletf;
|
||||
tf_data.sizetf = sys_fscanf_sizetf;
|
||||
tf_data.user_data = "$fscanf";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
//============================== sscanf
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$sscanf";
|
||||
tf_data.calltf = sys_sscanf_calltf;
|
||||
tf_data.compiletf = sys_sscanf_compiletf;
|
||||
tf_data.sizetf = sys_fscanf_sizetf;
|
||||
tf_data.user_data = "$sscanf";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*/
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_table.c,v 1.25 2004/06/09 22:14:10 steve Exp $"
|
||||
#ident "$Id: sys_table.c,v 1.26 2006/08/03 05:06:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_config.h"
|
||||
|
|
@ -35,6 +35,7 @@ extern void sys_plusargs_register();
|
|||
extern void sys_random_register();
|
||||
extern void sys_random_mti_register();
|
||||
extern void sys_readmem_register();
|
||||
extern void sys_scanf_register();
|
||||
extern void sys_time_register();
|
||||
extern void sys_vcd_register();
|
||||
extern void sys_vcdoff_register();
|
||||
|
|
@ -150,6 +151,7 @@ void (*vlog_startup_routines[])() = {
|
|||
sys_random_register,
|
||||
sys_random_mti_register,
|
||||
sys_readmem_register,
|
||||
sys_scanf_register,
|
||||
sys_time_register,
|
||||
sys_lxt_or_vcd_register,
|
||||
0
|
||||
|
|
@ -158,6 +160,9 @@ void (*vlog_startup_routines[])() = {
|
|||
|
||||
/*
|
||||
* $Log: sys_table.c,v $
|
||||
* Revision 1.26 2006/08/03 05:06:04 steve
|
||||
* Add the scanf functions.
|
||||
*
|
||||
* Revision 1.25 2004/06/09 22:14:10 steve
|
||||
* Move Mersenne Twister to $mti_random, and make
|
||||
* the standard $random standard. Also, add $dist_poisson.
|
||||
|
|
|
|||
Loading…
Reference in New Issue