diff --git a/src/frontend/help/help.c b/src/frontend/help/help.c index bee81e218..a02b48980 100644 --- a/src/frontend/help/help.c +++ b/src/frontend/help/help.c @@ -13,7 +13,7 @@ Modified 1999 Emmanuel Rouat #include "ngspice/hlpdefs.h" #include "ngspice/suffix.h" -extern char *cp_tildexpand(char *string); +extern char *cp_tildexpand(const char *string); char *hlp_directory; extern char *hlp_filelist[]; diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index bd2e4d64e..d26fb674a 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -20,6 +20,7 @@ Author: 1985 Wayne A. Christopher #include "ngspice/compatmode.h" #include "ngspice/cpdefs.h" +#include "ngspice/dstring.h" #include "ngspice/dvec.h" #include "ngspice/ftedefs.h" #include "ngspice/fteext.h" @@ -119,7 +120,8 @@ static void inp_stripcomments_line(char *s, bool cs); static void inp_fix_for_numparam( struct names *subckt_w_params, struct card *deck); static void inp_remove_excess_ws(struct card *deck); -static void expand_section_references(struct card *deck, char *dir_name); +static void expand_section_references(struct card *deck, + const char *dir_name); static void inp_grab_func(struct function_env *, struct card *deck); static void inp_fix_inst_calls_for_numparam( struct names *subckt_w_params, struct card *deck); @@ -163,7 +165,7 @@ static void inp_check_syntax(struct card *deck); static char *inp_spawn_brace(char *s); static char *inp_pathresolve(const char *name); -static char *inp_pathresolve_at(char *name, char *dir); +static char *inp_pathresolve_at(const char *name, const char *dir); static char *search_plain_identifier(char *str, const char *identifier); static struct nscope *inp_add_levels(struct card *deck); @@ -184,8 +186,8 @@ struct inp_read_t { int line_number; }; -static struct inp_read_t inp_read( - FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile); +struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, + bool comfile, bool intfile); #ifndef XSPICE @@ -302,8 +304,7 @@ static struct card *find_section_definition(struct card *c, char *name) return NULL; } - -static struct library *read_a_lib(char *y, char *dir_name) +static struct library *read_a_lib(const char *y, const char *dir_name) { char *yy, *y_resolved; @@ -355,7 +356,8 @@ static struct library *read_a_lib(char *y, char *dir_name) txfree(y_resolved); return lib; -} +} /* end of function read_a_lib */ + static struct names *new_names(void) @@ -587,8 +589,8 @@ static COMPATMODE_T ngspice_compat_mode(void) remove the 'level' entries from each card *-------------------------------------------------------------------------*/ -struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, - bool *expr_w_temper_p) +struct card *inp_readall(FILE *fp, const char *dir_name, + bool comfile, bool intfile, bool *expr_w_temper_p) { struct card *cc; struct inp_read_t rv; @@ -764,8 +766,8 @@ struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, } -struct inp_read_t inp_read( - FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile) +struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, + bool comfile, bool intfile) /* fp: in, pointer to file to be read, call_depth: in, nested call to fcn dir_name: in, name of directory of file to be read @@ -1266,18 +1268,19 @@ is_plain_filename(const char *p) #endif -FILE *inp_pathopen(char *name, char *mode) +FILE *inp_pathopen(const char *name, const char *mode) { - char *path = inp_pathresolve(name); + char * const path = inp_pathresolve(name); if (path) { FILE *fp = fopen(path, mode); - tfree(path); + txfree(path); return fp; } - return NULL; -} + return (FILE *) NULL; +} /* end of function inp_pathopen */ + /*-------------------------------------------------------------------------* @@ -1287,7 +1290,6 @@ FILE *inp_pathopen(char *name, char *mode) static char *inp_pathresolve(const char *name) { - char buf[BSIZE_SP]; struct variable *v; struct stat st; @@ -1297,10 +1299,17 @@ static char *inp_pathresolve(const char *name) if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) && name[0] == DIR_TERM_LINUX && isalpha_c(name[1]) && name[2] == DIR_TERM_LINUX) { - strcpy(buf, name); + DS_CREATE(ds, 100); + if (ds_cat_str(&ds, name) != 0) { + fprintf(stderr, "Unable to copy string while resolving path"); + controlled_exit(EXIT_FAILURE); + } + char *const buf = ds_get_buf(&ds); buf[0] = buf[1]; buf[1] = ':'; - return inp_pathresolve(buf); + char * const resolved_path = inp_pathresolve(buf); + ds_free(&ds); + return resolved_path; } #endif @@ -1312,55 +1321,77 @@ static char *inp_pathresolve(const char *name) /* fail if this was an absolute filename or if there is no sourcepath var */ if (is_absolute_pathname(name) || - !cp_getvar("sourcepath", CP_LIST, &v, 0)) - return NULL; - - for (; v; v = v->va_next) { - - switch (v->va_type) { - case CP_STRING: - cp_wstrip(v->va_string); - (void) sprintf(buf, "%s%s%s", - v->va_string, DIR_PATHSEP, name); - break; - case CP_NUM: - (void) sprintf(buf, "%d%s%s", v->va_num, DIR_PATHSEP, name); - break; - case CP_REAL: /* This is foolish */ - (void) sprintf(buf, "%g%s%s", v->va_real, DIR_PATHSEP, name); - break; - default: - fprintf(stderr, - "ERROR: enumeration value `CP_BOOL' or `CP_LIST' not " - "handled in inp_pathresolve\nAborting...\n"); - controlled_exit(EXIT_FAILURE); - break; - } - - if (stat(buf, &st) == 0) - return copy(buf); + !cp_getvar("sourcepath", CP_LIST, &v, 0)) { + return (char *) NULL; } - return (NULL); -} + { + DS_CREATE(ds, 100); + for (; v; v = v->va_next) { + int rc_ds; + ds_clear(&ds); /* empty buffer */ + + switch (v->va_type) { + case CP_STRING: + cp_wstrip(v->va_string); + rc_ds = ds_cat_printf(&ds, "%s%s%s", + v->va_string, DIR_PATHSEP, name); + break; + case CP_NUM: + rc_ds = ds_cat_printf(&ds, "%d%s%s", + v->va_num, DIR_PATHSEP, name); + break; + case CP_REAL: /* This is foolish */ + rc_ds = ds_cat_printf(&ds, "%g%s%s", + v->va_real, DIR_PATHSEP, name); + break; + default: + fprintf(stderr, + "ERROR: enumeration value `CP_BOOL' or `CP_LIST' " + "not handled in inp_pathresolve\nAborting...\n"); + controlled_exit(EXIT_FAILURE); + } + + if (rc_ds != 0) { /* unable to build string */ + (void) fprintf(cp_err, + "Unable to build path name in inp_pathresolve"); + controlled_exit(EXIT_FAILURE); + } + + /* Test if the file is found */ + { + const char * const buf = ds_get_buf(&ds); + if (stat(buf, &st) == 0) { + char * const buf_cpy = dup_string( + buf, ds_get_length(&ds)); + ds_free(&ds); + return buf_cpy; + } + /* Else contiue with next attempt */ + } + } /* end of loop over linked variables */ + ds_free(&ds); + } /* end of block trying to find a valid name */ + + return (char *) NULL; +} /* end of function inp_pathresolve */ -static char *inp_pathresolve_at(char *name, char *dir) + +static char *inp_pathresolve_at(const char *name, const char *dir) { - char buf[BSIZE_SP], *end; - /* if name is an absolute path name, * or if we haven't anything to prepend anyway */ - - if (is_absolute_pathname(name) || !dir || !dir[0]) + if (is_absolute_pathname(name) || !dir || !dir[0]) { return inp_pathresolve(name); + } if (name[0] == '~' && name[1] == '/') { - char *y = cp_tildexpand(name); + char * const y = cp_tildexpand(name); if (y) { - char *r = inp_pathresolve(y); - tfree(y); + char * const r = inp_pathresolve(y); + txfree(y); return r; } } @@ -1371,28 +1402,49 @@ static char *inp_pathresolve_at(char *name, char *dir) * sourcepath */ - strcpy(buf, "."); + { + DS_CREATE(ds, 100); + if (ds_cat_printf(&ds, ".%c%s", DIR_TERM, name) != 0) { + (void) fprintf(cp_err, + "Unable to build \".\" path name in inp_pathresolve_at"); + controlled_exit(EXIT_FAILURE); + } + char * const r = inp_pathresolve(ds_get_buf(&ds)); + ds_free(&ds); + if (r != (char *) NULL) { + return r; + } + } - end = strchr(buf, '\0'); - if (end[-1] != DIR_TERM) - *end++ = DIR_TERM; + { + DS_CREATE(ds, 100); + int rc_ds = 0; + rc_ds |= ds_cat_str(&ds, dir); /* copy the dir name */ + const size_t n = ds_get_length(&ds); /* end of copied dir name */ - strcpy(end, name); + /* Append a directory separator if not present already */ + const char ch_last = n > 0 ? dir[n - 1] : '\0'; + if (ch_last != DIR_TERM +#ifdef _WIN32 + && ch_last != DIR_TERM_LINUX +#endif + ) { + rc_ds |= ds_cat_char(&ds, DIR_TERM); + } + rc_ds |= ds_cat_str(&ds, name); /* append the file name */ - char *r = inp_pathresolve(buf); - if (r) + if (rc_ds != 0) { + (void) fprintf(cp_err, "Unable to build \"dir\" path name " + "in inp_pathresolve_at"); + controlled_exit(EXIT_FAILURE); + } + + char * const r = inp_pathresolve(ds_get_buf(&ds)); + ds_free(&ds); return r; + } +} /* end of function inp_pathresolve_at */ - strcpy(buf, dir); - - end = strchr(buf, '\0'); - if (end[-1] != DIR_TERM) - *end++ = DIR_TERM; - - strcpy(end, name); - - return inp_pathresolve(buf); -} /*-------------------------------------------------------------------------* @@ -2746,7 +2798,7 @@ static void inp_remove_excess_ws(struct card *c) } -static struct card *expand_section_ref(struct card *c, char *dir_name) +static struct card *expand_section_ref(struct card *c, const char *dir_name) { char *line = c->line; @@ -2847,7 +2899,7 @@ static struct card *expand_section_ref(struct card *c, char *dir_name) * just those references occuring in the given library section definition */ -static void expand_section_references(struct card *c, char *dir_name) +static void expand_section_references(struct card *c, const char *dir_name) { for (; c; c = c->nextcard) if (ciprefix(".lib", c->line)) diff --git a/src/frontend/parser/glob.c b/src/frontend/parser/glob.c index 4cdd8c8f0..469af46ee 100644 --- a/src/frontend/parser/glob.c +++ b/src/frontend/parser/glob.c @@ -390,7 +390,7 @@ static wordlist_l *brac2(const char *string, /* Expand tildes. */ -char *cp_tildexpand(char *string) +char *cp_tildexpand(const char *string) { /* Attempt to do the tilde expansion */ char * const result = tildexpand(string); diff --git a/src/include/ngspice/cpextern.h b/src/include/ngspice/cpextern.h index 52b88744a..9fa01e23e 100644 --- a/src/include/ngspice/cpextern.h +++ b/src/include/ngspice/cpextern.h @@ -79,8 +79,8 @@ extern void cp_pushcontrol(void); /* glob.c */ -extern bool cp_globmatch(char *p, char *s); -extern char *cp_tildexpand(char *string); +extern bool cp_globmatch(const char *p, const char *s); +extern char *cp_tildexpand(const char *string); extern char cp_cbrac; extern char cp_ccurl; extern char cp_comma; diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 2e892c811..70cea638c 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -214,8 +214,9 @@ extern void inp_source(const char *file); int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile); extern void inp_casefix(char *string); extern void inp_list(FILE *file, struct card *deck, struct card *extras, int type); -extern struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_temper); -extern FILE *inp_pathopen(char *name, char *mode); +struct card *inp_readall(FILE *fp, const char *dir_name, + bool comfile, bool intfile, bool *expr_w_temper_p); +extern FILE *inp_pathopen(const char *name, const char *mode); extern char *search_identifier(char *str, const char *identifier, char *str_begin); extern char *find_assignment(const char *s); extern char *find_back_assignment(const char *s, const char *start); diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 3e1c1c1f4..801d70953 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -140,7 +140,7 @@ #ifdef HAS_WINGUI #include "ngspice/wstdio.h" #define HAS_PROGREP -extern void SetAnalyse(char *Analyse, int Percent); +extern void SetAnalyse(const char *Analyse, int Percent); #endif #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER) @@ -299,7 +299,7 @@ extern int sh_vfprintf(FILE *fd, const char *format, va_list args); extern int sh_fputs(const char *input, FILE *fd); extern int sh_fputc(int input, FILE *fd); extern int sh_putc(int input, FILE *fd); -extern void SetAnalyse(char *analyse, int percent); +extern void SetAnalyse(const char *analyse, int percent); #define HAS_PROGREP diff --git a/src/misc/util.c b/src/misc/util.c index e8f1e58ce..60b5f2e49 100644 --- a/src/misc/util.c +++ b/src/misc/util.c @@ -189,43 +189,51 @@ basename(const char *name) #if defined(HAS_WINGUI) || defined(_MSC_VER) || defined(__MINGW32__) - -char * -ngdirname(const char *name) +/* This function returns the path portion of name or "." if it is NULL. + * The returned string is a new allocation that must be freed by the + * caller */ +char *ngdirname(const char *name) { - char *ret; - const char *end = NULL; - int start = 0; - - if(name && ((name[0] >= 'a' && name[0] <= 'z') || - (name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':') - start = 2; - - if(name) { - const char *p = name + start; - for(; *p; p++) - if(*p == '/' || *p == '\\') - end = p; + /* If name not given, return "." */ + if (name == (char *) NULL) { + return dup_string(".", 1); } - if(end && end == name + start) - end++; + /* Offset to start of path name after any drive letter present */ + const int start = (((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':') ? 2 : 0; - if(end) - ret = copy_substring(name, end); - else { - char *p = TMALLOC(char, 4); - ret = p; - if(start) { + /* Find last dir separator, if any, and return the input directory up to + * that separator or including it if it is the 1st char after any drive + *specification. */ + { + const char *p0 = name + start; /* 1st char past drive */ + const char *p; + for (p = p0 + strlen(name + start) - 1; p >= p0; --p) { + const char *ch_cur = *p; + if (ch_cur == '/' || ch_cur == '\\') { /* at last dir sep */ + /* Stop copy at last dir sep or right after if + * it is the first char after any drive spec. + * In the second case return "[drive]