From 382c4d74fd112c68e90a1805e6c79f26eb03eae8 Mon Sep 17 00:00:00 2001 From: steve Date: Thu, 3 Aug 2006 05:06:04 +0000 Subject: [PATCH] Add the scanf functions. --- vpi/Makefile.in | 4 +- vpi/sys_scanf.c | 378 ++++++++++++++++++++++++++++++++++++++++++++++++ vpi/sys_table.c | 7 +- 3 files changed, 386 insertions(+), 3 deletions(-) create mode 100644 vpi/sys_scanf.c diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 1fb6ef953..d4d4669d2 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -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) diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c new file mode 100644 index 000000000..dbd3a88f1 --- /dev/null +++ b/vpi/sys_scanf.c @@ -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 +# include +# include +# include +# include + +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 %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 $ + */ diff --git a/vpi/sys_table.c b/vpi/sys_table.c index fb4bd6285..44142d391 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -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.