⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 routines.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		file.isExecutable = (boolean) ((status.st_mode &
		    (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
		file.isSetuid = (boolean) ((status.st_mode & S_ISUID) != 0);
		file.size = status.st_size;
	    }
	}
    }
    return &file;
}

extern boolean doesFileExist (const char *const fileName)
{
    fileStatus *status = eStat (fileName);
    return status->exists;
}

extern boolean isRecursiveLink (const char* const dirName)
{
    boolean result = FALSE;
    fileStatus *status = eStat (dirName);
    if (status->isSymbolicLink)
    {
	char* const path = absoluteFilename (dirName);
	while (path [strlen (path) - 1] == PATH_SEPARATOR)
	    path [strlen (path) - 1] = '\0';
	while (! result  &&  strlen (path) > (size_t) 1)
	{
	    char *const separator = strrchr (path, PATH_SEPARATOR);
	    if (separator == NULL)
		break;
	    else if (separator == path)	/* backed up to root directory */
		*(separator + 1) = '\0';
	    else
		*separator = '\0';
	    result = isSameFile (path, dirName);
	}
	eFree (path);
    }
    return result;
}

#ifndef HAVE_FGETPOS

extern int fgetpos (FILE *stream, fpos_t *pos)
{
    int result = 0;

    *pos = ftell (stream);
    if (*pos == -1L)
	result = -1;

    return result;
}

extern int fsetpos (FILE *stream, fpos_t const *pos)
{
    return fseek (stream, *pos, SEEK_SET);
}

#endif

/*
 *  Pathname manipulation (O/S dependent!!!)
 */

static boolean isPathSeparator (const int c)
{
    boolean result;
#if defined (MSDOS_STYLE_PATH) || defined (VMS)
    result = (boolean) (strchr (PathDelimiters, c) != NULL);
#else
    result = (boolean) (c == PATH_SEPARATOR);
#endif
    return result;
}

#if ! defined (HAVE_STAT_ST_INO)

static void canonicalizePath (char *const path __unused__)
{
#if defined (MSDOS_STYLE_PATH)
    char *p;
    for (p = path  ;  *p != '\0'  ;  ++p)
	if (isPathSeparator (*p)  &&  *p != ':')
	    *p = PATH_SEPARATOR;
#endif
}

#endif

extern boolean isSameFile (const char *const name1, const char *const name2)
{
    boolean result = FALSE;
#if defined (HAVE_STAT_ST_INO)
    struct stat stat1, stat2;

    if (stat (name1, &stat1) == 0  &&  stat (name2, &stat2) == 0)
	result = (boolean) (stat1.st_ino == stat2.st_ino);
#else
    {
	char *const n1 = absoluteFilename (name1);
	char *const n2 = absoluteFilename (name2);
	canonicalizePath (n1);
	canonicalizePath (n2);
# if defined (CASE_INSENSITIVE_FILENAMES)
	result = (boolean) (strcasecmp (n1, n2) == 0);
#else
	result = (boolean) (strcmp (n1, n2) == 0);
#endif
	free (n1);
	free (n2);
    }
#endif
    return result;
}

extern const char *baseFilename (const char *const filePath)
{
#if defined (MSDOS_STYLE_PATH) || defined (VMS)
    const char *tail = NULL;
    unsigned int i;

    /*  Find whichever of the path delimiters is last.
     */
    for (i = 0  ;  i < strlen (PathDelimiters)  ;  ++i)
    {
	const char *sep = strrchr (filePath, PathDelimiters [i]);

	if (sep > tail)
	    tail = sep;
    }
#else
    const char *tail = strrchr (filePath, PATH_SEPARATOR);
#endif
    if (tail == NULL)
	tail = filePath;
    else
	++tail;			/* step past last delimiter */
#ifdef VAXC
    {
	/* remove version number from filename */
	char *p = strrchr ((char *) tail, ';');
	if (p != NULL)
	    *p = '\0';
    }
#endif

    return tail;
}

extern const char *fileExtension (const char *const fileName)
{
    const char *extension;
    const char *pDelimiter = NULL;
    const char *const base = baseFilename (fileName);
#ifdef QDOS
    pDelimiter = strrchr (base, '_');
#endif
    if (pDelimiter == NULL)
        pDelimiter = strrchr (base, '.');

    if (pDelimiter == NULL)
	extension = "";
    else
	extension = pDelimiter + 1;	/* skip to first char of extension */

    return extension;
}

