fixed path created by ngdirname in Windows. Also added const to parameters whose arguments do not change and fixed some potential buffer overruns.
This commit is contained in:
parent
2d9110bf65
commit
a53cd3a3e9
|
|
@ -13,7 +13,7 @@ Modified 1999 Emmanuel Rouat
|
||||||
#include "ngspice/hlpdefs.h"
|
#include "ngspice/hlpdefs.h"
|
||||||
#include "ngspice/suffix.h"
|
#include "ngspice/suffix.h"
|
||||||
|
|
||||||
extern char *cp_tildexpand(char *string);
|
extern char *cp_tildexpand(const char *string);
|
||||||
|
|
||||||
char *hlp_directory;
|
char *hlp_directory;
|
||||||
extern char *hlp_filelist[];
|
extern char *hlp_filelist[];
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Author: 1985 Wayne A. Christopher
|
||||||
|
|
||||||
#include "ngspice/compatmode.h"
|
#include "ngspice/compatmode.h"
|
||||||
#include "ngspice/cpdefs.h"
|
#include "ngspice/cpdefs.h"
|
||||||
|
#include "ngspice/dstring.h"
|
||||||
#include "ngspice/dvec.h"
|
#include "ngspice/dvec.h"
|
||||||
#include "ngspice/ftedefs.h"
|
#include "ngspice/ftedefs.h"
|
||||||
#include "ngspice/fteext.h"
|
#include "ngspice/fteext.h"
|
||||||
|
|
@ -119,7 +120,8 @@ static void inp_stripcomments_line(char *s, bool cs);
|
||||||
static void inp_fix_for_numparam(
|
static void inp_fix_for_numparam(
|
||||||
struct names *subckt_w_params, struct card *deck);
|
struct names *subckt_w_params, struct card *deck);
|
||||||
static void inp_remove_excess_ws(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_grab_func(struct function_env *, struct card *deck);
|
||||||
static void inp_fix_inst_calls_for_numparam(
|
static void inp_fix_inst_calls_for_numparam(
|
||||||
struct names *subckt_w_params, struct card *deck);
|
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_spawn_brace(char *s);
|
||||||
|
|
||||||
static char *inp_pathresolve(const char *name);
|
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 char *search_plain_identifier(char *str, const char *identifier);
|
||||||
|
|
||||||
static struct nscope *inp_add_levels(struct card *deck);
|
static struct nscope *inp_add_levels(struct card *deck);
|
||||||
|
|
@ -184,8 +186,8 @@ struct inp_read_t {
|
||||||
int line_number;
|
int line_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct inp_read_t inp_read(
|
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
||||||
FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile);
|
bool comfile, bool intfile);
|
||||||
|
|
||||||
|
|
||||||
#ifndef XSPICE
|
#ifndef XSPICE
|
||||||
|
|
@ -302,8 +304,7 @@ static struct card *find_section_definition(struct card *c, char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct library *read_a_lib(const char *y, const char *dir_name)
|
||||||
static struct library *read_a_lib(char *y, char *dir_name)
|
|
||||||
{
|
{
|
||||||
char *yy, *y_resolved;
|
char *yy, *y_resolved;
|
||||||
|
|
||||||
|
|
@ -355,7 +356,8 @@ static struct library *read_a_lib(char *y, char *dir_name)
|
||||||
txfree(y_resolved);
|
txfree(y_resolved);
|
||||||
|
|
||||||
return lib;
|
return lib;
|
||||||
}
|
} /* end of function read_a_lib */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct names *new_names(void)
|
static struct names *new_names(void)
|
||||||
|
|
@ -587,8 +589,8 @@ static COMPATMODE_T ngspice_compat_mode(void)
|
||||||
remove the 'level' entries from each card
|
remove the 'level' entries from each card
|
||||||
*-------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile,
|
struct card *inp_readall(FILE *fp, const char *dir_name,
|
||||||
bool *expr_w_temper_p)
|
bool comfile, bool intfile, bool *expr_w_temper_p)
|
||||||
{
|
{
|
||||||
struct card *cc;
|
struct card *cc;
|
||||||
struct inp_read_t rv;
|
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(
|
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
||||||
FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile)
|
bool comfile, bool intfile)
|
||||||
/* fp: in, pointer to file to be read,
|
/* fp: in, pointer to file to be read,
|
||||||
call_depth: in, nested call to fcn
|
call_depth: in, nested call to fcn
|
||||||
dir_name: in, name of directory of file to be read
|
dir_name: in, name of directory of file to be read
|
||||||
|
|
@ -1266,18 +1268,19 @@ is_plain_filename(const char *p)
|
||||||
#endif
|
#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) {
|
if (path) {
|
||||||
FILE *fp = fopen(path, mode);
|
FILE *fp = fopen(path, mode);
|
||||||
tfree(path);
|
txfree(path);
|
||||||
return fp;
|
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)
|
static char *inp_pathresolve(const char *name)
|
||||||
{
|
{
|
||||||
char buf[BSIZE_SP];
|
|
||||||
struct variable *v;
|
struct variable *v;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
|
|
@ -1297,10 +1299,17 @@ static char *inp_pathresolve(const char *name)
|
||||||
if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) &&
|
if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) &&
|
||||||
name[0] == DIR_TERM_LINUX && isalpha_c(name[1]) &&
|
name[0] == DIR_TERM_LINUX && isalpha_c(name[1]) &&
|
||||||
name[2] == DIR_TERM_LINUX) {
|
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[0] = buf[1];
|
||||||
buf[1] = ':';
|
buf[1] = ':';
|
||||||
return inp_pathresolve(buf);
|
char * const resolved_path = inp_pathresolve(buf);
|
||||||
|
ds_free(&ds);
|
||||||
|
return resolved_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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
|
/* fail if this was an absolute filename or if there is no sourcepath var
|
||||||
*/
|
*/
|
||||||
if (is_absolute_pathname(name) ||
|
if (is_absolute_pathname(name) ||
|
||||||
!cp_getvar("sourcepath", CP_LIST, &v, 0))
|
!cp_getvar("sourcepath", CP_LIST, &v, 0)) {
|
||||||
return NULL;
|
return (char *) 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
/* if name is an absolute path name,
|
||||||
* or if we haven't anything to prepend anyway
|
* 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);
|
return inp_pathresolve(name);
|
||||||
|
}
|
||||||
|
|
||||||
if (name[0] == '~' && name[1] == '/') {
|
if (name[0] == '~' && name[1] == '/') {
|
||||||
char *y = cp_tildexpand(name);
|
char * const y = cp_tildexpand(name);
|
||||||
if (y) {
|
if (y) {
|
||||||
char *r = inp_pathresolve(y);
|
char * const r = inp_pathresolve(y);
|
||||||
tfree(y);
|
txfree(y);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1371,28 +1402,49 @@ static char *inp_pathresolve_at(char *name, char *dir)
|
||||||
* sourcepath
|
* 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)
|
DS_CREATE(ds, 100);
|
||||||
*end++ = DIR_TERM;
|
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 (rc_ds != 0) {
|
||||||
if (r)
|
(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;
|
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;
|
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
|
* 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)
|
for (; c; c = c->nextcard)
|
||||||
if (ciprefix(".lib", c->line))
|
if (ciprefix(".lib", c->line))
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ static wordlist_l *brac2(const char *string,
|
||||||
|
|
||||||
|
|
||||||
/* Expand tildes. */
|
/* Expand tildes. */
|
||||||
char *cp_tildexpand(char *string)
|
char *cp_tildexpand(const char *string)
|
||||||
{
|
{
|
||||||
/* Attempt to do the tilde expansion */
|
/* Attempt to do the tilde expansion */
|
||||||
char * const result = tildexpand(string);
|
char * const result = tildexpand(string);
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@ extern void cp_pushcontrol(void);
|
||||||
|
|
||||||
/* glob.c */
|
/* glob.c */
|
||||||
|
|
||||||
extern bool cp_globmatch(char *p, char *s);
|
extern bool cp_globmatch(const char *p, const char *s);
|
||||||
extern char *cp_tildexpand(char *string);
|
extern char *cp_tildexpand(const char *string);
|
||||||
extern char cp_cbrac;
|
extern char cp_cbrac;
|
||||||
extern char cp_ccurl;
|
extern char cp_ccurl;
|
||||||
extern char cp_comma;
|
extern char cp_comma;
|
||||||
|
|
|
||||||
|
|
@ -214,8 +214,9 @@ extern void inp_source(const char *file);
|
||||||
int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile);
|
int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile);
|
||||||
extern void inp_casefix(char *string);
|
extern void inp_casefix(char *string);
|
||||||
extern void inp_list(FILE *file, struct card *deck, struct card *extras, int type);
|
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);
|
struct card *inp_readall(FILE *fp, const char *dir_name,
|
||||||
extern FILE *inp_pathopen(char *name, char *mode);
|
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 *search_identifier(char *str, const char *identifier, char *str_begin);
|
||||||
extern char *find_assignment(const char *s);
|
extern char *find_assignment(const char *s);
|
||||||
extern char *find_back_assignment(const char *s, const char *start);
|
extern char *find_back_assignment(const char *s, const char *start);
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@
|
||||||
#ifdef HAS_WINGUI
|
#ifdef HAS_WINGUI
|
||||||
#include "ngspice/wstdio.h"
|
#include "ngspice/wstdio.h"
|
||||||
#define HAS_PROGREP
|
#define HAS_PROGREP
|
||||||
extern void SetAnalyse(char *Analyse, int Percent);
|
extern void SetAnalyse(const char *Analyse, int Percent);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
|
#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_fputs(const char *input, FILE *fd);
|
||||||
extern int sh_fputc(int input, FILE *fd);
|
extern int sh_fputc(int input, FILE *fd);
|
||||||
extern int sh_putc(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
|
#define HAS_PROGREP
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,43 +189,51 @@ basename(const char *name)
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAS_WINGUI) || defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(HAS_WINGUI) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
/* This function returns the path portion of name or "." if it is NULL.
|
||||||
char *
|
* The returned string is a new allocation that must be freed by the
|
||||||
ngdirname(const char *name)
|
* caller */
|
||||||
|
char *ngdirname(const char *name)
|
||||||
{
|
{
|
||||||
char *ret;
|
/* If name not given, return "." */
|
||||||
const char *end = NULL;
|
if (name == (char *) NULL) {
|
||||||
int start = 0;
|
return dup_string(".", 1);
|
||||||
|
|
||||||
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(end && end == name + start)
|
/* Offset to start of path name after any drive letter present */
|
||||||
end++;
|
const int start = (((name[0] >= 'a' && name[0] <= 'z') ||
|
||||||
|
(name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':') ? 2 : 0;
|
||||||
|
|
||||||
if(end)
|
/* Find last dir separator, if any, and return the input directory up to
|
||||||
ret = copy_substring(name, end);
|
* that separator or including it if it is the 1st char after any drive
|
||||||
else {
|
*specification. */
|
||||||
char *p = TMALLOC(char, 4);
|
{
|
||||||
ret = p;
|
const char *p0 = name + start; /* 1st char past drive */
|
||||||
if(start) {
|
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]<dir sep>" */
|
||||||
|
const char * const end = p + (p == p0);
|
||||||
|
return copy_substring(name, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No directory separator found so return "[drive]." */
|
||||||
|
{
|
||||||
|
char * const ret = TMALLOC(char, 2 + start);
|
||||||
|
char *p = ret;
|
||||||
|
if (start) { /* Add drive letter if found */
|
||||||
*p++ = name[0];
|
*p++ = name[0];
|
||||||
*p++ = name[1];
|
*p++ = name[1];
|
||||||
}
|
}
|
||||||
*p++ = '.';
|
*p++ = '.';
|
||||||
*p++ = '\0';
|
*p = '\0';
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
} /* end of function ngdirname */
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue