return make_temp_name (prefix, 0);
}
-/* The following function does a lot of work with \0-terminated strings.
- To avoid extra calls to strlen and strcat, we maintain an important
- lengths explicitly. This macro is used to check whether we're in sync. */
-#ifdef ENABLE_CHECKING
-#define CHECK_LENGTH(str, len) (eassert (strlen (str) == len), len)
-#else
-#define CHECK_LENGTH(str, len) (len)
-#endif /* ENABLE_CHECKING */
-
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
doc: /* Convert filename NAME to absolute, and canonicalize it.
Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
/* These point to SDATA and need to be careful with string-relocation
during GC (via DECODE_FILE). */
char *nm;
+ char *nmlim;
const char *newdir;
+ const char *newdirlim;
/* This should only point to alloca'd data. */
char *target;
struct passwd *pw;
#ifdef DOS_NT
int drive = 0;
- bool collapse_newdir = 1;
+ bool collapse_newdir = true;
bool is_escaped = 0;
#endif /* DOS_NT */
- ptrdiff_t length, newdirlen, nmlen, nbytes;
+ ptrdiff_t length, nbytes;
Lisp_Object handler, result, handled_name;
bool multibyte;
Lisp_Object hdir;
/* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */
nm = xlispstrdupa (name);
- nmlen = SBYTES (name);
+ nmlim = nm + SBYTES (name);
#ifdef DOS_NT
/* Note if special escape prefix is present, but remove for now. */
if (nm[0] == '/' && nm[1] == ':')
{
is_escaped = 1;
- nmlen -= 2;
nm += 2;
}
if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
{
drive = (unsigned char) nm[0];
- nmlen -= 2;
nm += 2;
}
colon when stripping the drive letter. Otherwise, this expands to
"//somedir". */
if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
- nmlen--, nm++;
+ nm++;
/* Discard any previous drive specifier if nm is now in UNC format. */
if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])
if (IS_DIRECTORY_SEP (nm[1]))
{
if (strcmp (nm, SSDATA (name)) != 0)
- name = make_specified_string
- (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
+ name = make_specified_string (nm, -1, nmlim - nm, multibyte);
}
else
#endif
#else /* not DOS_NT */
if (strcmp (nm, SSDATA (name)) == 0)
return name;
- return make_specified_string
- (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
+ return make_specified_string (nm, -1, nmlim - nm, multibyte);
#endif /* not DOS_NT */
}
}
return an absolute name, if the final prefix is not absolute we
append it to the current working directory. */
- newdir = 0;
- newdirlen = -1;
+ newdir = newdirlim = 0;
if (nm[0] == '~') /* prefix ~ */
{
Lisp_Object tem;
if (!(newdir = egetenv ("HOME")))
- newdir = "";
- nmlen--, nm++;
+ newdir = newdirlim = "";
+ nm++;
/* `egetenv' may return a unibyte string, which will bite us since
we expect the directory to be multibyte. */
#ifdef WINDOWSNT
else
#endif
tem = build_string (newdir);
- newdirlen = SBYTES (tem);
+ newdirlim = newdir + SBYTES (tem);
if (multibyte && !STRING_MULTIBYTE (tem))
{
hdir = DECODE_FILE (tem);
newdir = SSDATA (hdir);
- newdirlen = SBYTES (hdir);
+ newdirlim = newdir + SBYTES (hdir);
}
#ifdef DOS_NT
- collapse_newdir = 0;
+ collapse_newdir = false;
#endif
}
else /* ~user/filename */
bite us since we expect the directory to be
multibyte. */
tem = build_string (newdir);
- newdirlen = SBYTES (tem);
+ newdirlim = newdir + SBYTES (tem);
if (multibyte && !STRING_MULTIBYTE (tem))
{
hdir = DECODE_FILE (tem);
newdir = SSDATA (hdir);
- newdirlen = SBYTES (hdir);
+ newdirlim = newdir + SBYTES (hdir);
}
- nmlen -= (p - nm);
nm = p;
#ifdef DOS_NT
- collapse_newdir = 0;
+ collapse_newdir = false;
#endif
}
Lisp_Object tem = build_string (adir);
tem = DECODE_FILE (tem);
- newdirlen = SBYTES (tem);
- memcpy (adir, SSDATA (tem), newdirlen + 1);
+ newdirlim = adir + SBYTES (tem);
+ memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
}
}
if (!adir)
adir[1] = ':';
adir[2] = '/';
adir[3] = 0;
- newdirlen = 3;
+ newdirlim = adir + 3;
}
newdir = adir;
}
&& !newdir)
{
newdir = SSDATA (default_directory);
- newdirlen = SBYTES (default_directory);
+ newdirlim = newdir + SBYTES (default_directory);
#ifdef DOS_NT
/* Note if special escape prefix is present, but remove for now. */
if (newdir[0] == '/' && newdir[1] == ':')
{
is_escaped = 1;
- newdirlen -= 2;
newdir += 2;
}
#endif
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = (unsigned char) newdir[0];
- newdirlen -= 2;
newdir += 2;
}
if (!IS_DIRECTORY_SEP (nm[0]))
{
+ ptrdiff_t nmlen = nmlim - nm;
+ ptrdiff_t newdirlen = newdirlim - newdir;
char *tmp = alloca (newdirlen + file_name_as_directory_slop
- + CHECK_LENGTH (nm, nmlen) + 1);
- nbytes = file_name_as_directory (tmp, newdir, newdirlen,
- multibyte);
- memcpy (tmp + nbytes, nm, nmlen + 1);
- nmlen += nbytes;
+ + nmlen + 1);
+ ptrdiff_t dlen = file_name_as_directory (tmp, newdir, newdirlen,
+ multibyte);
+ memcpy (tmp + dlen, nm, nmlen + 1);
nm = tmp;
+ nmlim = nm + dlen + nmlen;
}
adir = alloca (adir_size);
if (drive)
Lisp_Object tem = build_string (adir);
tem = DECODE_FILE (tem);
- newdirlen = SBYTES (tem);
- memcpy (adir, SSDATA (tem), newdirlen + 1);
+ newdirlim = adir + SBYTES (tem);
+ memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
}
else
- newdirlen = strlen (adir);
+ newdirlim = adir + strlen (adir);
newdir = adir;
}
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = newdir[0];
- newdirlen -= 2;
newdir += 2;
}
if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])
&& !IS_DIRECTORY_SEP (newdir[2]))
{
- char *adir = strcpy (alloca (newdirlen + 1), newdir);
+ char *adir = strcpy (alloca (newdirlim - newdir + 1), newdir);
char *p = adir + 2;
while (*p && !IS_DIRECTORY_SEP (*p)) p++;
p++;
while (*p && !IS_DIRECTORY_SEP (*p)) p++;
*p = 0;
newdir = adir;
- newdirlen = strlen (adir);
+ newdirlim = newdir + strlen (adir);
}
else
#endif
- newdirlen = 0, newdir = "";
+ newdir = newdirlim = "";
}
}
#endif /* DOS_NT */
- if (newdir)
- {
- /* Ignore any slash at the end of newdir, unless newdir is
- just "/" or "//". */
- length = CHECK_LENGTH (newdir, newdirlen);
- while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
- && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
- length--;
- }
- else
- length = 0;
+ /* Ignore any slash at the end of newdir, unless newdir is
+ just "/" or "//". */
+ length = newdirlim - newdir;
+ while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
+ && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
+ length--;
/* Now concatenate the directory and name to new space in the stack frame. */
- tlen = length + file_name_as_directory_slop + CHECK_LENGTH (nm, nmlen) + 1;
+ tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1;
#ifdef DOS_NT
/* Reserve space for drive specifier and escape prefix, since either
or both may need to be inserted. (The Microsoft x86 compiler
nbytes = file_name_as_directory (target, newdir, length, multibyte);
}
- memcpy (target + nbytes, nm, nmlen + 1);
+ memcpy (target + nbytes, nm, nmlim - nm + 1);
/* Now canonicalize by removing `//', `/.' and `/foo/..' if they
appear. */