extern boolean isAbsolutePath (const char *const path)
{
    boolean result = FALSE;
#if defined (MSDOS_STYLE_PATH)
    if (isPathSeparator (path [0]))
	result = TRUE;
    else if (isalpha (path [0])  &&  path [1] == ':')
    {
	if (isPathSeparator (path [2]))
	    result = TRUE;
	else
	    /*  We don't support non-absolute file names with a drive
	     *  letter, like `d:NAME' (it's too much hassle).
	     */
	    error (FATAL,
		"%s: relative file names with drive letters not supported",
		path);
    }
#elif defined (VMS)
    result = (boolean) (strchr (path, ':') != NULL);
#else
    result = isPathSeparator (path [0]);
#endif
    return result;
}

extern vString *combinePathAndFile (
    const char *const path, const char *const file)
{
    vString *const filePath = vStringNew ();
#ifdef VMS
    const char *const directoryId = strstr (file, ".DIR;1");

    if (directoryId == NULL)
    {
	const char *const versionId = strchr (file, ';');

	vStringCopyS (filePath, path);
	if (versionId == NULL)
	    vStringCatS (filePath, file);
	else
	    vStringNCatS (filePath, file, versionId - file);
	vStringCopyToLower (filePath, filePath);
    }
    else
    {
	/*  File really is a directory; append it to the path.
	 *  Gotcha: doesn't work with logical names.
	 */
	vStringNCopyS (filePath, path, strlen (path) - 1);
	vStringPut (filePath, '.');
	vStringNCatS (filePath, file, directoryId - file);
	if (strchr (path, '[') != NULL)
	    vStringPut (filePath, ']');
	else
	    vStringPut (filePath, '>');
	vStringTerminate (filePath);
    }
#else
    const int lastChar = path [strlen (path) - 1];
    boolean terminated = isPathSeparator (lastChar);

    vStringCopyS (filePath, path);
    if (! terminated)
    {
	vStringPut (filePath, OUTPUT_PATH_SEPARATOR);
	vStringTerminate (filePath);
    }
    vStringCatS (filePath, file);
#endif

    return filePath;
}

/* Return a newly-allocated string whose contents concatenate those of
 * s1, s2, s3.
 * Routine adapted from Gnu etags.
 */
static char* concat (const char *s1, const char *s2, const char *s3)
{
  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  char *result = xMalloc (len1 + len2 + len3 + 1, char);

  strcpy (result, s1);
  strcpy (result + len1, s2);
  strcpy (result + len1 + len2, s3);
  result [len1 + len2 + len3] = '\0';

  return result;
}

/* Return a newly allocated string containing the absolute file name of FILE
 * given CWD (which should end with a slash).
 * Routine adapted from Gnu etags.
 */
extern char* absoluteFilename (const char *file)
{
    char *slashp, *cp;
    char *res = NULL;
    if (isAbsolutePath (file))
    {
#ifdef MSDOS_STYLE_PATH
	if (file [1] == ':')
	    res = eStrdup (file);
	else
	{
	    char drive [3];
	    sprintf (drive, "%c:", currentdrive ());
	    res = concat (drive, file, "");
	}
#else
	res = eStrdup (file);
#endif
    }
    else
	res = concat (CurrentDirectory, file, "");

    /* Delete the "/dirname/.." and "/." substrings. */
    slashp = strchr (res, PATH_SEPARATOR);
    while (slashp != NULL  &&  slashp [0] != '\0')
    {
	if (slashp[1] == '.')
	{
	    if (slashp [2] == '.' &&
		(slashp [3] == PATH_SEPARATOR || slashp [3] == '\0'))
	    {
		cp = slashp;
		do
		    cp--;
		while (cp >= res  &&  ! isAbsolutePath (cp));
		if (cp < res)
		    cp = slashp;/* the absolute name begins with "/.." */
#ifdef MSDOS_STYLE_PATH
		/* Under MSDOS and NT we get `d:/NAME' as absolute file name,
		 * so the luser could say `d:/../NAME'. We silently treat this
		 * as `d:/NAME'.
		 */
		else if (cp [0] != PATH_SEPARATOR)
		    cp = slashp;
#endif
		strcpy (cp, slashp + 3);
		slashp = cp;
		continue;
	    }
	    else if (slashp [2] == PATH_SEPARATOR  ||  slashp [2] == '\0')
	    {
		strcpy (slashp, slashp + 2);
		continue;
	    }
	}
	slashp = strchr (slashp + 1, PATH_SEPARATOR);
    }

    if (res [0] == '\0')
	return eStrdup ("/");
    else
    {
#ifdef MSDOS_STYLE_PATH
	/* Canonicalize drive letter case. */
	if (res [1] == ':'  &&  islower (res [0]))
	    res [0] = toupper (res [0]);
#endif

	return res;
    }
}

