diff --git a/src/xspice/cmpp/Makefile.am b/src/xspice/cmpp/Makefile.am index c5fce8cc3..c858a3348 100644 --- a/src/xspice/cmpp/Makefile.am +++ b/src/xspice/cmpp/Makefile.am @@ -11,7 +11,7 @@ bin_PROGRAMS = cmpp AM_CPPFLAGS = -I. -I$(srcdir) AM_YFLAGS = -d -cmpp_SOURCES = main.c cmpp.h \ +cmpp_SOURCES = main.c cmpp.h file_buffer.c file_buffer.h\ pp_ifs.c pp_lst.c pp_mod.c read_ifs.c writ_ifs.c util.c \ ifs_lex.l ifs_yacc.y ifs_yacc_y.h \ mod_lex.l mod_yacc.y mod_yacc_y.h @@ -42,7 +42,7 @@ if CROSS_COMPILING BUILT_SOURCES += build/cmpp$(BUILD_EXEEXT) CLEANFILES = build/cmpp$(BUILD_EXEEXT) -BUILD_CMPP_FILES = main.c \ +BUILD_CMPP_FILES = main.c file_buffer.c \ pp_ifs.c pp_lst.c pp_mod.c read_ifs.c writ_ifs.c util.c \ ifs_lex.c ifs_yacc.c \ mod_lex.c mod_yacc.c diff --git a/src/xspice/cmpp/cmpp.h b/src/xspice/cmpp/cmpp.h index e719fa850..27e713ab7 100644 --- a/src/xspice/cmpp/cmpp.h +++ b/src/xspice/cmpp/cmpp.h @@ -38,6 +38,7 @@ NON-STANDARD FEATURES ============================================================================*/ +#include #include #include @@ -49,20 +50,25 @@ NON-STANDARD FEATURES #ifdef _MSC_VER #include #include + +/* If CRT debugging is being used so that crtdbg.h is included, strdup will + * be defined to a debug version. In this case, strdup should not be + * redefined to the standard version. */ +#ifndef strdup #define strdup _strdup +#endif + #define unlink _unlink #define isatty _isatty #define fileno _fileno -#endif +#endif /* _MSC_VER */ /* *********************************************************************** */ #define GET_IFS_TABLE 0 /* Read the entire ifs table */ #define GET_IFS_NAME 1 /* Get the C function name out of the table only */ -#define MAX_PATH_LEN 1024 /* Maximum pathname length */ #define MAX_NAME_LEN 1024 /* Maximum SPICE name length */ -#define MAX_FN_LEN 31 /* Maximum filename length */ /* ******************************************************************** */ @@ -262,7 +268,9 @@ void preprocess_ifs_file(void); void preprocess_lst_files(void); -void preprocess_mod_file(char *filename); +void preprocess_mod_file(const char *filename); + +int output_paths_from_lst_file(const char *filename); void init_error (char *program_name); @@ -272,6 +280,7 @@ void print_error(const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2) #else void print_error(const char *fmt, ...); #endif +void vprint_error(const char *fmt, va_list p); void str_to_lower(char *s); @@ -281,7 +290,7 @@ int read_ifs_file(const char *filename, int mode, Ifs_Table_t *ifs_table); int write_ifs_c_file(const char *filename, Ifs_Table_t *ifs_table); -FILE *fopen_cmpp(const char **path_p, const char *mode); +char *gen_filename(const char *filename, const char *mode); void rem_ifs_table(Ifs_Table_t *ifs_table); diff --git a/src/xspice/cmpp/main.c b/src/xspice/cmpp/main.c index 94ad9fff5..d49f30f77 100644 --- a/src/xspice/cmpp/main.c +++ b/src/xspice/cmpp/main.c @@ -35,25 +35,37 @@ REFERENCED FILES NON-STANDARD FEATURES None. - ============================================================================*/ +#ifdef DEBUG_CMPP +#ifdef _WIN32 +#include +#endif +#endif #include #include #include + #include "cmpp.h" -#define USAGE_MSG "Usage: cmpp [-ifs] [-mod []] [-lst]" +#define USAGE_MSG \ + "Usage: cmpp [-ifs] | [-mod []] | [-lst] | [-p fn.lst]" #define TOO_FEW_ARGS "ERROR - Too few arguments" #define TOO_MANY_ARGS "ERROR - Too many arguments" #define UNRECOGNIZED_ARGS "ERROR - Unrecognized argument" +#ifdef DEBUG_CMPP +#define PRINT_CMPP_INFO(argc, argv) print_cmpp_info(argc, argv); +static void print_cmpp_info(int argc, char **argv); +#else +#define PRINT_CMPP_INFO(argc, argv) +#endif + + /* *********************************************************************** */ - - /* main @@ -61,9 +73,11 @@ Function main checks the validity of the command-line arguments supplied when the program is invoked and calls one of the three major functions as appropriate: - preprocess_ifs_file Process Interface Specification File. - preprocess_mod_file Process Model Definition File. - preprocess_lst_file Process Pathname List Files. + preprocess_ifs_file Process Interface Specification File. + preprocess_mod_file Process Model Definition File. + preprocess_lst_file Process Pathname List Files. + output_paths_from_lst_file Write paths from a list file to stdout + to facilite building the code models depending on the argument. */ @@ -72,11 +86,11 @@ int main( int argc, /* Number of command line arguments */ char *argv[]) /* Command line argument text */ { - init_error (argv[0]); - /* Process command line arguments and vector to appropriate function */ + PRINT_CMPP_INFO(argc, argv) + /* Process command line arguments and vector to appropriate function */ if(argc < 2) { print_error(TOO_FEW_ARGS); print_error(USAGE_MSG); @@ -115,6 +129,26 @@ int main( print_error(USAGE_MSG); exit(1); } + } + else if (strcmp(argv[1],"-p") == 0) { /* Output paths from a list file */ + if (argc == 3) { + const int n_item = output_paths_from_lst_file(argv[2]); + if (n_item < 0) { + print_error("Unable to print paths to stdout"); + exit(-1); + } + exit(n_item); + } + else { /* Wrong number of arguments */ + if (argc < 3) { + print_error(TOO_FEW_ARGS); + } + else { + print_error(TOO_MANY_ARGS); + } + print_error(USAGE_MSG); + exit(1); + } } else { print_error(UNRECOGNIZED_ARGS); @@ -123,5 +157,67 @@ int main( } exit(0); -} +} /* end of function main */ + + + +#ifdef DEBUG_CMPP +/* Print some debugging information for cmpp + * + * With the use of environment variables to locate files, it is helpful + * to know some information about the program when debugging. If the + * build of a code model fails due to cmpp, the macro can be enabled to + * find the information needed to separately debug cmpp */ +static void print_cmpp_info(int argc, char **argv) +{ + /* Print the program and its arguments */ + { + int i; + for (i = 0; i < argc; ++i) { + (void) fprintf(stdout, "%s ", argv[i]); + } + (void) fprintf(stdout, "\n"); + } + +#ifdef _WIN32 + /* Print the current directory */ + { + const DWORD n_char = GetCurrentDirectoryA(0, (char *) NULL); + if (n_char > 0) { + char *p_buf = (char *) malloc(n_char); + if (p_buf != (char *) NULL) { + if (GetCurrentDirectoryA(n_char, p_buf) != 0) { + (void) fprintf(stdout, "Current Directory: \"%s\".\n", + p_buf); + } + free(p_buf); + } + } + } +#endif + + /* Print the CMPP_IDIR environment variable if defined */ + { + const char * const ev = getenv("CMPP_IDIR"); + if (ev) { + (void) fprintf(stdout, "CMPP_IDIR = \"%s\"\n", ev); + } + else { + (void) fprintf(stdout, "CMPP_IDIR is not defined\n"); + } + } + + /* Print the CMPP_ODIR environment variable if defined */ + { + const char * const ev = getenv("CMPP_ODIR"); + if (ev) { + (void) fprintf(stdout, "CMPP_ODIR = \"%s\"\n", ev); + } + else { + (void) fprintf(stdout, "CMPP_ODIR is not defined\n"); + } + } +} /* end of function print_cmpp_info */ +#endif /* #ifdef DEBUG_CMPP */ + diff --git a/src/xspice/cmpp/pp_ifs.c b/src/xspice/cmpp/pp_ifs.c index ce840b0c4..830633fef 100644 --- a/src/xspice/cmpp/pp_ifs.c +++ b/src/xspice/cmpp/pp_ifs.c @@ -42,14 +42,6 @@ NON-STANDARD FEATURES -/* *********************************************************************** */ - -static void txfree(void *ptr) -{ - if(ptr) - free(ptr); -}; - /* preprocess_ifs_file @@ -91,30 +83,51 @@ void preprocess_ifs_file(void) void rem_ifs_table(Ifs_Table_t *ifs_table) { - int i; /* Remove the ifs_table */ - txfree(ifs_table->name.c_fcn_name); - txfree(ifs_table->name.description); - txfree(ifs_table->name.model_name); + free(ifs_table->name.c_fcn_name); + free(ifs_table->name.description); + free(ifs_table->name.model_name); - for(i = 0; i < ifs_table->num_conn; i++) { - txfree(ifs_table->conn[i].name); - txfree(ifs_table->conn[i].description); - txfree(ifs_table->conn[i].default_type); + { + Conn_Info_t * const p_conn = ifs_table->conn; + const int num_conn = ifs_table->num_conn; + int i; + for (i = 0; i < num_conn; ++i) { + Conn_Info_t *p_conn_cur = p_conn + i; + free(p_conn_cur->name); + free(p_conn_cur->description); + free(p_conn_cur->default_type); + } } - for(i = 0; i < ifs_table->num_param; i++) { - txfree(ifs_table->param[i].name); - txfree(ifs_table->param[i].description); + { + Param_Info_t * const p_param = ifs_table->param; + const int num_param = ifs_table->num_param; + int i; + for (i = 0; i < num_param; ++i) { + Param_Info_t *p_param_cur = p_param + i; + free(p_param_cur->name); + free(p_param_cur->description); + } } - for(i = 0; i < ifs_table->num_inst_var; i++) { - txfree(ifs_table->inst_var[i].name); - txfree(ifs_table->inst_var[i].description); + + { + Inst_Var_Info_t * const p_inst_var = ifs_table->inst_var; + const int num_inst_var = ifs_table->num_inst_var; + int i; + for(i = 0; i < num_inst_var; ++i) { + Inst_Var_Info_t *p_inst_var_cur = p_inst_var + i; + free(p_inst_var_cur->name); + free(p_inst_var_cur->description); + } } - txfree(ifs_table->conn); - txfree(ifs_table->param); - txfree(ifs_table->inst_var); -} + + free(ifs_table->conn); + free(ifs_table->param); + free(ifs_table->inst_var); +} /* end of function rem_ifs_table */ + + diff --git a/src/xspice/cmpp/pp_lst.c b/src/xspice/cmpp/pp_lst.c index 01a624a3a..3d321a396 100644 --- a/src/xspice/cmpp/pp_lst.c +++ b/src/xspice/cmpp/pp_lst.c @@ -47,11 +47,15 @@ NON-STANDARD FEATURES ============================================================================*/ -#include "cmpp.h" #include +#include +#include +#include #include #include +#include "cmpp.h" +#include "file_buffer.h" /* *********************************************************************** */ @@ -63,34 +67,56 @@ typedef struct { char *path_name; /* Pathname read from model path file */ char *spice_name; /* Name of model from ifspec.ifs */ char *cfunc_name; /* Name of C fcn from ifspec.ifs */ - bool spice_unique; /* True if spice name unique */ - bool cfunc_unique; /* True if C fcn name unique */ + unsigned int version; /* version of the code model */ } Model_Info_t; typedef struct { char *path_name; /* Pathname read from udn path file */ char *node_name; /* Name of node type */ - bool unique; /* True if node type name unique */ + unsigned int version; /* version of the code model */ } Node_Info_t; - -/* *********************************************************************** */ +/* Structure for uniqueness testing */ +struct Key_src { + const char *key; /* value to compare */ + const char *src; /* source of value */ +}; + + + +/************************************************************************ */ + +static int cmpr_ks(const struct Key_src *ks1, const struct Key_src *ks2); +static void free_model_info(int num_models, Model_Info_t *p_model_info); +static void free_node_info(int num_nodes, Node_Info_t *p_node_info); static int read_modpath(int *num_models, Model_Info_t **model_info); static int read_udnpath(int *num_nodes, Node_Info_t **node_info); static int read_model_names(int num_models, Model_Info_t *model_info); static int read_node_names(int num_nodes, Node_Info_t *node_info); static int check_uniqueness(int num_models, Model_Info_t *model_info, - int num_nodes, Node_Info_t *node_info); + int num_nodes, Node_Info_t *node_info); +static void report_error_spice_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static void report_error_function_name (const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static void report_error_udn_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static bool test_for_duplicates(unsigned int n, struct Key_src *p_ks, + void (*p_error_reporter)(const struct Key_src *p_ks1, + const struct Key_src *p_ks2)); +static inline void trim_slash(size_t *p_n, char *p); static int write_CMextrn(int num_models, Model_Info_t *model_info); static int write_CMinfo(int num_models, Model_Info_t *model_info); +static int write_CMinfo2(int num_models, Model_Info_t *model_info); static int write_UDNextrn(int num_nodes, Node_Info_t *node_info); static int write_UDNinfo(int num_nodes, Node_Info_t *node_info); +static int write_UDNinfo2(int num_nodes, Node_Info_t *node_info); static int write_objects_inc(int num_models, Model_Info_t *model_info, - int num_nodes, Node_Info_t *node_info); + int num_nodes, Node_Info_t *node_info); static int read_udn_type_name(const char *path, char **node_name); @@ -101,7 +127,7 @@ static int read_udn_type_name(const char *path, char **node_name); preprocess_lst_files Function preprocess_lst_files is the top-level driver function for -preprocessing a simulator model path list file (modpath.lst). +preprocessing a simulator model path list file (modpath.lst). This function calls read_ifs_file() requesting it to read and parse the Interface Specification file (ifspec.ifs) to extract the model name and associated C function name and place this @@ -125,20 +151,18 @@ void preprocess_lst_files(void) int num_models; /* The number of models */ int num_nodes; /* The number of user-defined nodes */ - /* Get list of models from model pathname file */ status = read_modpath(&num_models, &model_info); - if(status != 0) { + if (status != 0) { exit(1); } /* Get list of node types from udn pathname file */ status = read_udnpath(&num_nodes, &node_info); - if(status != 0) { + if (status < 0) { exit(1); } - /* Get the spice and C function names from the ifspec.ifs files */ status = read_model_names(num_models, model_info); if(status != 0) { @@ -151,15 +175,12 @@ void preprocess_lst_files(void) exit(1); } - /* Check to be sure the names are unique */ - status = check_uniqueness(num_models, model_info, - num_nodes, node_info); + status = check_uniqueness(num_models, model_info, num_nodes, node_info); if(status != 0) { exit(1); } - /* Write out the CMextrn.h file used to compile SPIinit.c */ status = write_CMextrn(num_models, model_info); if(status != 0) { @@ -171,7 +192,10 @@ void preprocess_lst_files(void) if(status != 0) { exit(1); } - + status = write_CMinfo2(num_models, model_info); + if(status != 0) { + exit(1); + } /* Write out the UDNextrn.h file used to compile SPIinit.c */ status = write_UDNextrn(num_nodes, node_info); @@ -184,7 +208,10 @@ void preprocess_lst_files(void) if(status != 0) { exit(1); } - + status = write_UDNinfo2(num_nodes, node_info); + if(status != 0) { + exit(1); + } /* Write the make_include file used to link the models and */ /* user-defined node functions with the simulator */ @@ -193,17 +220,107 @@ void preprocess_lst_files(void) if(status != 0) { exit(1); } - /* remove model_info and node_info */ - if (model_info) { - if(model_info->cfunc_name) free(model_info->cfunc_name); - if(model_info->path_name) free(model_info->path_name); - if(model_info->spice_name) free(model_info->spice_name); + + /* Free allocations */ + if (model_info != (Model_Info_t *) NULL) { + free_model_info(num_models, model_info); } - if (node_info) { - if(node_info->node_name) free(node_info->node_name); - if(node_info->path_name) free(node_info->path_name); + if (node_info != (Node_Info_t *) NULL) { + free_node_info(num_nodes, node_info); } -} +} /* end of function preprocess_lst_files */ + + + +/* This function parses the supplied .lst file and outputs the paths to + * stdout */ +int output_paths_from_lst_file(const char *filename) +{ + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* for reading MODPATH_FILENAME */ + unsigned int n_path = 0; + + /* Open the file */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("ERROR - Unable to open file \"%s\" to obtain " + "paths: %s", + filename, strerror(errno)); + xrc = -1; + goto EXITPOINT; + } + + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + + /* Output the file that was found */ + if (fprintf(stdout, "%s\n", fbobj.str_value.sz) < 0) { + print_error("ERROR - Unable to output path name to stdout: %s", + strerror(errno)); + xrc = -1; + goto EXITPOINT; + } + ++n_path; /* 1 more path printed OK */ + + /* Try getting a version. If found, it will be discarded */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with path names: %s", + strerror(errno)); + xrc = -1; + } + + /* Return the path count if no errors */ + if (xrc == 0) { + xrc = (int) n_path; + } + + return xrc; +} /* end of function output_paths_from_lst_file */ + @@ -218,108 +335,169 @@ file, and puts them into an internal data structure for future processing. */ +/* Structure for retrieving data items from the file. These will be either + * names, such as directory names or unsigned integers that are version + * numbers */ +#define N_MODEL_INIT 10 static int read_modpath( - int *num_models, /* Number of model pathnames found */ - Model_Info_t **model_info /* Info about each model */ -) + int *p_num_model_info, /* Number of model pathnames found */ + Model_Info_t **pp_model_info) /* Info about each model */ { - FILE *fp; /* Model pathname file pointer */ - char path[MAX_PATH_LEN+2]; /* space to read pathnames into */ - Model_Info_t *model = NULL; /* temporary pointer to model info */ - - int n; - int i; - int j; - int len; - int line_num; - - const char *filename = MODPATH_FILENAME; - - - /* Initialize number of models to zero in case of error */ - *num_models = 0; + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* for reading MODPATH_FILENAME */ + Model_Info_t *p_model_info = (Model_Info_t *) NULL; + unsigned int n_model_info = 0; + unsigned int n_model_info_alloc = 0; + char *filename = (char *) NULL; /* Open the model pathname file */ - fp = fopen_cmpp(&filename, "r"); - - if (fp == NULL) { - print_error("ERROR - File not found: %s", filename); - return -1; + if ((filename = gen_filename(MODPATH_FILENAME, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build mod path file name"); + xrc = -1; + goto EXITPOINT; + } + /* Open the file using the default buffer size. For debugging, a very + * small value can be used, for example by giving the size as 1, to + * force the function do actions that otherwise would be done rarely + * if at all. */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("ERROR - Unable to open mod path file \"%s\": %s", + filename, strerror(errno)); + xrc = -1; + goto EXITPOINT; } - /* Read the pathnames from the file, one line at a time until EOF */ - n = 0; - line_num = 0; - while( fgets(path, sizeof(path), fp) ) { + /* Allocate initial model info array */ + if ((p_model_info = (Model_Info_t *) malloc(N_MODEL_INIT * + sizeof(Model_Info_t))) == (Model_Info_t *) NULL) { + print_error("ERROR - Unable to allocate initial model array"); + xrc = -1; + goto EXITPOINT; + } + n_model_info_alloc = N_MODEL_INIT; - line_num++; - len = (int) strlen(path); + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ - /* If line was too long for buffer, exit with error */ - if(len > MAX_PATH_LEN) { - print_error("ERROR - Line %d of %s exceeds %d characters", - line_num, filename, MAX_PATH_LEN); - return -1; + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); } - /* Strip white space including newline */ - for(i = 0, j = 0; i < len; ) { - if(isspace_c(path[i])) { - i++; - } - else { - path[j] = path[i]; - i++; - j++; + /* Enlarge model array if full */ + if (n_model_info_alloc == n_model_info) { + n_model_info_alloc *= 2; + void * const p = realloc(p_model_info, + n_model_info_alloc * sizeof(Model_Info_t)); + if (p == NULL) { + print_error("ERROR - Unable to enlarge model array"); + xrc = -1; + goto EXITPOINT; } + p_model_info = (Model_Info_t *) p; } - path[j] = '\0'; - len = j; - - /* Strip trailing '/' if any */ - if(path[len - 1] == '/') - path[--len] = '\0'; - - /* If blank line, continue */ - if(len == 0) - continue; - - /* Make sure pathname is short enough to add a filename at the end */ - if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) { - print_error("ERROR - Pathname on line %d of %s exceeds %d characters", - line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1))); - return -1; - } - - /* Allocate and initialize a new model info structure */ - if(n == 0) - model = (Model_Info_t *) malloc(sizeof(Model_Info_t)); - else - model = (Model_Info_t *) realloc(model, (size_t) (n + 1) * sizeof(Model_Info_t)); - model[n].path_name = NULL; - model[n].spice_name = NULL; - model[n].cfunc_name = NULL; - model[n].spice_unique = true; - model[n].cfunc_unique = true; /* Put pathname into info structure */ - model[n].path_name = (char *) malloc((size_t) (len+1)); - strcpy(model[n].path_name, path); + Model_Info_t * const p_model_info_cur = p_model_info + + n_model_info; - /* Increment count of paths read */ - n++; + if ((p_model_info_cur->path_name = (char *) malloc( + fbobj.str_value.n_char + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate path name"); + xrc = -1; + goto EXITPOINT; + } + + strcpy(p_model_info_cur->path_name, fbobj.str_value.sz); + p_model_info_cur->spice_name = (char *) NULL; + p_model_info_cur->cfunc_name = (char *) NULL; + + /* Must set before returning due to EOF. */ + p_model_info_cur->version = 1; + ++n_model_info; + + /* Try getting a version */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + p_model_info_cur->version = (unsigned int) fbobj.ulong_value; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with model info: %s", + strerror(errno)); + xrc = -1; } + /* Free name of file being used */ + if (filename) { + free((void *) filename); + } - /* Close model pathname file and return data read */ - fclose(fp); + /* If error, free model info */ + if (xrc != 0) { + free_model_info(n_model_info, p_model_info); + n_model_info = 0; + p_model_info = (Model_Info_t *) NULL; + } - *num_models = n; - *model_info = model; + *p_num_model_info = n_model_info; + *pp_model_info = p_model_info; + + return xrc; +} /* end of function read_modpath */ + + + +/* Remove slash at end of path name if present */ +static inline void trim_slash(size_t *p_n, char *p) +{ + size_t n = *p_n; + if (n > 1) { + char * const p_last = p + n - 1; + if (*p_last == '/') { + *p_last = '\0'; + --*p_n; + } + } +} /* end of function trim_slash */ - return 0; -} /* *********************************************************************** */ @@ -334,106 +512,153 @@ processing. */ +#define N_NODE_INIT 5 + static int read_udnpath( - int *num_nodes, /* Number of node pathnames found */ - Node_Info_t **node_info /* Info about each node */ + int *p_num_node_info, /* Addr to receive # node pathnames */ + Node_Info_t **pp_node_info /* Addr to receive node info */ ) { - FILE *fp; /* Udn pathname file pointer */ - char path[MAX_PATH_LEN+2]; /* space to read pathnames into */ - Node_Info_t *node = NULL; /* temporary pointer to node info */ + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* For reading Udn pathname */ + Node_Info_t *p_node_info = (Node_Info_t *) NULL; + /* array of node info */ + unsigned int n_node_info = 0; + unsigned int n_node_info_alloc = 0; + char *filename = (char *) NULL; - int n; - int i; - int j; - int len; - int line_num; - - const char *filename = UDNPATH_FILENAME; - - - /* Initialize number of nodes to zero in case of error */ - *num_nodes = 0; /* Open the node pathname file */ - fp = fopen_cmpp(&filename, "r"); - - /* For backward compatibility, return with WARNING only if file not found */ - if(fp == NULL) { - print_error("WARNING - File not found: %s", filename); - return 0; + if ((filename = gen_filename(UDNPATH_FILENAME, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build udn path file name"); + xrc = -1; + goto EXITPOINT; } - /* Read the pathnames from the file, one line at a time until EOF */ - n = 0; - line_num = 0; - while( fgets(path, sizeof(path), fp) ) { + /* For backward compatibility, return with WARNING only if file + * not found */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("WARNING - File not found: %s", filename); + xrc = +1; + goto EXITPOINT; + } - line_num++; - len = (int) strlen(path); + /* Allocate initial node info array */ + if ((p_node_info = (Node_Info_t *) malloc(N_NODE_INIT * + sizeof(Node_Info_t))) == (Node_Info_t *) NULL) { + print_error("ERROR - Unable to allocate initial node array"); + xrc = -1; + goto EXITPOINT; + } + n_node_info_alloc = N_NODE_INIT; - /* If line was too long for buffer, exit with error */ - if(len > MAX_PATH_LEN) { - print_error("ERROR - Line %d of %s exceeds %d characters", - line_num, filename, MAX_PATH_LEN); - return -1; + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); } - /* Strip white space including newline */ - for(i = 0, j = 0; i < len; ) { - if(isspace_c(path[i])) { - i++; - } - else { - path[j] = path[i]; - i++; - j++; + + /* Enlarge node array if full */ + if (n_node_info_alloc == n_node_info) { + n_node_info_alloc *= 2; + void * const p = realloc(p_node_info, + n_node_info_alloc * sizeof(Node_Info_t)); + if (p == NULL) { + print_error("ERROR - Unable to enlarge node array"); + xrc = -1; + goto EXITPOINT; } + p_node_info = (Node_Info_t *) p; } - path[j] = '\0'; - len = j; - - /* Strip trailing '/' if any */ - if(path[len - 1] == '/') - path[--len] = '\0'; - - /* If blank line, continue */ - if(len == 0) - continue; - - /* Make sure pathname is short enough to add a filename at the end */ - if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) { - print_error("ERROR - Pathname on line %d of %s exceeds %d characters", - line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1))); - return -1; - } - - /* Allocate and initialize a new node info structure */ - if(n == 0) - node = (Node_Info_t *) malloc(sizeof(Node_Info_t)); - else - node = (Node_Info_t *) realloc(node, (size_t) (n + 1) * sizeof(Node_Info_t)); - node[n].path_name = NULL; - node[n].node_name = NULL; - node[n].unique = true; /* Put pathname into info structure */ - node[n].path_name = (char *) malloc((size_t) (len+1)); - strcpy(node[n].path_name, path); + Node_Info_t * const p_node_info_cur = p_node_info + + n_node_info; - /* Increment count of paths read */ - n++; + if ((p_node_info_cur->path_name = (char *) malloc( + fbobj.str_value.n_char + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate path name"); + xrc = -1; + goto EXITPOINT; + } + + strcpy(p_node_info_cur->path_name, fbobj.str_value.sz); + p_node_info_cur->node_name = NULL; + + /* Must set before returning due to EOF. */ + p_node_info_cur->version = 1; + ++n_node_info; + + /* Try getting a version */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + p_node_info_cur->version = (unsigned int) fbobj.ulong_value; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with node info: %s", + strerror(errno)); + xrc = -1; } + /* Free name of file being used */ + if (filename) { + free((void *) filename); + } - /* Close node pathname file and return data read */ - fclose(fp); + /* If error, free node info */ + if (xrc != 0) { + free_node_info(n_node_info, p_node_info); + n_node_info = 0; + p_node_info = (Node_Info_t *) NULL; + } - *num_nodes = n; - *node_info = node; + *p_num_node_info = n_node_info; + *pp_node_info = p_node_info; - return 0; -} + return xrc; +} /* end of function read_udnpath */ @@ -452,47 +677,109 @@ static int read_model_names( Model_Info_t *model_info /* Info about each model */ ) { - bool all_found; /* True if all ifspec files read */ - int i; /* A temporary counter */ - char path[MAX_PATH_LEN+1]; /* full pathname to ifspec file */ - int status; /* Return status */ - Ifs_Table_t ifs_table; /* Repository for info read from ifspec file */ + bool all_found = true; /* True if all ifspec files read */ + int i; /* A temporary counter */ + char path_stack[100]; /* full pathname to ifspec file if from stack */ + char *path = path_stack; /* actual path buffer */ + int status; /* Return status */ + + /* Repository for info read from ifspec file.*/ + Ifs_Table_t ifs_table; + + /* Find the required buffer size and allocate if the default buffer + * on the stack is too small */ + { + int j; + size_t n_byte_needed = 0; + for (j = 0; j < num_models; j++) { /* max(model path lengths) */ + const size_t n = strlen(model_info[j].path_name); + if (n_byte_needed < n) { + n_byte_needed = n; + } + } + n_byte_needed += 1 + strlen(IFSPEC_FILENAME) + 1; + if (n_byte_needed > sizeof path_stack) { + if ((path = (char *) malloc(n_byte_needed)) == (char *) NULL) { + print_error("ERROR - Unable to allocate a buffer " + "for model paths"); + return -1; + } + } + } /* For each model found in model pathname file, read the interface */ /* spec file to get the SPICE and C function names into model_info */ + for(i = 0; i < num_models; i++) { + Model_Info_t *p_model_info_cur = model_info + i; - for(i = 0, all_found = true; i < num_models; i++) { + /* 0 for error recovery */ + (void) memset(&ifs_table, 0, sizeof ifs_table); - /* Form the full pathname to the interface spec file */ - strcpy(path, model_info[i].path_name); - strcat(path, "/"); - strcat(path, IFSPEC_FILENAME); + /* Form the full pathname to the interface spec file. Size has + * been checked to ensure that all strings will fit. */ + { + char *p_dst = path; + + /* Copy path name */ + const char *p_src = model_info[i].path_name; + for ( ; ; ) { + const char ch_cur = *p_src; + if (ch_cur == '\0') { + break; + } + *p_dst++ = ch_cur; + ++p_src; + } + *p_dst++ = '/'; /* add directory separator */ + strcpy(p_dst, IFSPEC_FILENAME); + } /* Read the SPICE and C function names from the interface spec file */ status = read_ifs_file(path, GET_IFS_NAME, &ifs_table); /* Transfer the names into the model_info structure */ - if(status == 0) { - model_info[i].spice_name = ifs_table.name.model_name; - model_info[i].cfunc_name = ifs_table.name.c_fcn_name; + if (status == 0) { + if ((p_model_info_cur->spice_name = strdup( + ifs_table.name.model_name)) == (char *) NULL) { + print_error("ERROR - Unable to copy code model name"); + all_found = false; + break; + } + if ((p_model_info_cur->cfunc_name = strdup( + ifs_table.name.c_fcn_name)) == (char *) NULL) { + print_error("ERROR - Unable to copy code model function name"); + all_found = false; + break; + } } else { + print_error( + "ERROR - Problems reading \"%s\" in directory \"%s\"", + IFSPEC_FILENAME, p_model_info_cur->path_name); all_found = false; - print_error("ERROR - Problems reading %s in directory %s", - IFSPEC_FILENAME, model_info[i].path_name); + break; } /* Remove the ifs_table */ rem_ifs_table(&ifs_table); + } /* end of loop over models */ + + /* Free buffer if allocated */ + if (path != path_stack) { + free(path); } - if(all_found) + if (all_found) { return 0; - else + } + else { + /* Free allocations of model when failure occurred */ + rem_ifs_table(&ifs_table); return -1; + } +} /* end of function read_model_names */ -} /* *********************************************************************** */ @@ -511,21 +798,57 @@ static int read_node_names( Node_Info_t *node_info /* Info about each node */ ) { - bool all_found; /* True if all files read OK */ - int i; /* A temporary counter */ - char path[MAX_PATH_LEN+1]; /* full pathname to file */ - int status; /* Return status */ + bool all_found = true; /* True if all ifspec files read */ + int i; /* A temporary counter */ + char path_stack[100]; /* full pathname to ifspec file if from stack */ + char *path = path_stack; /* actual path buffer */ + int status; /* Return status */ char *node_name; /* Name of node type read from file */ + /* Find the required buffer size and allocate if the default buffer + * on the stack is too small */ + { + int j; + size_t n_byte_needed = 0; + for (j = 0; j < num_nodes; j++) { /* max(model path lengths) */ + const size_t n = strlen(node_info[j].path_name); + if (n_byte_needed < n) { + n_byte_needed = n; + } + } + n_byte_needed += 1 + strlen(UDNFUNC_FILENAME) + 1; + if (n_byte_needed > sizeof path_stack) { + if ((path = (char *) malloc(n_byte_needed)) == (char *) NULL) { + print_error("ERROR - Unable to allocate a buffer " + "for user types"); + return -1; + } + } + } + + /* For each node found in node pathname file, read the udnfunc.c */ /* file to get the node type names into node_info */ for(i = 0, all_found = true; i < num_nodes; i++) { + /* Form the full pathname to the user-defined type file. Size has + * been checked to ensure that all strings will fit. */ + { + char *p_dst = path; - /* Form the full pathname to the interface spec file */ - strcpy(path, node_info[i].path_name); - strcat(path, "/"); - strcat(path, UDNFUNC_FILENAME); + /* Copy path name */ + const char *p_src = node_info[i].path_name; + for ( ; ; ) { + const char ch_cur = *p_src; + if (ch_cur == '\0') { + break; + } + *p_dst++ = ch_cur; + ++p_src; + } + *p_dst++ = '/'; /* add directory separator */ + strcpy(p_dst, UDNFUNC_FILENAME); + } /* Read the udn node type name from the file */ status = read_udn_type_name(path, &node_name); @@ -545,8 +868,7 @@ static int read_node_names( return 0; else return -1; - -} +} /* end of function read_node_names */ @@ -568,14 +890,11 @@ static int check_uniqueness( Node_Info_t *node_info /* Info about each node type */ ) { - int i; /* A temporary counter */ - int j; /* A temporary counter */ - bool all_unique; /* true if names are unique */ - /* Define a list of model names used internally by XSPICE */ /* These names (except 'poly') are defined in src/sim/INP/INPdomodel.c and */ /* are case insensitive */ - static char *SPICEmodel[] = { "npn", + static const char *SPICEmodel[] = { + "npn", "pnp", "d", "njf", @@ -590,13 +909,14 @@ static int check_uniqueness( "sw", "csw", "poly" }; - static int numSPICEmodels = sizeof(SPICEmodel) / sizeof(char *); + static const int numSPICEmodels = sizeof(SPICEmodel) / sizeof(char *); /* Define a list of node type names used internally by the simulator */ /* These names are defined in src/sim/include/MIFtypes.h and are case */ /* insensitive */ - static char *UDNidentifier[] = { "v", + static const char *UDNidentifier[] = { + "v", "vd", "i", "id", @@ -606,138 +926,220 @@ static int check_uniqueness( "h", "hd", "d" }; - static int numUDNidentifiers = sizeof(UDNidentifier) / sizeof(char *); - + static const int numUDNidentifiers = sizeof(UDNidentifier) / sizeof(char *); + bool f_have_duplicate = false; /* no duplicates found yet */ /* First, normalize case of all model and node names to lower since */ /* SPICE is case insensitive in parsing decks */ - for(i = 0; i < num_models; i++) - str_to_lower(model_info[i].spice_name); - for(i = 0; i < num_nodes; i++) - str_to_lower(node_info[i].node_name); - - /* Then, loop through all model names and report errors if same as SPICE */ - /* model name or same as another model name in list */ - for(i = 0, all_unique = true; i < num_models; i++) { - - /* First check against list of SPICE internal names */ - for(j = 0; j < numSPICEmodels; j++) { - if(strcmp(model_info[i].spice_name, SPICEmodel[j]) == 0) { - all_unique = false; - print_error("ERROR - Model name '%s' is same as internal SPICE model name\n", - model_info[i].spice_name); - } + { + int i; + for(i = 0; i < num_models; i++) { + str_to_lower(model_info[i].spice_name); } - - /* Skip if already seen once */ - if(model_info[i].spice_unique == false) - continue; - - /* Then check against other names in list */ - for(j = 0; j < num_models; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(model_info[i].spice_name, model_info[j].spice_name) == 0) { - all_unique = false; - model_info[i].spice_unique = false; - model_info[j].spice_unique = false; - print_error("ERROR - Model name '%s' in directory: %s", - model_info[i].spice_name, - model_info[i].path_name); - print_error(" is same as"); - print_error(" model name '%s' in directory: %s\n", - model_info[j].spice_name, - model_info[j].path_name); - } - } - } - - /* Loop through all C function names and report errors if duplicates found */ - for(i = 0; i < num_models; i++) { - - /* Skip if already seen once */ - if(model_info[i].cfunc_unique == false) - continue; - - /* Check against other names in list only, not against SPICE identifiers */ - /* Let linker catch collisions with SPICE identifiers for now */ - for(j = 0; j < num_models; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(model_info[i].cfunc_name, model_info[j].cfunc_name) == 0) { - all_unique = false; - model_info[i].cfunc_unique = false; - model_info[j].cfunc_unique = false; - print_error("ERROR - C function name '%s' in directory: %s", - model_info[i].cfunc_name, - model_info[i].path_name); - print_error(" is same as"); - print_error(" C function name '%s' in directory: %s\n", - model_info[j].cfunc_name, - model_info[j].path_name); - } - } - - } - - /* Loop through all node type names and report errors if same as internal */ - /* name or same as another name in list */ - for(i = 0; i < num_nodes; i++) { - - /* First check against list of internal names */ - for(j = 0; j < numUDNidentifiers; j++) { - if(strcmp(node_info[i].node_name, UDNidentifier[j]) == 0) { - all_unique = false; - print_error("ERROR - Node type '%s' is same as internal node type\n", - node_info[i].node_name); - } - } - - /* Skip if already seen once */ - if(node_info[i].unique == false) - continue; - - /* Then check against other names in list */ - for(j = 0; j < num_nodes; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(node_info[i].node_name, node_info[j].node_name) == 0) { - all_unique = false; - node_info[i].unique = false; - node_info[j].unique = false; - print_error("ERROR - Node type '%s' in directory: %s", - node_info[i].node_name, - node_info[i].path_name); - print_error(" is same as"); - print_error(" node type '%s' in directory: %s\n", - node_info[j].node_name, - node_info[j].path_name); - } + { + int i; + for(i = 0; i < num_nodes; i++) { + str_to_lower(node_info[i].node_name); } } + /* Sizes of models and nodes */ + const unsigned int n_model = (unsigned int) numSPICEmodels + num_models; + const unsigned int n_node = (unsigned int) numUDNidentifiers + num_nodes; + const unsigned int n_ks = n_model > n_node ? n_model : n_node; + + /* Allocate structure to compare */ + struct Key_src * const p_ks = (struct Key_src *) malloc( + n_ks * sizeof *p_ks); + if (p_ks == (struct Key_src *) NULL) { + print_error("ERROR - Unable to allocate array to check uniqueness."); + return -1; + } + + /* Set up for test of SPICE name of models and test */ + if (num_models > 0) { /* Have user-defined models */ + { + int i, j; + + /* Fill up with SPICE models */ + for (i = 0; i < numSPICEmodels; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + p_ks_cur->key = SPICEmodel[i]; + p_ks_cur->src = (char *) NULL; /* denotes internal SPICE */ + } + /* Add SPICE model names for code models */ + for (j = 0; j < num_models; ++i, ++j) { + struct Key_src *p_ks_cur = p_ks + i; + Model_Info_t *p_mi_cur = model_info + j; + p_ks_cur->key = p_mi_cur->spice_name; + p_ks_cur->src = p_mi_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(n_model, p_ks, + &report_error_spice_name); + } + + /* Set up for test of function names */ + { + int i; + + /* Fill up with C function names from code models */ + for (i = 0; i < num_models; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + Model_Info_t *p_mi_cur = model_info + i; + p_ks_cur->key = p_mi_cur->cfunc_name; + p_ks_cur->src = p_mi_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(num_models, p_ks, + &report_error_function_name); + } + } + + /* Set up for test of node types and test */ + if (num_nodes > 0) { /* Have user-defined types */ + int i, j; + + /* Fill up with SPICE node types */ + for (i = 0; i < numUDNidentifiers; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + p_ks_cur->key = UDNidentifier[i]; + p_ks_cur->src = (char *) NULL; /* denotes internal SPICE */ + } + /* Add user-defined nodes */ + for (j = 0; j < num_nodes; ++i, ++j) { + struct Key_src *p_ks_cur = p_ks + i; + Node_Info_t *p_ni_cur = node_info + j; + p_ks_cur->key = p_ni_cur->node_name; + p_ks_cur->src = p_ni_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(n_node, p_ks, + &report_error_udn_name); + } + + /* Free allocation for compares */ + free(p_ks); /* Return error status */ - if(all_unique) - return 0; - else - return -1; + return f_have_duplicate ? -1 : 0; +} /* end of function check_uniqueness */ + + + +/* Test for duplicate key values and report using the supplied function + * if found */ +static bool test_for_duplicates(unsigned int n, struct Key_src *p_ks, + void (*p_error_reporter)(const struct Key_src *p_ks1, + const struct Key_src *p_ks2)) +{ + bool f_have_duplicate = false; + + /* Sort to put duplicates together */ + qsort(p_ks, n, sizeof(struct Key_src), + (int (*)(const void *, const void *)) &cmpr_ks); + + unsigned int i; + for (i = 0; i != n; ) { + const struct Key_src * const p_ks_i = p_ks + i; + const char * const p_key_i_val = p_ks_i->key; + unsigned int j; + for (j = i + 1; j != n; ++j) { + const struct Key_src * const p_ks_j = p_ks + j; + const char * const p_key_j_val = p_ks_j->key; + if (strcmp(p_key_i_val, p_key_j_val) != 0) { + break; + } + + /* Duplicate found. Indicate a duplicate was found and report + * the error */ + f_have_duplicate = true; + (*p_error_reporter)(p_ks_i, p_ks_j); + } /* end of loop testing for duplicates */ + i = j; /* advance to next unique value or end of list */ + } /* end of loop over items to test */ + return f_have_duplicate; +} /* end of function test_for_duplicates */ + + + +/* Compare function for struct Key_src. + * + * Remarks + * the src field may be NULL to indicate internal values. These should + * be ordered before values that are not NULL for nicer error messages. + * Note that for a given key, only one src field can be NULL. */ +static int cmpr_ks(const struct Key_src *ks1, const struct Key_src *ks2) +{ + /* First order by the value of the key */ + const int rc = strcmp(ks1->key, ks2->key); + if (rc != 0) { + return rc; + } + + /* Test for NULL src fields. Only one can be NULL for the same key */ + if (ks1->src == (char *) NULL) { + return -1; + } + if (ks2->src == (char *) NULL) { + return +1; + } + + /* Both keys not NULL, so compare */ + return strcmp(ks1->src, ks2->src); +} /* end of function cmpr_ks */ + + + +static void report_error_spice_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + const char * const p_ks1_src = p_ks1->src; + if (p_ks1_src == (char *) NULL) { /* internal SPICE name */ + print_error("ERROR: Model name \"%s\" from directory \"%s\" " + "is the name of an internal SPICE model", + p_ks1->key, p_ks2->src); + } + else { + print_error("ERROR: Model name \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1_src, p_ks2->src); + } +} /* end of function report_error_spice_name */ + + + +static void report_error_function_name (const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + print_error("ERROR: C function name \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1->src, p_ks2->src); +} /* end of function report_error_spice_name */ + + + +static void report_error_udn_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + const char * const p_ks1_src = p_ks1->src; + if (p_ks1_src == (char *) NULL) { /* internal SPICE name */ + print_error("ERROR: Node type \"%s\" from directory \"%s\" " + "is the name of an internal SPICE node type", + p_ks1->key, p_ks2->src); + } + else { + print_error("ERROR: Node type \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1_src, p_ks2->src); + } +} /* end of function report_error_udn_name */ -} /* *********************************************************************** */ @@ -761,12 +1163,17 @@ static int write_CMextrn( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing CMextrn.h */ - const char *filename = "cmextrn.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("cmextrn.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cmextrn.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); + free(filename); return -1; } @@ -776,9 +1183,14 @@ static int write_CMextrn( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + free(filename); return 0; -} +} /* end of function write_CMextrn */ /* *********************************************************************** */ @@ -802,24 +1214,81 @@ static int write_CMinfo( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing CMinfo.h */ - const char *filename = "cminfo.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("cminfo.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cminfo.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); + free(filename); return -1; } /* Write out the data */ for(i = 0; i < num_models; i++) { - fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + Model_Info_t *p_mi_cur = model_info + i; + if (p_mi_cur->version == 1) { + fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + } } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_CMinfo */ + + + +static int write_CMinfo2( + int num_models, /* Number of model pathnames */ + Model_Info_t *model_info /* Info about each model */ +) +{ + int i; /* A temporary counter */ + FILE *fp; /* File pointer for writing CMinfo.h */ + + char *filename = (char *) NULL; + + /* Open the file to be written */ + if ((filename = gen_filename("cminfo2.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cminfo2.h"); + return -1; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for write", filename); + free(filename); + return -1; + } + + /* Write out the data */ + for (i = 0; i < num_models; i++) { + Model_Info_t *p_mi_cur = model_info + i; + if (p_mi_cur->version <= 2) { + fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + } + } + + /* Close the file and return */ + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); + return 0; +} /* end of function write_CMinfo2 */ @@ -847,10 +1316,14 @@ static int write_UDNextrn( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing UDNextrn.h */ - const char *filename = "udnextrn.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("udnextrn.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udnextrn.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -862,9 +1335,16 @@ static int write_UDNextrn( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_UDNextrn */ + /* *********************************************************************** */ @@ -879,9 +1359,6 @@ and user-defined nodes. This SPICE source file uses the structures mentioned in the include file to define the node types known to the simulator. */ - - - static int write_UDNinfo( int num_nodes, /* Number of node pathnames */ Node_Info_t *node_info /* Info about each node */ @@ -890,10 +1367,14 @@ static int write_UDNinfo( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing UDNinfo.h */ - const char *filename = "udninfo.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("udninfo.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udninfo.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -901,13 +1382,65 @@ static int write_UDNinfo( /* Write out the data */ for(i = 0; i < num_nodes; i++) { - fprintf(fp, "&udn_%s_info,\n", node_info[i].node_name); + Node_Info_t *p_ni_cur = node_info + i; + if (p_ni_cur->version == 1) { + fprintf(fp, "&udn_%s_info,\n", p_ni_cur->node_name); + } } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_UDNinfo */ + + + +static int write_UDNinfo2( + int num_nodes, /* Number of node pathnames */ + Node_Info_t *node_info /* Info about each node */ +) +{ + int i; /* A temporary counter */ + FILE *fp; /* File pointer for writing UDNinfo.h */ + + char *filename = (char *) NULL; + + /* Open the file to be written */ + if ((filename = gen_filename("udninfo2.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udninfo2.h"); + return -1; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for write", filename); + return -1; + } + + /* Write out the data */ + for(i = 0; i < num_nodes; i++) { + Node_Info_t *p_ni_cur = node_info + i; + if (p_ni_cur->version <= 2) { + fprintf(fp, "&udn_%s_info,\n", p_ni_cur->node_name); + } + } + + /* Close the file and return */ + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); + return 0; +} /* end of function write_UDNinfo */ + /* *********************************************************************** */ @@ -930,10 +1463,14 @@ static int write_objects_inc( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing make_include */ - const char *filename = "objects.inc"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("objects.inc", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to objects.inc"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -956,9 +1493,16 @@ static int write_objects_inc( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_objects_inc */ + /* @@ -983,12 +1527,18 @@ static int read_udn_type_name( int i; /* a counter */ static char *struct_type = "Evt_Udn_Info_t"; + char *filename = (char *) NULL; /* Open the file from which the node type name will be read */ - fp = fopen_cmpp(&path, "r"); - free((char*)path); - if(fp == NULL) + if ((filename = gen_filename(path, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build path to Evt_Udn_Info_t"); return -1; + } + fp = fopen(filename, "r"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for reading", filename); + return -1; + } /* Read the file until the definition of the Evt_Udn_Info_t struct */ /* is found, then get the name of the node type from the first */ @@ -1039,10 +1589,19 @@ static int read_udn_type_name( c = fgetc(fp); if(c == '"') { found = true; + if (i >= sizeof name) { + print_error("name too long"); + exit(1); + } name[i] = '\0'; } - else if(c != EOF) + else if(c != EOF) { + if (i > sizeof name) { + print_error("name too long"); + exit(1); + } name[i++] = (char) c; + } } while((c != EOF) && (! found)); } } while((c != EOF) && (! found)); @@ -1054,7 +1613,11 @@ static int read_udn_type_name( fclose(fp); if(found) { - *node_name = (char *) malloc(strlen(name) + 1); + if ((*node_name = (char *) malloc( + strlen(name) + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate node name"); + return -1; + } strcpy(*node_name, name); return 0; } @@ -1064,3 +1627,58 @@ static int read_udn_type_name( } } + + +/* Free allocations in p_model_info array */ +static void free_model_info(int num_models, Model_Info_t *p_model_info) +{ + /* Return if no structure */ + if (p_model_info == (Model_Info_t *) NULL) { + return; + } + + int i; + for (i = 0; i < num_models; ++i) { + Model_Info_t *p_cur = p_model_info + i; + void *p; + if ((p = p_cur->cfunc_name) != NULL) { + free(p); + } + if ((p = p_cur->path_name) != NULL) { + free(p); + } + if ((p = p_cur->spice_name) != NULL) { + free(p); + } + } + + free(p_model_info); +} /* end of function free_model_info */ + + + +/* Free allocations in p_nod_info array */ +static void free_node_info(int num_nodes, Node_Info_t *p_node_info) +{ + /* Return if no structure */ + if (p_node_info == (Node_Info_t *) NULL) { + return; + } + + int i; + for (i = 0; i < num_nodes; ++i) { + Node_Info_t *p_cur = p_node_info + i; + void *p; + if ((p = p_cur->node_name) != NULL) { + free(p); + } + if ((p = p_cur->path_name) != NULL) { + free(p); + } + } + + free(p_node_info); +} /* end of function free_node_info */ + + + diff --git a/src/xspice/cmpp/pp_mod.c b/src/xspice/cmpp/pp_mod.c index fe31be4f0..c31bce1a8 100644 --- a/src/xspice/cmpp/pp_mod.c +++ b/src/xspice/cmpp/pp_mod.c @@ -54,6 +54,7 @@ NON-STANDARD FEATURES ============================================================================*/ +#include #include #include #include @@ -74,21 +75,33 @@ extern int mod_num_errors; extern Ifs_Table_t *mod_ifs_table; -extern const char *current_filename; +extern char *current_filename; extern char *prog_name; /*---------------------------------------------------------------------------*/ -static char *change_extension (char *filename, char *ext) +/* Allocate and build a file name from the input filename by changing its + * extension (text after the last '.') in filename to ext or append .ext if + * the filename has no extension */ +static char *change_extension(const char *filename, const char *ext) { - char *p = strrchr(filename, '.'); - size_t prefix_len = p ? (size_t) (p-filename+1) : strlen(filename); - char *new_filename = malloc(prefix_len + strlen(ext) + 1); + const char * const p = strrchr(filename, '.'); + const size_t prefix_len = p ? (size_t) (p - filename) : strlen(filename); + const size_t ext_len = strlen(ext); + char * const new_filename = malloc(prefix_len + ext_len + 2); + /* +1 for '.' +1 for '\0' */ + if (new_filename == (char *) NULL) { + return (char *) NULL; + } - strncpy(new_filename, filename, prefix_len); - strcpy(new_filename+prefix_len, ext); + { + char *p_cur = (char *) memcpy(new_filename, filename, prefix_len) + + prefix_len; + *p_cur++ = '.'; + (void) memcpy(p_cur, ext, ext_len + 1); + } return new_filename; -} +} /* end of function change_extension */ /*---------------------------------------------------------------------------*/ @@ -108,14 +121,12 @@ utilities. void preprocess_mod_file ( - char *filename) /* The file to read */ + const char *filename) /* The file to read */ { - - - Ifs_Table_t ifs_table; /* info read from ifspec.ifs file */ - int status; /* Return status */ - const char *output_filename; - + Ifs_Table_t ifs_table; /* info read from ifspec.ifs file */ + int status; /* Return status */ + char *output_filename = (char *) NULL; /* .mod file being written */ + /* * Read the entire ifspec.ifs file and load the data into ifs_table */ @@ -125,45 +136,80 @@ void preprocess_mod_file ( if (status != 0) { exit(1); } - - current_filename = filename; - mod_yyin = fopen_cmpp (¤t_filename, "r"); - if (mod_yyin == NULL) { - print_error("ERROR - Could not open input .mod file: %s", current_filename); - exit(1); - } - - output_filename = change_extension (filename, "c"); - mod_yyout = fopen_cmpp (&output_filename, "w"); + /* Open the cfunc.mod file defining the code model function */ + if ((current_filename = gen_filename(filename, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build mod file name"); + exit(1); + } + if ((mod_yyin = fopen(current_filename, "r")) == (FILE *) NULL) { + print_error("ERROR - Unable to open mod file \"%s\": %s", + current_filename, strerror(errno)); + exit(1); + } + + { + char *output_filename_base = (char *) NULL; + if ((output_filename_base = change_extension( + filename, "c")) == (char *) NULL) { + print_error("ERROR - Could not change extension of " + "\"%s\".", filename); + exit(1); + } + + if ((output_filename = gen_filename( + output_filename_base, "w")) == (char *) NULL) { + print_error("ERROR - Unable to build output file name"); + exit(1); + } + + free(output_filename_base); + } + + if ((mod_yyout = fopen(output_filename, "w")) == (FILE *) NULL) { + /* .c file could not be opened */ + print_error("ERROR - Could not open output .c file\"%s\": %s", + output_filename, strerror(errno)); + exit(1); + } - if (mod_yyout == NULL) { - print_error("ERROR - Could not open output .c file: %s", output_filename); - exit(1); - } - mod_ifs_table = &ifs_table; mod_num_errors = 0; +/* Define DEBUG_WITH_MOD_FILE to have the compiler use the cfunc.mod file for + * deugging instead of the cfunc.c file. */ +#ifdef DEBUG_WITH_MOD_FILE fprintf (mod_yyout, "#line 1 \"%s\"\n", current_filename); +#endif fprintf (mod_yyout, "#include \"ngspice/cm.h\"\n"); fprintf (mod_yyout, "extern void %s(Mif_Private_t *);\n", - ifs_table.name.c_fcn_name); + ifs_table.name.c_fcn_name); +#ifdef DEBUG_WITH_MOD_FILE fprintf (mod_yyout, "#line 1 \"%s\"\n", current_filename); +#endif mod_yylineno = 1; - if (mod_yyparse() || (mod_num_errors > 0)) { - print_error("Error parsing .mod file: \"%s\"", current_filename); - unlink (output_filename); - exit (1); - } - fclose (mod_yyout); - if(output_filename) - free((char*)output_filename); + if (mod_yyparse() || (mod_num_errors > 0)) { + print_error("Error parsing .mod file: \"%s\"", current_filename); + unlink(output_filename); + exit(1); + } + + if (fclose(mod_yyout) != 0) { + print_error("Error closing output file \"%s\": %s", + current_filename, strerror(errno)); + unlink(output_filename); + exit(1); + } + rem_ifs_table(&ifs_table); mod_yyrestart(NULL); -} + free(output_filename); + free(current_filename); +} /* end of function preprocess_mod_file */ + + /*---------------------------------------------------------------------------*/ void diff --git a/src/xspice/cmpp/read_ifs.c b/src/xspice/cmpp/read_ifs.c index 51b72184d..ce439a8a5 100644 --- a/src/xspice/cmpp/read_ifs.c +++ b/src/xspice/cmpp/read_ifs.c @@ -47,7 +47,11 @@ NON-STANDARD FEATURES ============================================================================*/ #include +#include #include +#include +#include + #include "ifs_yacc_y.h" extern char *prog_name; @@ -65,7 +69,7 @@ extern int ifs_num_errors; static int read_ifs_table(FILE *fp, int mode, Ifs_Table_t *ifs_table); -const char *current_filename; +char *current_filename; /* *********************************************************************** */ @@ -94,35 +98,42 @@ int read_ifs_file( int mode, /* Get names only or get everything? */ Ifs_Table_t *ifs_table) /* Table to put info in */ { - - FILE *fp; /* Ifs file pointer */ - - int status; /* returned status from function */ - - + FILE *fp = (FILE *) NULL; /* Ifs file pointer */ + int status = 0; /* returned status from function */ + + /* Open the ifs file for read access */ - fp = fopen_cmpp(&filename, "r"); - - if(fp == NULL) { - perror (prog_name); - print_error("ERROR - File not found: %s", filename); - return -1; + /* Open the model pathname file */ + if ((current_filename = gen_filename(filename, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build full file name"); + return -1; + } + if ((fp = fopen(current_filename, "r")) == (FILE *) NULL) { + print_error("ERROR - Unable to open \"%s\": %s", + current_filename, strerror(errno)); + status = -1; + goto EXITPOINT; + } + + /* Get the stuff from the file into the ifs_table struct. Here mode + * defines the data that will be added to the structure */ + status = read_ifs_table(fp, mode, ifs_table); + + EXITPOINT: + /* Close file and return */ + if (fp != (FILE *) NULL) { + if (fclose(fp) != 0) { + print_error("ERROR - Unable to close \"%s\": %s", + current_filename, strerror(errno)); + status = -1; + } } - current_filename = filename; - - /* Get the stuff from the file into the ifs_table struct */ - - status = read_ifs_table(fp, mode, ifs_table); - - /* Close file and return */ - - fclose(fp); - - return(status); - -} + free(current_filename); + current_filename = (char *) NULL; + return status; +} /* end of function read_ifs_file */ @@ -146,7 +157,6 @@ static int read_ifs_table( int mode, /* Get names only or get everything? */ Ifs_Table_t *ifs_table) /* Table to put info in */ { - assert (ifs_table); assert (fp); diff --git a/src/xspice/cmpp/util.c b/src/xspice/cmpp/util.c index da6a27163..255812e4d 100644 --- a/src/xspice/cmpp/util.c +++ b/src/xspice/cmpp/util.c @@ -84,16 +84,21 @@ void print_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - - fprintf(stderr, "%s: ", prog_name); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - + vprint_error(fmt, ap); va_end(ap); } /* end of function print_error */ +void vprint_error(const char *fmt, va_list p_arg) +{ + fprintf(stderr, "%s: ", prog_name); + vfprintf(stderr, fmt, p_arg); + fprintf(stderr, "\n"); +} /* end of function vprint_error */ + + + /* Convert a string to all lower case */ void str_to_lower(char *s) { @@ -110,24 +115,22 @@ void str_to_lower(char *s) /* If *path_p is relative, prefix with the value of the CMPP output or * input environment variable. Open the file and return the path that * was used to open it. */ -FILE *fopen_cmpp(const char **path_p, const char *mode) +char *gen_filename(const char *filename, const char *mode) { - const char *path = *path_p; char *buf = (char *) NULL; /* If absoulte path, prefix with CMPP_ODIR/CMPP_IDIR env value */ - if (!is_absolute_pathname(path)) { /* relative path */ + if (!is_absolute_pathname(filename)) { /* relative path */ const char *e = getenv((*mode == 'w' || *mode == 'a') ? "CMPP_ODIR" : "CMPP_IDIR"); if (e) { /* have env var */ const size_t len_prefix = strlen(e); - const size_t len_path = strlen(path); - const size_t n_char = len_prefix + len_path + 1; + const size_t len_filename = strlen(filename); + const size_t n_char = len_prefix + len_filename + 1; /* Allocate buffer to build full file name */ if ((buf = (char *) malloc(n_char + 1)) == (char *) NULL) { - *path_p = (char *) NULL; - return (FILE *) NULL; + return (char *) NULL; } /* Build the full file name */ @@ -136,24 +139,21 @@ FILE *fopen_cmpp(const char **path_p, const char *mode) (void) memcpy(p_cur, e, len_prefix); p_cur += len_prefix; *p_cur++ = DIR_TERM_UNIX; - (void) memcpy(p_cur, path, len_path + 1); + (void) memcpy(p_cur, filename, len_filename + 1); } } /* end of case that env variable found */ } /* end of case that path is absolute */ - /* If did not build full file name yet, copy the original - * name of the file */ + /* If did not build full file name yet, make the original + * name of the file the full file name */ if (buf == (char *) NULL) { - if ((buf = strdup(path)) == (char *) NULL) { /* failed */ - *path_p = (char *) NULL; - return (FILE *) NULL; + if ((buf = strdup(filename)) == (char *) NULL) { /* failed */ + return (char *) NULL; } } - /* Return copy of file name and opened file */ - *path_p = buf; - return fopen(buf, mode); -} /* end of function fopen_cmpp */ + return buf; +} /* end of function gen_filename */ diff --git a/src/xspice/cmpp/writ_ifs.c b/src/xspice/cmpp/writ_ifs.c index 9e9129fa7..e1ab2d5e6 100644 --- a/src/xspice/cmpp/writ_ifs.c +++ b/src/xspice/cmpp/writ_ifs.c @@ -40,45 +40,31 @@ NON-STANDARD FEATURES #include +#include #include #include #include "cmpp.h" /* Local function prototypes */ - -static void write_comment(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_includes(FILE *fp); - -static void write_mPTable(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_pTable(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_conn_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_param_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_inst_var_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_SPICEdev(FILE *fp, Ifs_Table_t *ifs_table); +static int write_comment(FILE *fp, Ifs_Table_t *ifs_table); +static int write_includes(FILE *fp); +static int write_mPTable(FILE *fp, Ifs_Table_t *ifs_table); +static int write_pTable(FILE *fp, Ifs_Table_t *ifs_table); +static int write_conn_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_param_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_inst_var_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_SPICEdev(FILE *fp, Ifs_Table_t *ifs_table); -static char *data_type_to_str(Data_Type_t type); - -static char *port_type_to_str(Port_Type_t port); - -static char *dir_to_str(Dir_t dir); - +static const char *data_type_to_str(Data_Type_t type); +static const char *port_type_to_str(Port_Type_t port); +static const char *dir_to_str(Dir_t dir); static char *value_to_str(Data_Type_t type, Value_t value); - -static char *no_value_to_str(void); - -static char *boolean_to_str(bool value); - +static const char *no_value_to_str(void); +static const char *boolean_to_str(bool value); static char *integer_to_str(int value); - -static char *gen_port_type_str(Port_Type_t port); +static const char *gen_port_type_str(Port_Type_t port); @@ -110,59 +96,102 @@ The output file is then closed. int write_ifs_c_file( - const char *filename, /* File to write to */ + const char *filename_in, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - FILE *fp; /* File pointer */ - int int_status; /* returned status from fclose */ + FILE *fp = (FILE *) NULL; /* File pointer */ + char *filename = (char *) NULL; + int xrc = 0; /* Open the ifspec.c file for write access */ - - fp = fopen_cmpp(&filename, "w"); - - if(fp == NULL) { - print_error("ERROR - Can't create file: %s", filename); - return -1; + if ((filename = gen_filename(filename_in, "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to \"%s\".", filename); + xrc = -1; + goto EXITPOINT; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening \"%s\" for write", filename); + xrc = -1; + goto EXITPOINT; } - /* Write out a comment section at the top of the file */ - write_comment(fp, ifs_table); + if (write_comment(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing comment to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Put in the # includes */ - write_includes(fp); + if (write_includes(fp) != 0) { + print_error("ERROR - Problems writing includes to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write the SPICE3 required XXXmPTable structure */ - write_mPTable(fp, ifs_table); + if (write_mPTable(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing mPTable to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write the SPICE3 required XXXpTable structure */ - write_pTable(fp, ifs_table); + if (write_pTable(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing pTable to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the connector table required for the code model element parser */ - write_conn_info(fp, ifs_table); + if (write_conn_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing includes to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the parameter table required for the code model element parser */ - write_param_info(fp, ifs_table); + if (write_param_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing params to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the instance variable table required for the code model element parser */ - write_inst_var_info(fp, ifs_table); + if (write_inst_var_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing instaice variables to \"%s\"", + filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the externally visible structure for this model */ - write_SPICEdev(fp, ifs_table); - - - /* Close the ifspec.c file and return */ - - int_status = fclose(fp); - - if (int_status == 0) { - return 0; + if (write_SPICEdev(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing model structureto \"%s\"", + filename); + xrc = -1; + goto EXITPOINT; } - else { - return -1; + + +EXITPOINT: + /* Close the ifspec.c file, free allocation, and return */ + if (fp != (FILE *) NULL) { + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing \"%s\": %s.", + filename, strerror(errno)); + xrc = -1; + } } -} + + if (filename != (char *) NULL) { + free(filename); + } + + return xrc; +} /* end of function write_ifs_c_file */ @@ -178,21 +207,29 @@ generated and should not be edited. */ -static void write_comment( +static int write_comment( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - fprintf(fp, "\n"); - fprintf(fp, "/*\n"); - fprintf(fp, " * Structures for model: %s\n", ifs_table->name.model_name); - fprintf(fp, " *\n"); - fprintf(fp, " * Automatically generated by cmpp preprocessor\n"); - fprintf(fp, " *\n"); - fprintf(fp, " * !!! DO NOT EDIT !!!\n"); - fprintf(fp, " *\n"); - fprintf(fp, " */\n"); - fprintf(fp, "\n"); -} + const int rc = fprintf(fp, + "\n" + "/*\n" + " * Structures for model: %s\n" + " *\n" + " * Automatically generated by cmpp preprocessor\n" + " *\n" + " * !!! DO NOT EDIT !!!\n" + " *\n" + " */\n" + "\n", + ifs_table->name.model_name); + if (rc < 0) { + print_error("Comment writing failed."); + return -1; + } + return 0; +} /* end of function write_comment */ + /* *********************************************************************** */ @@ -205,21 +242,28 @@ ifspec.c. */ -static void write_includes( +static int write_includes( FILE *fp) /* File to write to */ { - fprintf(fp, "\n"); - fprintf(fp, "#include \"ngspice/ngspice.h\"\n"); -/* fprintf(fp, "#include \"ngspice/prefix.h\"\n");*/ - fprintf(fp, "#include \n"); - fprintf(fp, "#include \"ngspice/devdefs.h\"\n"); - fprintf(fp, "#include \"ngspice/ifsim.h\"\n"); - fprintf(fp, "#include \"ngspice/mifdefs.h\"\n"); - fprintf(fp, "#include \"ngspice/mifproto.h\"\n"); - fprintf(fp, "#include \"ngspice/mifparse.h\"\n"); -/* fprintf(fp, "#include \"ngspice/suffix.h\"\n");*/ - fprintf(fp, "\n"); -} + const int rc = fprintf(fp, + "\n" + "#include \"ngspice/ngspice.h\"\n" +/* "#include \"ngspice/prefix.h\"\n"*/ + "#include \n" + "#include \"ngspice/devdefs.h\"\n" + "#include \"ngspice/ifsim.h\"\n" + "#include \"ngspice/mifdefs.h\"\n" + "#include \"ngspice/mifproto.h\"\n" + "#include \"ngspice/mifparse.h\"\n" +/* "#include \"ngspice/suffix.h\"\n"*/ + "\n"); + if (rc < 0) { + print_error("Include writing failed."); + return -1; + } + return 0; +} /* end of function write_includes */ + /* *********************************************************************** */ @@ -238,28 +282,28 @@ that can be queried using the SPICE 3C1 .save feature. */ -static void write_pTable( +static int write_pTable( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char str[80]; bool is_array; Data_Type_t type; /* Only write the pTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ + if (ifs_table->num_inst_var == 0) { + return 0; + } - if(ifs_table->num_inst_var == 0) - return; - + int rc = 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static IFparm MIFpTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static IFparm MIFpTable[] = {\n"); /* Write out an entry for each instance variable in the table */ @@ -267,68 +311,71 @@ static void write_pTable( /* Use the index of the element in the instance variable info array */ /* ADDED TO the number of parameters as the SPICE3 integer tag. */ - for(i = 0; i < ifs_table->num_inst_var; i++) { + for (i = 0; i < ifs_table->num_inst_var; i++) { /* Use the SPICE3 OP macro since instance vars are output-only */ - fprintf(fp, " OP("); + rc |= fprintf(fp, " OP("); /* Put in the name of the parameter and the integer tag */ - fprintf(fp, "\"%s\", ", ifs_table->inst_var[i].name); - fprintf(fp, "%d, ", i + ifs_table->num_param); + rc |= fprintf(fp, "\"%s\", ", ifs_table->inst_var[i].name); + rc |= fprintf(fp, "%d, ", i + ifs_table->num_param); /* Format SPICE3 type according to parameter type field */ type = ifs_table->inst_var[i].type; is_array = ifs_table->inst_var[i].is_array; - strcpy(str,""); - if(is_array == true) { - strcat(str,"("); + rc |= fprintf(fp, "("); } if(type == CMPP_BOOLEAN) { - strcat(str,"IF_FLAG"); /* There is no BOOLEAN in SPICE3 */ + rc |= fprintf(fp, "IF_FLAG"); /* no BOOLEAN in SPICE3 */ } else if(type == CMPP_INTEGER) { - strcat(str,"IF_INTEGER"); + rc |= fprintf(fp, "IF_INTEGER"); } else if(type == CMPP_REAL) { - strcat(str,"IF_REAL"); + rc |= fprintf(fp, "IF_REAL"); } else if(type == CMPP_COMPLEX) { - strcat(str,"IF_COMPLEX"); + rc |= fprintf(fp, "IF_COMPLEX"); } else if(type == CMPP_STRING) { - strcat(str,"IF_STRING"); + rc |= fprintf(fp, "IF_STRING"); } else if(type == CMPP_POINTER) { - strcat(str,"IF_STRING"); + rc |= fprintf(fp, "IF_STRING"); } else { print_error("INTERNAL ERROR - write_pTable() - Impossible data type."); + xrc = -1; + rc |= fprintf(fp, "INVALID DATA TYPE"); } if(is_array == true) { - strcat(str,"|IF_VECTOR)"); + rc |= fprintf(fp, "|IF_VECTOR)"); } - fprintf(fp, "%s, ", str); /* Put in the description string and finish this line off */ - - fprintf(fp, "\"%s\"", ifs_table->inst_var[i].description); - fprintf(fp, "),\n"); - - } + rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->inst_var[i].description); + } /* end of loop over instance variables */ /* Finish off the structure */ + rc |= fprintf(fp, "};\n\n"); + + /* Check outputs */ + if (rc < 0) { + print_error("pTable writing failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_pTable */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} /* *********************************************************************** */ @@ -345,95 +392,95 @@ model parameters are derived from the Interface Specification's PARAMETER table. */ -static void write_mPTable( +static int write_mPTable( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char str[80]; - bool is_array; - Data_Type_t type; /* Only write the mPTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_param == 0) - return; + if (ifs_table->num_param == 0) { + return 0; + } + int rc = 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static IFparm MIFmPTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static IFparm MIFmPTable[] = {\n"); /* Write out an entry for each parameter in the table */ /* Use the index of the element in the parameter info array */ /* as the SPICE3 integer tag. */ - + Param_Info_t *param = ifs_table->param; for(i = 0; i < ifs_table->num_param; i++) { + Param_Info_t *param_cur = param + i; /* Use the SPICE3 IOP macro since model parameters are input/output */ - fprintf(fp, " IOP("); + rc |= fprintf(fp, " IOP("); /* Put in the name of the parameter and the integer tag */ - - fprintf(fp, "\"%s\", ", ifs_table->param[i].name); - fprintf(fp, "%d, ", i); + rc |= fprintf(fp, "\"%s\", ", param_cur->name); + rc |= fprintf(fp, "%d, ", i); /* Format SPICE3 type according to parameter type field */ - type = ifs_table->param[i].type; - is_array = ifs_table->param[i].is_array; + const bool is_array = param_cur->is_array; + const Data_Type_t type = param_cur->type; - strcpy(str,""); - - if(is_array == true) { - strcat(str,"("); + if (is_array) { + rc |= fprintf(fp, "("); } - if(type == CMPP_BOOLEAN) { - strcat(str,"IF_FLAG"); /* There is no BOOLEAN in SPICE3 */ + if (type == CMPP_BOOLEAN) { + rc |= fprintf(fp, "IF_FLAG"); /* no BOOLEAN in SPICE3 */ } - else if(type == CMPP_INTEGER) { - strcat(str,"IF_INTEGER"); + else if (type == CMPP_INTEGER) { + rc |= fprintf(fp, "IF_INTEGER"); } - else if(type == CMPP_REAL) { - strcat(str,"IF_REAL"); + else if (type == CMPP_REAL) { + rc |= fprintf(fp, "IF_REAL"); } - else if(type == CMPP_COMPLEX) { - strcat(str,"IF_COMPLEX"); + else if (type == CMPP_COMPLEX) { + rc |= fprintf(fp, "IF_COMPLEX"); } - else if(type == CMPP_STRING) { - strcat(str,"IF_STRING"); + else if (type == CMPP_STRING) { + rc |= fprintf(fp, "IF_STRING"); } else { print_error("INTERNAL ERROR - write_mPTable() - Impossible data type."); + xrc = -1; } - if(is_array == true) { - strcat(str,"|IF_VECTOR)"); + if (is_array) { + rc |= fprintf(fp, "|IF_VECTOR)"); } - fprintf(fp, "%s, ", str); /* Put in the description string and finish this line off */ - - fprintf(fp, "\"%s\"", ifs_table->param[i].description); - fprintf(fp, "),\n"); - - } + rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->param[i].description); + } /* end of loop over parameters */ /* Finish off the structure */ + rc |= fprintf(fp, "};\n\n"); - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + /* Check outputs */ + if (rc < 0) { + print_error("mPTable writing failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_mPTable */ -} /* *********************************************************************** */ @@ -450,147 +497,164 @@ derived from the Interface Specification file's PORT table. -static void write_conn_info( +static int write_conn_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; int j; - char *str; + const char *str; + int rc = 0; /* Only write the connTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_conn == 0) /* An unlikely condition for sure ... */ - return; + if (ifs_table->num_conn == 0) { /* An unlikely condition for sure ... */ + return 0; + } /* First, we must define arrays of port types */ /* Note that there should be always at least one allowed port type */ /* so we don't have to worry about arrays with no elements */ - for(i = 0; i < ifs_table->num_conn; i++) { + const Conn_Info_t * const conn = ifs_table->conn; + const int num_conn = ifs_table->num_conn; + for (i = 0; i < num_conn; i++) { + const Conn_Info_t * const p_conn_cur = conn + i; + rc |= fprintf(fp, + "\n" + "static Mif_Port_Type_t MIFportEnum%d[] = {\n", i); - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Port_Type_t MIFportEnum%d[] = {\n", i); - - if(ifs_table->conn[i].num_allowed_types < 1) - print_error("ERROR - write_conn_info() - Number of allowed types cannot be zero"); - - for(j = 0; j < ifs_table->conn[i].num_allowed_types; j++) { - - str = port_type_to_str(ifs_table->conn[i].allowed_port_type[j]); - fprintf(fp, "\t%s,\n", str); + if (p_conn_cur->num_allowed_types < 1) { + print_error("ERROR - write_conn_info() - " + "Number of allowed types cannot be zero"); + xrc = -1; + } + const int num_allowed_types = p_conn_cur->num_allowed_types; + for (j = 0; j < num_allowed_types; j++) { + rc |= fprintf(fp, " %s,\n", + port_type_to_str(p_conn_cur->allowed_port_type[j])); } /* for number of allowed types */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, + "};\n" + "\n" + "\n" + "static char *MIFportStr%d[] = {\n", i); - - fprintf(fp, "\n"); - fprintf(fp, "static char *MIFportStr%d[] = {\n", i); - - for(j = 0; j < ifs_table->conn[i].num_allowed_types; j++) { - if(ifs_table->conn[i].allowed_port_type[j] == USER_DEFINED) - fprintf(fp, "\t\"%s\",\n", ifs_table->conn[i].allowed_type[j]); + for (j = 0; j < num_allowed_types; j++) { + if (p_conn_cur->allowed_port_type[j] == USER_DEFINED) { + rc |= fprintf(fp, " \"%s\",\n", + p_conn_cur->allowed_type[j]); + } else { - str = gen_port_type_str(ifs_table->conn[i].allowed_port_type[j]); - fprintf(fp, "\t\"%s\",\n", str); + str = gen_port_type_str(p_conn_cur->allowed_port_type[j]); + rc |= fprintf(fp, " \"%s\",\n", str); } } /* for number of allowed types */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); - + rc |= fprintf(fp, + "};\n" + "\n"); } /* for number of connections */ /* Now write the structure */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Conn_Info_t MIFconnTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static Mif_Conn_Info_t MIFconnTable[] = {\n"); /* Write out an entry for each parameter in the table */ - for(i = 0; i < ifs_table->num_conn; i++) { + for (i = 0; i < num_conn; i++) { + const Conn_Info_t * const p_conn_cur = conn + i; - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->conn[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->conn[i].description); + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n", p_conn_cur->name); + rc |= fprintf(fp, " \"%s\",\n", p_conn_cur->description); - str = dir_to_str(ifs_table->conn[i].direction); - fprintf(fp, " %s,\n", str); + str = dir_to_str(p_conn_cur->direction); + rc |= fprintf(fp, " %s,\n", str); - str = port_type_to_str(ifs_table->conn[i].default_port_type); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", + port_type_to_str(p_conn_cur->default_port_type)); - fprintf(fp, " \"%s\",\n", - (ifs_table->conn[i].default_port_type == USER_DEFINED) - ? ifs_table->conn[i].default_type - : gen_port_type_str (ifs_table->conn[i].default_port_type)); + rc |= fprintf(fp, " \"%s\",\n", + (p_conn_cur->default_port_type == USER_DEFINED) + ? p_conn_cur->default_type + : gen_port_type_str(p_conn_cur->default_port_type)); - fprintf(fp," %d,\n",ifs_table->conn[i].num_allowed_types); - - fprintf(fp, " MIFportEnum%d,\n", i); - fprintf(fp, " MIFportStr%d,\n", i); + rc |= fprintf(fp," %d,\n", p_conn_cur->num_allowed_types); + rc |= fprintf(fp, " MIFportEnum%d,\n", i); + rc |= fprintf(fp, " MIFportStr%d,\n", i); - str = boolean_to_str(ifs_table->conn[i].is_array); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->is_array); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].is_array == false) { + if (p_conn_cur->is_array == false) { str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* is_array == true */ - str = boolean_to_str(ifs_table->conn[i].has_lower_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->has_lower_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].has_lower_bound == true) - str = integer_to_str(ifs_table->conn[i].lower_bound); + if (p_conn_cur->has_lower_bound == true) + str = integer_to_str(p_conn_cur->lower_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->conn[i].has_upper_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->has_upper_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].has_upper_bound == true) - str = integer_to_str(ifs_table->conn[i].upper_bound); + if (p_conn_cur->has_upper_bound == true) + str = integer_to_str(p_conn_cur->upper_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } /* if is_array */ - str = boolean_to_str(ifs_table->conn[i].null_allowed); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->null_allowed); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ + rc |= fprintf(fp, + "};\n" + "\n"); + + /* Check outputs */ + if (rc < 0) { + print_error("Writing of connection information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_conn_info */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} /* *********************************************************************** */ @@ -613,152 +677,162 @@ input deck. -static void write_param_info( +static int write_param_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char *str; + const char *str; /* Only write the paramTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_param == 0) - return; + if (ifs_table->num_param == 0) { + return 0; + } /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Param_Info_t MIFparamTable[] = {\n"); + int rc = 0; + rc |= fprintf(fp, + "\n" + "static Mif_Param_Info_t MIFparamTable[] = {\n"); /* Write out an entry for each parameter in the table */ + const Param_Info_t * const param = ifs_table->param; + const int num_param = ifs_table->num_param; + for (i = 0; i < num_param; i++) { + const Param_Info_t * const p_param_cur = param + i; - for(i = 0; i < ifs_table->num_param; i++) { + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n", p_param_cur->name); + rc |= fprintf(fp, " \"%s\",\n", p_param_cur->description); - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->param[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->param[i].description); + rc |= fprintf(fp, " %s,\n", + data_type_to_str(p_param_cur->type)); - str = data_type_to_str(ifs_table->param[i].type); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_default); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_default); - fprintf(fp, " %s,\n", str); - - if(ifs_table->param[i].has_default == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].default_value); + if (p_param_cur->has_default == true) + str = value_to_str(p_param_cur->type, p_param_cur->default_value); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_lower_limit); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_lower_limit); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_lower_limit == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].lower_limit); + if (p_param_cur->has_lower_limit == true) + str = value_to_str(p_param_cur->type, p_param_cur->lower_limit); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_upper_limit); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_upper_limit); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_upper_limit == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].upper_limit); + if (p_param_cur->has_upper_limit == true) + str = value_to_str(p_param_cur->type, p_param_cur->upper_limit); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].is_array); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->is_array); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].is_array == false) { + if (!p_param_cur->is_array) { str = boolean_to_str(false); /* has_conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* is_array == true */ - str = boolean_to_str(ifs_table->param[i].has_conn_ref); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_conn_ref); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_conn_ref == true) { + if (p_param_cur->has_conn_ref) { - str = integer_to_str(ifs_table->param[i].conn_ref); - fprintf(fp, " %s,\n", str); + str = integer_to_str(p_param_cur->conn_ref); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* has_conn_ref == false */ str = integer_to_str(0); /* conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_lower_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_lower_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_lower_bound == true) - str = integer_to_str(ifs_table->param[i].lower_bound); + if (p_param_cur->has_lower_bound) + str = integer_to_str(p_param_cur->lower_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_upper_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_upper_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_upper_bound == true) - str = integer_to_str(ifs_table->param[i].upper_bound); + if (p_param_cur->has_upper_bound) + str = integer_to_str(p_param_cur->upper_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } /* if has_conn_ref */ } /* if is_array */ - str = boolean_to_str(ifs_table->param[i].null_allowed); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->null_allowed); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, "};\n\n"); -} + /* Check outputs */ + if (rc < 0) { + print_error("Writing of param information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_param_info */ @@ -780,53 +854,59 @@ written by write_inst_var_info is more extensive. -static void write_inst_var_info( +static int write_inst_var_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char *str; + const char *str; /* Only write the inst_varTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_inst_var == 0) - return; + if (ifs_table->num_inst_var == 0) + return 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Inst_Var_Info_t MIFinst_varTable[] = {\n"); + int rc = 0; + rc |= fprintf(fp, + "\n" + "static Mif_Inst_Var_Info_t MIFinst_varTable[] = {\n"); /* Write out an entry for each parameter in the table */ for(i = 0; i < ifs_table->num_inst_var; i++) { - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].description); + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].name); + rc |= fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].description); - str = data_type_to_str(ifs_table->inst_var[i].type); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", + data_type_to_str(ifs_table->inst_var[i].type)); str = boolean_to_str(ifs_table->inst_var[i].is_array); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, "};\n\n"); -} + /* Check outputs */ + if (rc < 0) { + print_error("Writing of instance variable information failed."); + xrc = -1; + } + return xrc; +} /* end of function write_inst_var_info */ @@ -845,118 +925,133 @@ pointers to all of the above data structures. -static void write_SPICEdev( +static int write_SPICEdev( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - - /* Extern the code model function name */ - fprintf(fp, "\n"); - fprintf(fp, "extern void %s(Mif_Private_t *);\n", - ifs_table->name.c_fcn_name); + int rc = 0; /* init print rc to nonnegative (no error) */ + int xrc = 0; - /* SPICE now needs these static integers */ - fprintf(fp, "\n"); - fprintf(fp, "static int val_terms = 0;\n"); - fprintf(fp, "static int val_numNames = 0;\n"); - fprintf(fp, "static int val_numInstanceParms = %d;\n",ifs_table->num_inst_var); - fprintf(fp, "static int val_numModelParms = %d;\n",ifs_table->num_param); - fprintf(fp, "static int val_sizeofMIFinstance = sizeof(MIFinstance);\n"); - fprintf(fp, "static int val_sizeofMIFmodel = sizeof(MIFmodel);\n"); + /* Extern the code model function name */ + rc |= fprintf(fp, + "\n" + "extern void %s(Mif_Private_t *);\n", + ifs_table->name.c_fcn_name); + + /* SPICE now needs these static integers */ + rc |= fprintf(fp, + "\n" + "static int val_terms = 0;\n" + "static int val_numNames = 0;\n" + "static int val_numInstanceParms = %d;\n" + "static int val_numModelParms = %d;\n" + "static int val_sizeofMIFinstance = sizeof(MIFinstance);\n" + "static int val_sizeofMIFmodel = sizeof(MIFmodel);\n", + ifs_table->num_inst_var, ifs_table->num_param); /* Write out the structure beginning */ /* Use the c function external identifier appended with _info as the */ /* external identifier for the structure. */ - fprintf(fp, "\n"); - fprintf(fp, "SPICEdev %s_info = {\n", ifs_table->name.c_fcn_name); + rc |= fprintf(fp, + "\n" + "SPICEdev %s_info = {\n", ifs_table->name.c_fcn_name); /* Write the IFdevice structure */ - fprintf(fp, " .DEVpublic = {\n"); - fprintf(fp, " .name = \"%s\",\n", ifs_table->name.model_name); - fprintf(fp, " .description = \"%s\",\n", ifs_table->name.description); - fprintf(fp, " .terms = &val_terms,\n"); - fprintf(fp, " .numNames = &val_numNames,\n"); - fprintf(fp, " .termNames = NULL,\n"); + rc |= fprintf(fp, " .DEVpublic = {\n"); + rc |= fprintf(fp, " .name = \"%s\",\n", ifs_table->name.model_name); + rc |= fprintf(fp, " .description = \"%s\",\n", ifs_table->name.description); + rc |= fprintf(fp, + " .terms = &val_terms,\n" + " .numNames = &val_numNames,\n" + " .termNames = NULL,\n" + " .numInstanceParms = &val_numInstanceParms,\n"); - fprintf(fp, " .numInstanceParms = &val_numInstanceParms,\n"); if(ifs_table->num_inst_var > 0) - fprintf(fp, " .instanceParms = MIFpTable,\n"); + rc |= fprintf(fp, " .instanceParms = MIFpTable,\n"); else - fprintf(fp, " .instanceParms = NULL,\n"); + rc |= fprintf(fp, " .instanceParms = NULL,\n"); - fprintf(fp, " .numModelParms = &val_numModelParms,\n"); + rc |= fprintf(fp, " .numModelParms = &val_numModelParms,\n"); if(ifs_table->num_param > 0) - fprintf(fp, " .modelParms = MIFmPTable,\n"); + rc |= fprintf(fp, " .modelParms = MIFmPTable,\n"); else - fprintf(fp, " .modelParms = NULL,\n"); - fprintf(fp, " .flags = 0,\n\n"); + rc |= fprintf(fp, " .modelParms = NULL,\n"); + rc |= fprintf(fp, " .flags = 0,\n\n"); - fprintf(fp, " .cm_func = %s,\n", ifs_table->name.c_fcn_name); + rc |= fprintf(fp, " .cm_func = %s,\n", ifs_table->name.c_fcn_name); - fprintf(fp, " .num_conn = %d,\n", ifs_table->num_conn); + rc |= fprintf(fp, " .num_conn = %d,\n", ifs_table->num_conn); if(ifs_table->num_conn > 0) - fprintf(fp, " .conn = MIFconnTable,\n"); + rc |= fprintf(fp, " .conn = MIFconnTable,\n"); else - fprintf(fp, " .conn = NULL,\n"); + rc |= fprintf(fp, " .conn = NULL,\n"); - fprintf(fp, " .num_param = %d,\n", ifs_table->num_param); + rc |= fprintf(fp, " .num_param = %d,\n", ifs_table->num_param); if(ifs_table->num_param > 0) - fprintf(fp, " .param = MIFparamTable,\n"); + rc |= fprintf(fp, " .param = MIFparamTable,\n"); else - fprintf(fp, " .param = NULL,\n"); + rc |= fprintf(fp, " .param = NULL,\n"); - fprintf(fp, " .num_inst_var = %d,\n", ifs_table->num_inst_var); + rc |= fprintf(fp, " .num_inst_var = %d,\n", ifs_table->num_inst_var); if(ifs_table->num_inst_var > 0) - fprintf(fp, " .inst_var = MIFinst_varTable,\n"); + rc |= fprintf(fp, " .inst_var = MIFinst_varTable,\n"); else - fprintf(fp, " .inst_var = NULL,\n"); + rc |= fprintf(fp, " .inst_var = NULL,\n"); - fprintf(fp, " },\n\n"); + rc |= fprintf(fp, " },\n\n"); /* Write the names of the generic code model functions */ - fprintf(fp, " .DEVparam = NULL,\n"); - fprintf(fp, " .DEVmodParam = MIFmParam,\n"); - fprintf(fp, " .DEVload = MIFload,\n"); - fprintf(fp, " .DEVsetup = MIFsetup,\n"); - fprintf(fp, " .DEVunsetup = MIFunsetup,\n"); - fprintf(fp, " .DEVpzSetup = NULL,\n"); - fprintf(fp, " .DEVtemperature = NULL,\n"); - fprintf(fp, " .DEVtrunc = MIFtrunc,\n"); - fprintf(fp, " .DEVfindBranch = NULL,\n"); - fprintf(fp, " .DEVacLoad = MIFload,\n"); - fprintf(fp, " .DEVaccept = NULL,\n"); - fprintf(fp, " .DEVdestroy = MIFdestroy,\n"); - fprintf(fp, " .DEVmodDelete = MIFmDelete,\n"); - fprintf(fp, " .DEVdelete = MIFdelete,\n"); - fprintf(fp, " .DEVsetic = NULL,\n"); - fprintf(fp, " .DEVask = MIFask,\n"); - fprintf(fp, " .DEVmodAsk = MIFmAsk,\n"); - fprintf(fp, " .DEVpzLoad = NULL,\n"); - fprintf(fp, " .DEVconvTest = MIFconvTest,\n"); - fprintf(fp, " .DEVsenSetup = NULL,\n"); - fprintf(fp, " .DEVsenLoad = NULL,\n"); - fprintf(fp, " .DEVsenUpdate = NULL,\n"); - fprintf(fp, " .DEVsenAcLoad = NULL,\n"); - fprintf(fp, " .DEVsenPrint = NULL,\n"); - fprintf(fp, " .DEVsenTrunc = NULL,\n"); - fprintf(fp, " .DEVdisto = NULL,\n"); - fprintf(fp, " .DEVnoise = NULL,\n"); - fprintf(fp, " .DEVsoaCheck = NULL,\n"); - fprintf(fp, " .DEVinstSize = &val_sizeofMIFinstance,\n"); - fprintf(fp, " .DEVmodSize = &val_sizeofMIFmodel,\n"); - fprintf(fp, "\n"); - fprintf(fp, "#ifdef CIDER\n"); - fprintf(fp, " .DEVdump = NULL,\n"); - fprintf(fp, " .DEVacct = NULL,\n"); - fprintf(fp, "#endif\n"); - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} + rc |= fprintf(fp, + " .DEVparam = NULL,\n" + " .DEVmodParam = MIFmParam,\n" + " .DEVload = MIFload,\n" + " .DEVsetup = MIFsetup,\n" + " .DEVunsetup = MIFunsetup,\n" + " .DEVpzSetup = NULL,\n" + " .DEVtemperature = NULL,\n" + " .DEVtrunc = MIFtrunc,\n" + " .DEVfindBranch = NULL,\n" + " .DEVacLoad = MIFload,\n" + " .DEVaccept = NULL,\n" + " .DEVdestroy = MIFdestroy,\n" + " .DEVmodDelete = MIFmDelete,\n" + " .DEVdelete = MIFdelete,\n" + " .DEVsetic = NULL,\n" + " .DEVask = MIFask,\n" + " .DEVmodAsk = MIFmAsk,\n" + " .DEVpzLoad = NULL,\n" + " .DEVconvTest = MIFconvTest,\n" + " .DEVsenSetup = NULL,\n" + " .DEVsenLoad = NULL,\n" + " .DEVsenUpdate = NULL,\n" + " .DEVsenAcLoad = NULL,\n" + " .DEVsenPrint = NULL,\n" + " .DEVsenTrunc = NULL,\n" + " .DEVdisto = NULL,\n" + " .DEVnoise = NULL,\n" + " .DEVsoaCheck = NULL,\n" + " .DEVinstSize = &val_sizeofMIFinstance,\n" + " .DEVmodSize = &val_sizeofMIFmodel,\n" + "\n" + "#ifdef CIDER\n" + " .DEVdump = NULL,\n" + " .DEVacct = NULL,\n" + "#endif\n" + "};\n\n" + ); + /* Check outputs */ + if (rc < 0) { + print_error("Writing of SPICE device information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_SPICEdev */ @@ -973,202 +1068,111 @@ being created. #define BASE_STR_LEN 80 -static char *data_type_to_str(Data_Type_t type) +static const char *data_type_to_str(Data_Type_t type) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(type) { - + switch (type) { case CMPP_BOOLEAN: - strcpy(str,"MIF_BOOLEAN"); - break; - + return "MIF_BOOLEAN"; case CMPP_INTEGER: - strcpy(str,"MIF_INTEGER"); - break; - + return "MIF_INTEGER"; case CMPP_REAL: - strcpy(str,"MIF_REAL"); - break; - + return "MIF_REAL"; case CMPP_COMPLEX: - strcpy(str,"MIF_COMPLEX"); - break; - + return "MIF_COMPLEX"; case CMPP_STRING: - strcpy(str,"MIF_STRING"); - break; - - case CMPP_POINTER: - strcpy(str,"MIF_STRING"); - break; - + case CMPP_POINTER: + return "MIF_STRING"; default: print_error("INTERNAL ERROR - data_type_to_str() - Impossible data type."); + return "INVALID DATA TYPE"; } - - return(str); } /* *********************************************************************** */ -static char *port_type_to_str(Port_Type_t port) +static const char *port_type_to_str(Port_Type_t port) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(port) { - + switch (port) { case VOLTAGE: - strcpy(str,"MIF_VOLTAGE"); - break; - + return "MIF_VOLTAGE"; case DIFF_VOLTAGE: - strcpy(str,"MIF_DIFF_VOLTAGE"); - break; - + return "MIF_DIFF_VOLTAGE"; case CURRENT: - strcpy(str,"MIF_CURRENT"); - break; - + return "MIF_CURRENT"; case DIFF_CURRENT: - strcpy(str,"MIF_DIFF_CURRENT"); - break; - + return "MIF_DIFF_CURRENT"; case VSOURCE_CURRENT: - strcpy(str,"MIF_VSOURCE_CURRENT"); - break; - + return "MIF_VSOURCE_CURRENT"; case CONDUCTANCE: - strcpy(str,"MIF_CONDUCTANCE"); - break; - + return "MIF_CONDUCTANCE"; case DIFF_CONDUCTANCE: - strcpy(str,"MIF_DIFF_CONDUCTANCE"); - break; - + return "MIF_DIFF_CONDUCTANCE"; case RESISTANCE: - strcpy(str,"MIF_RESISTANCE"); - break; - + return "MIF_RESISTANCE"; case DIFF_RESISTANCE: - strcpy(str,"MIF_DIFF_RESISTANCE"); - break; - + return "MIF_DIFF_RESISTANCE"; case DIGITAL: - strcpy(str,"MIF_DIGITAL"); - break; - + return "MIF_DIGITAL"; case USER_DEFINED: - strcpy(str,"MIF_USER_DEFINED"); - break; - + return "MIF_USER_DEFINED"; default: print_error("INTERNAL ERROR - port_type_to_str() - Impossible port type."); + return "INVALID PORT TYPE"; } - - return(str); - } /* *********************************************************************** */ -static char *gen_port_type_str(Port_Type_t port) +static const char *gen_port_type_str(Port_Type_t port) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(port) { - + switch (port) { case VOLTAGE: - strcpy(str,"v"); - break; - + return "v"; case DIFF_VOLTAGE: - strcpy(str,"vd"); - break; - + return "vd"; case CURRENT: - strcpy(str,"i"); - break; - + return "i"; case DIFF_CURRENT: - strcpy(str,"id"); - break; - + return "id"; case VSOURCE_CURRENT: - strcpy(str,"vnam"); - break; - + return "vnam"; case CONDUCTANCE: - strcpy(str,"g"); - break; - + return "g"; case DIFF_CONDUCTANCE: - strcpy(str,"gd"); - break; - + return "gd"; case RESISTANCE: - strcpy(str,"h"); - break; - + return "h"; case DIFF_RESISTANCE: - strcpy(str,"hd"); - break; - + return "hd"; case DIGITAL: - strcpy(str,"d"); - break; - + return "d"; case USER_DEFINED: - strcpy(str,""); - break; - + return ""; default: - print_error("INTERNAL ERROR - gen_port_type_str() - Impossible port type."); + print_error("INTERNAL ERROR - gen_port_type_str() - " + "Impossible port type."); + return "INVALID PORT TYPE"; } +} /* end of function gen_port_type_str */ - return(str); - -} /* *********************************************************************** */ -static char *dir_to_str(Dir_t dir) +static const char *dir_to_str(Dir_t dir) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - switch(dir) { - case CMPP_IN: - strcpy(str,"MIF_IN"); - break; - + return "MIF_IN"; case CMPP_OUT: - strcpy(str,"MIF_OUT"); - break; - + return "MIF_OUT"; case CMPP_INOUT: - strcpy(str,"MIF_INOUT"); - break; - + return "MIF_INOUT"; default: print_error("INTERNAL ERROR - dir_to_str() - Impossible direction type."); + return "MIF_DIRECTION_INVALID"; } - - return(str); } @@ -1180,12 +1184,15 @@ static char *value_to_str(Data_Type_t type, Value_t value) static char *str = NULL; static int max_len = 0; - char *bool_str; + const char *bool_str; int str_len; if(str == NULL) { - str = (char *) malloc(2 * BASE_STR_LEN + 1); + if ((str = (char *) malloc(2 * BASE_STR_LEN + 1)) == (char *) NULL) { + (void) fprintf(stderr, "Unable to allocate string buffer.\n"); + return (char *) NULL; + } max_len = 2 * BASE_STR_LEN; } @@ -1212,35 +1219,38 @@ static char *value_to_str(Data_Type_t type, Value_t value) case CMPP_STRING: /* be careful, the string could conceivably be very long... */ str_len = (int) strlen(value.svalue); - if((str_len + BASE_STR_LEN) > max_len) { - str = (char *) realloc(str, (size_t) (max_len + str_len + 1)); + if ((str_len + BASE_STR_LEN) > max_len) { + size_t n_byte_alloc = max_len + str_len + 1; + void * const p = realloc(str, n_byte_alloc); + if (p == NULL) { + (void) fprintf(stderr, "Unable to resize string " + "buffer to size %zu.\n", + n_byte_alloc); + free(str); + return (char *) NULL; + } + str = (char *) p; max_len += str_len; - } + } /* end of resize */ + sprintf(str, "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, \"%s\"}", value.svalue); break; default: print_error("INTERNAL ERROR - value_to_str() - Impossible data type."); - } + } /* end of switch */ + + return str; +} /* end of function value_to_string */ - return(str); -} /* *********************************************************************** */ -static char *boolean_to_str(bool value) +static const char *boolean_to_str(bool value) { - static char *str = NULL; - - if (str == NULL) { - str = (char *) malloc(BASE_STR_LEN+1); - } - - strcpy(str, value ? "MIF_TRUE" : "MIF_FALSE"); - - return str; + return value ? "MIF_TRUE" : "MIF_FALSE"; } @@ -1248,31 +1258,17 @@ static char *boolean_to_str(bool value) static char *integer_to_str(int value) { - static char *str = NULL; - - if(str == NULL) { - str = (char *) malloc(BASE_STR_LEN + 1); - } - + static char str[3 * sizeof(int) + 1]; sprintf(str, "%d", value); - - return(str); + return str; } /* *********************************************************************** */ -static char *no_value_to_str(void) +static const char *no_value_to_str(void) { - static char *str = NULL; - - if(str == NULL) { - str = (char *) malloc(BASE_STR_LEN + 1); - } - - sprintf(str, "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}"); - - return(str); + return "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}"; }