diff --git a/vpi/table_mod.c b/vpi/table_mod.c index ff2e09070..dc41ae03e 100644 --- a/vpi/table_mod.c +++ b/vpi/table_mod.c @@ -348,7 +348,7 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, table->have_ctl = 1; /* Look for the dependent data field. */ - cp = index(control, ';'); + cp = strchr(control, ';'); if (cp) { size_t len; unsigned long val; @@ -385,7 +385,7 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, /* Find the number of interpolation/extrapolation control fields. */ num_fields = 1; cp = control; - while ((cp = index(cp, ','))) { + while ((cp = strchr(cp, ','))) { cp += 1; num_fields += 1; } diff --git a/vpi/table_mod_parse.y b/vpi/table_mod_parse.y index d2c004c5a..700d1265c 100644 --- a/vpi/table_mod_parse.y +++ b/vpi/table_mod_parse.y @@ -24,21 +24,85 @@ #include "table_mod.h" #include "ivl_alloc.h" +/* + * The number of parse errors encountered while parsing the data file. + */ static unsigned errors = 0; + +/* + * The minimum number of columns needed in the data file to satisfy the + * control string/input variable requirements. + */ static unsigned minimum_columns; + +/* + * The number of independent values we expect to keep based on the control + * string/independent variables. + */ static unsigned indep_values; + +/* + * The total number of independent columns to expect. This includes any + * ignored columns. + */ static unsigned indep_columns; + +/* + * The zero based dependent column location. This is just minimum_columns - 1. + */ static unsigned dep_column; + +/* + * The number of columns to expect in this data file. This must be + * greater than or equal to the minimum_columns above. + */ static unsigned number_of_columns = 0; + +/* + * The number of columns that this point currently has. + */ static unsigned cur_columns; + +/* + * The zero based current independent value we are looking for. + */ static unsigned cur_value; + +/* + * The usable values for this point. The independent values are first and + * the dependent value is the last entry. + */ static double *values; + +/* + * The name of the file we are getting data from. + */ static const char *in_file_name; + +/* + * The table structure that we are getting data for. + */ static p_table_mod table_def; +/* + * The lexor and error routines. + */ extern int tblmodlex(void); static void yyerror(const char *fmt, ...); +static void process_point() +{ + assert(cur_value == indep_values); + #if 0 + unsigned idx; + fprintf(stderr, "%#g", values[0]); + for (idx = 1; idx < indep_values; idx += 1) { + fprintf(stderr, ", %#g", values[idx]); + } + fprintf(stderr, " => %#g\n", values[indep_values]); + #endif +} + %} %locations @@ -52,19 +116,23 @@ static void yyerror(const char *fmt, ...); %% + /* + * A table is just a bunch of points. The lexor ignores any comments. + */ table : point | table point + /* + * An individual point is just a bunch of columns followed by one or more + * end of line characters. + */ point : columns END_LINE { - #if 0 - unsigned idx; - fprintf(stderr, "%#g", values[0]); - for (idx = 1; idx < indep_values; idx += 1) { - fprintf(stderr, ", %#g", values[idx]); - } - fprintf(stderr, " => %#g\n", values[indep_values]); - #endif + /* + * If the number of columns has been defined then we must have + * enough columns and we expect every line to have the same + * number of columns. + */ if (number_of_columns) { if (cur_columns < minimum_columns) { yyerror("Found %u columns, need at least %u.", @@ -72,15 +140,26 @@ point : columns END_LINE } else if (cur_columns != number_of_columns) { yyerror("Found %u columns, expected %u.", cur_columns, number_of_columns); - } + } else process_point(); + /* + * If this is the first point then we must have enough columns. + * If there are enough then we define this to be the number of + * columns that the file must have. + */ } else { if (cur_columns < minimum_columns) { yyerror("Found %u columns, need at least %u.", cur_columns, minimum_columns); - } else number_of_columns = cur_columns; + } else { + number_of_columns = cur_columns; + process_point(); + } } } + /* + * Each column is a real value. We only save the columns we care about. + */ columns : REAL { if (table_def->control.info.interp[0] != IVL_IGNORE_COLUMN) { @@ -103,12 +182,17 @@ columns : REAL %% +/* + * Setup the various variables, then parse the input file and then cleanup + * the lexor and the allocated memory. + */ unsigned parse_table_model(FILE *fp, vpiHandle callh, p_table_mod table) { unsigned rtn = 0; assert(table); assert(table->fields > 0); assert(table->depend > 0); + /* Initialize the variables used by the parser. */ table_def = table; indep_values = table->dims; indep_columns = table->fields; @@ -117,7 +201,9 @@ unsigned parse_table_model(FILE *fp, vpiHandle callh, p_table_mod table) values = malloc(sizeof(double)*(indep_values+1)); assert(values); in_file_name = table->file.name; + /* Parse the input file. */ init_tblmod_lexor(fp); + /* If there are errors then print a message. */ if (yyparse()) errors += 1; if (errors) { vpi_printf("ERROR: %s:%u: ", vpi_get_str(vpiFile, callh), @@ -125,14 +211,15 @@ unsigned parse_table_model(FILE *fp, vpiHandle callh, p_table_mod table) vpi_printf("Had %u error(s) while reading table file.\n", errors); rtn = 1; } + /* Cleanup the lexor and allocated memory. */ destroy_tblmod_lexor(); free(values); return rtn; } /* - * Because every parse error is reported after the newline subtract one from - * the line count. + * Currently every parse error is reported after the newline so subtract + * one from the line count. */ void yyerror(const char *fmt, ...) {