summaryrefslogtreecommitdiff
path: root/Build/source/libs/libgnuw32/filename.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/libgnuw32/filename.c')
-rw-r--r--Build/source/libs/libgnuw32/filename.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/Build/source/libs/libgnuw32/filename.c b/Build/source/libs/libgnuw32/filename.c
new file mode 100644
index 00000000000..5aede5152f3
--- /dev/null
+++ b/Build/source/libs/libgnuw32/filename.c
@@ -0,0 +1,392 @@
+/* Utility and Unix shadow routines for XEmacs on Windows NT.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+
+ Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */
+
+/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
+/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
+/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */
+
+#include <win32lib.h>
+
+/* Normalize filename by converting all path separators to
+ the specified separator. Also conditionally convert upper
+ case path name components to lower case.
+ Returns the index of the first meaningful char in the path
+ past any drive specifier of unc name specifier.
+ Remove any multiple path separators after a leading
+ drive specifier or double path separator.
+*/
+
+int
+normalize_filename (char *fp, char path_sep)
+{
+ char *p;
+ int ret, i;
+
+ if (fp == NULL || *fp == '\0')
+ return 0;
+
+ /* Always lower-case drive letters a-z, even if the filesystem
+ preserves case in filenames.
+ This is so filenames can be compared by string comparison
+ functions that are case-sensitive. Even case-preserving filesystems
+ do not distinguish case in drive letters. */
+ if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') {
+ *fp += 'a' - 'A';
+ }
+
+ /* Remove unneeded double slashes */
+ ret = (IS_UNC_NAME(fp) ? 2 :
+ NAME_BEGINS_WITH_DEVICE(fp) ?
+ (IS_DIR_SEP(*(fp+2)) ? 3 : 2) : IS_DIR_SEP(*fp) ? 1 : 0);
+ for (i = ret, p = fp+i;
+ IS_DIR_SEP(*p);
+ i++, p++);
+ if (i > ret) {
+ int len = strlen(fp+i);
+ /* remove unneeded slashes, for the sake of win95 */
+#if 0
+ fprintf(stderr, "moving %s to %s\n", fp+ret, fp+i);
+#endif
+ memcpy(fp+ret, fp+i, len);
+ *(char *)(fp+ret+len) = '\0';
+ }
+
+ /* conditionnally rewrite to same path_sep, slash preferably */
+ if (path_sep) {
+ for (p = fp; *p; p++)
+ if (IS_DIR_SEP(*p))
+ *p = path_sep;
+ }
+
+#if 0
+ fprintf(stderr, "normalize_filename returned (%d) %s\n", ret, fp);
+#endif
+
+ return ret;
+}
+
+
+/* Destructively turn backslashes into slashes. */
+void
+dostounix_filename (char *p)
+{
+ normalize_filename (p, '/');
+}
+
+/* Destructively turn slashes into backslashes. */
+void
+unixtodos_filename (char *p)
+{
+ normalize_filename (p, '\\');
+}
+
+/* Quote file name. */
+char *
+quote_filename(char *name)
+{
+ int len = strlen(name);
+ char *quoted_name;
+ if (strchr(name, ' ') && *name != '"') {
+ quoted_name = xmalloc(len+3);
+ memcpy(quoted_name+1, name, len);
+ *quoted_name = '"';
+ *(quoted_name+len+1) = '"';
+ *(quoted_name+len+2) = '\0';
+ }
+ else {
+ quoted_name = xstrdup(name);
+ }
+ return quoted_name;
+}
+
+/* Unquote file name */
+char *
+unquote_filename(char *name)
+{
+ int len = strlen(name);
+ if (*name == '"' && *(name + len - 1) == '"') {
+ memmove(name, name+1, len-2);
+ *(name + len - 2) = '\0';
+ }
+ return name;
+}
+
+
+/* Remove all CR's that are followed by a LF.
+ (From msdos.c...probably should figure out a way to share it,
+ although this code isn't going to ever change.) */
+int
+crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count)
+{
+ unsigned char *np = buf;
+ unsigned char *startp = buf;
+ unsigned char *endp = buf + n;
+
+ if (n == 0)
+ return n;
+ while (buf < endp - 1)
+ {
+ if (*buf == 0x0a)
+ (*lf_count)++;
+ if (*buf == 0x0d)
+ {
+ if (*(++buf) != 0x0a)
+ *np++ = 0x0d;
+ }
+ else
+ *np++ = *buf++;
+ }
+ if (buf < endp)
+ {
+ if (*buf == 0x0a)
+ (*lf_count)++;
+ *np++ = *buf++;
+ }
+ return np - startp;
+}
+
+/* Parse the root part of file name, if present. Return length and
+ optionally store pointer to char after root. */
+int
+_parse_root (char * name, char ** pPath)
+{
+ char * start = name;
+
+ if (name == NULL)
+ return 0;
+
+ /* find the root name of the volume if given */
+ if (isalpha (name[0]) && name[1] == ':')
+ {
+ /* skip past drive specifier */
+ name += 2;
+ if (IS_DIR_SEP (name[0]))
+ name++;
+ }
+ else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1]))
+ {
+ int slashes = 2;
+ name += 2;
+ do
+ {
+ if (IS_DIR_SEP (*name) && --slashes == 0)
+ break;
+ name++;
+ }
+ while ( *name );
+ if (IS_DIR_SEP (name[0]))
+ name++;
+ }
+
+ if (pPath)
+ *pPath = name;
+
+ return name - start;
+}
+
+/* Get long base name for name; name is assumed to be absolute. */
+static int
+get_long_basename (char * name, char * buf, int size)
+{
+ WIN32_FIND_DATA find_data;
+ HANDLE dir_handle;
+ int len = 0;
+#ifdef PIGSFLY
+ char *p;
+
+ /* If the last component of NAME has a wildcard character,
+ return it as the basename. */
+ p = name + strlen (name);
+ while (*p != '\\' && *p != ':' && p > name) p--;
+ if (p > name) p++;
+ if (strchr (p, '*') || strchr (p, '?'))
+ {
+ if ((len = strlen (p)) < size)
+ memcpy (buf, p, len + 1);
+ else
+ len = 0;
+ return len;
+ }
+#endif
+
+ dir_handle = FindFirstFile (name, &find_data);
+ if (dir_handle != INVALID_HANDLE_VALUE)
+ {
+ if ((len = strlen (find_data.cFileName)) < size)
+ memcpy (buf, find_data.cFileName, len + 1);
+ else
+ len = 0;
+ FindClose (dir_handle);
+ }
+ return len;
+}
+
+/* Get long name for file, if possible (assumed to be absolute). */
+BOOL
+win32_get_long_filename (char * name, char * buf, int size)
+{
+ char * o = buf;
+ char * p;
+ char * q;
+ char full[ MAX_PATH ];
+ int len;
+
+ len = strlen (name);
+ if (len >= MAX_PATH)
+ return FALSE;
+
+ /* Use local copy for destructive modification. */
+ memcpy (full, name, len+1);
+ unixtodos_filename (full);
+
+ /* Copy root part verbatim. */
+ len = _parse_root (full, &p);
+ memcpy (o, full, len);
+ o += len;
+ size -= len;
+
+ do
+ {
+ q = p;
+ p = strchr (q, '\\');
+ if (p) *p = '\0';
+ len = get_long_basename (full, o, size);
+ if (len > 0)
+ {
+ o += len;
+ size -= len;
+ if (p != NULL)
+ {
+ *p++ = '\\';
+ if (size < 2)
+ return FALSE;
+ *o++ = '\\';
+ size--;
+ *o = '\0';
+ }
+ }
+ else
+ return FALSE;
+ }
+ while (p != NULL && *p);
+
+ return TRUE;
+}
+
+/* Map filename to a legal 8.3 name if necessary. */
+const char *
+map_win32_filename (const char * name, const char ** pPath)
+{
+ static char shortname[MAX_PATH];
+ char * str = shortname;
+ char c;
+ const char * path;
+ const char * save_name = name;
+
+ if (is_fat_volume (name, &path)) /* truncate to 8.3 */
+ {
+ register int left = 8; /* maximum number of chars in part */
+ register int extn = 0; /* extension added? */
+ register int dots = 2; /* maximum number of dots allowed */
+
+ while (name < path)
+ *str++ = *name++; /* skip past UNC header */
+
+ while ((c = *name++))
+ {
+ switch ( c )
+ {
+ case '\\':
+ case '/':
+ *str++ = '\\';
+ extn = 0; /* reset extension flags */
+ dots = 2; /* max 2 dots */
+ left = 8; /* max length 8 for main part */
+ break;
+ case ':':
+ *str++ = ':';
+ extn = 0; /* reset extension flags */
+ dots = 2; /* max 2 dots */
+ left = 8; /* max length 8 for main part */
+ break;
+ case '.':
+ if ( dots )
+ {
+ /* Convert path components of the form .xxx to _xxx,
+ but leave . and .. as they are. This allows .emacs
+ to be read as _emacs, for example. */
+
+ if (! *name ||
+ *name == '.' ||
+ IS_DIR_SEP (*name))
+ {
+ *str++ = '.';
+ dots--;
+ }
+ else
+ {
+ *str++ = '_';
+ left--;
+ dots = 0;
+ }
+ }
+ else if ( !extn )
+ {
+ *str++ = '.';
+ extn = 1; /* we've got an extension */
+ left = 3; /* 3 chars in extension */
+ }
+ else
+ {
+ /* any embedded dots after the first are converted to _ */
+ *str++ = '_';
+ }
+ break;
+ case '~':
+ case '#': /* don't lose these, they're important */
+ if ( ! left )
+ str[-1] = c; /* replace last character of part */
+ /* FALLTHRU */
+ default:
+ if ( left )
+ {
+ *str++ = tolower (c); /* map to lower case (looks nicer) */
+ left--;
+ dots = 0; /* started a path component */
+ }
+ break;
+ }
+ }
+ *str = '\0';
+ }
+ else
+ {
+ strcpy (shortname, name);
+ unixtodos_filename (shortname);
+ }
+
+ if (pPath)
+ *pPath = shortname + (path - save_name);
+
+ return shortname;
+}