/* Return a newly allocated string containing the absolute file name of dir
 * where `file' resides given `CurrentDirectory'.
 * Routine adapted from Gnu etags.
 */
extern char* absoluteDirname (char *file)
{
    char *slashp, *res;
    char save;
    slashp = strrchr (file, PATH_SEPARATOR);
    if (slashp == NULL)
	res = eStrdup (CurrentDirectory);
    else
    {
	save = slashp [1];
	slashp [1] = '\0';
	res = absoluteFilename (file);
	slashp [1] = save;
    }
    return res;
}

/* Return a newly allocated string containing the file name of FILE relative
 * to the absolute directory DIR (which should end with a slash).
 * Routine adapted from Gnu etags.
 */
extern char* relativeFilename (const char *file, const char *dir)
{
    const char *fp, *dp;
    char *absdir, *res;
    int i;

    /* Find the common root of file and dir (with a trailing slash). */
    absdir = absoluteFilename (file);
    fp = absdir;
    dp = dir;
    while (*fp++ == *dp++)
	continue;
    fp--;
    dp--;			/* back to the first differing char */
    do
    {				/* look at the equal chars until path sep */
	if (fp == absdir)
	    return absdir;	/* first char differs, give up */
	fp--;
	dp--;
    } while (*fp != PATH_SEPARATOR);

    /* Build a sequence of "../" strings for the resulting relative file name.
     */
    i = 0;
    while ((dp = strchr (dp + 1, PATH_SEPARATOR)) != NULL)
	i += 1;
    res = xMalloc (3 * i + strlen (fp + 1) + 1, char);
    res [0] = '\0';
    while (i-- > 0)
	strcat (res, "../");

    /* Add the file name relative to the common root of file and dir. */
    strcat (res, fp + 1);
    free (absdir);

    return res;
}

extern FILE *tempFile (const char *const mode, char **const pName)
{
    char *name;
    FILE *fp;
    int fd;
#if defined(HAVE_MKSTEMP)
    const char *const pattern = "tags.XXXXXX";
    const char *tmpdir = NULL;
    fileStatus *file = eStat (ExecutableProgram);
    if (! file->isSetuid)
	tmpdir = getenv ("TMPDIR");
    if (tmpdir == NULL)
	tmpdir = TMPDIR;
    name = xMalloc (strlen (tmpdir) + 1 + strlen (pattern) + 1, char);
    sprintf (name, "%s%c%s", tmpdir, OUTPUT_PATH_SEPARATOR, pattern);
    fd = mkstemp (name);
#elif defined(HAVE_TEMPNAM)
    name = tempnam (TMPDIR, "tags");
    if (name == NULL)
	error (FATAL | PERROR, "cannot allocate temporary file name");
    fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
#else
    name = xMalloc (L_tmpnam, char);
    if (tmpnam (name) != name)
	error (FATAL | PERROR, "cannot assign temporary file name");
    fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
#endif
    if (fd == -1)
	error (FATAL | PERROR, "cannot open temporary file");
    fp = fdopen (fd, mode);
    if (fp == NULL)
	error (FATAL | PERROR, "cannot open temporary file");
    DebugStatement (
	debugPrintf (DEBUG_STATUS, "opened temporary file %s\n", name); )
    Assert (*pName == NULL);
    *pName = name;
    return fp;
}

/* vi:set tabstop=8 shiftwidth=4: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -