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

📄 main.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
	sprintf(filePath, "%s%c%s", path, PATH_SEPARATOR, file);
#else
    if ((path[strlen(path) - 1]) == PATH_SEPARATOR)
	sprintf(filePath, "%s%s", path, file);
    else
	sprintf(filePath, "%s%c%s", path, PATH_SEPARATOR, file);
#endif
}

/*----------------------------------------------------------------------------
 *  File extension and language handling
 *--------------------------------------------------------------------------*/

static const char *findExtension( fileName )
    const char *const fileName;
{
    const char *extension;
    const char *const start = strrchr(fileName, '.');	/* find last '.' */

    if (start == NULL)
	extension = "";
    else
	extension = start + 1;		/* skip to character after '.' */

    return extension;
}

/*  Determines whether the specified file name is considered to be a header
 *  file for the purposes of determining whether enclosed tags are global or
 *  static.
 */
static boolean isFileHeader( fileName )
    const char *const fileName;
{
    const char *const extension = findExtension(fileName);
    boolean header = FALSE;		    /* default unless match found */
    int i;

    for (i = 0 ; Option.headerExt[i] != NULL ; ++i)
    {
	if (strcmp(Option.headerExt[i], extension) == 0)
	{
	    header = TRUE;		    /* found in list */
	    break;
	}
    }
    return header;
}

static boolean isExtensionInList( extension, list )
    const char *const extension;
    const char *const *const list;
{
    boolean isKnown = FALSE;

    if (list != NULL)
    {
	const char *const *pExtension = list;

	while (! isKnown  &&  *pExtension != NULL)
	{
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
	    if (strequiv(extension, *pExtension))
#else
	    if (strcmp(extension, *pExtension) == 0)
#endif
		isKnown = TRUE;
	    ++pExtension;
	}
    }
    return isKnown;
}

static langType getExtensionLanguage( extension )
    const char *const extension;
{
    unsigned int i;
    langType language = LANG_IGNORE;

    for (i = 0  ;  i < (int)LANG_COUNT  ;  ++i)
    {
	if (isExtensionInList(extension, Option.langMap[i]))
	{
	    language = (langType)i;
	    break;
	}
    }
    return language;
}

static langType getFileLanguage( fileName )
    const char *const fileName;
{
    const char *const extension = findExtension(fileName);
    langType language;

    if (Option.language != LANG_AUTO)
	language = Option.language;
    else if (isFileHeader(fileName))
	language = LANG_CPP;
    else if (extension[0] == '\0')
	language = LANG_IGNORE;		/* ignore files with no extension */
    else
	language = getExtensionLanguage(extension);

    return language;
}

/*----------------------------------------------------------------------------
 *  Tag file management
 *--------------------------------------------------------------------------*/

static boolean isValidTagAddress( excmd )
    const char *const excmd;
{
    boolean isValid = FALSE;

    if (strchr("/?", excmd[0]) != NULL)
	isValid = TRUE;
    else
    {
	char *address = (char *)malloc(strlen(excmd) + 1);

	if (address != NULL)
	{
	    if (sscanf(excmd, "%[^;\n]", address) == 1  &&
		strspn(address,"0123456789") == strlen(address))
		    isValid = TRUE;
	    free(address);
	}
    }
    return isValid;
}

static boolean isCtagsLine( line )
    const char *const line;
{
    enum fieldList { TAG, TAB1, SRC_FILE, TAB2, EXCMD, NUM_FIELDS };
    boolean ok = FALSE;			/* we assume not unless confirmed */
    const size_t fieldLength = strlen(line) + 1;
    char *const fields = (char *)malloc((size_t)NUM_FIELDS * fieldLength);

    if (fields == NULL)
	error(FATAL, "Cannot analyze tag file");
    else
    {
#define field(x)	(fields + ((size_t)(x) * fieldLength))

	const int numFields = sscanf(line, "%[^\t]%[\t]%[^\t]%[\t]%[^\n]",
				     field(TAG), field(TAB1), field(SRC_FILE),
				     field(TAB2), field(EXCMD));

	/*  There must be exactly five fields: two tab fields containing
	 *  exactly one tab each, the tag must not begin with "#", and the
	 *  file name should not end with ";", and the excmd must be
	 *  accceptable.
	 *
	 *  These conditions will reject tag-looking lines like:
	 *      int	a;	<C-comment>
	 *      #define	LABEL	<C-comment>
	 */
	if (numFields == NUM_FIELDS   &&
	    strlen(field(TAB1)) == 1  &&
	    strlen(field(TAB2)) == 1  &&
	    field(TAG)[0] != '#'      &&
	    field(SRC_FILE)[strlen(field(SRC_FILE)) - 1] != ';'  &&
	    isValidTagAddress(field(EXCMD)))
		ok = TRUE;

	free(fields);
    }
    return ok;
}

static boolean isEtagsLine( line )
    const char *const line;
{
    const char *const magic = "\f\n";

    return (boolean)(strncmp(line, magic, strlen(magic)) == 0);
}

static boolean isTagFile( filename )
    const char *const filename;
{
    boolean ok = FALSE;			/* we assume not unless confirmed */
    FILE *const fp = fopen(filename, "r");

    if (fp == NULL  &&  errno == ENOENT)
	ok = TRUE;
    else if (fp != NULL)
    {
	const char *line = readLine(&TagFile.line, fp);

	if (line == NULL)
	    ok = TRUE;
	else if (Option.etags)		/* check for etags magic number */
	    ok = isEtagsLine(line);
	else
	    ok = isCtagsLine(line);
	fclose(fp);
    }
    return ok;
}

static void openTagFile( toStdout )
    const boolean toStdout;
{
    static char tempName[L_tmpnam];

    /*  Open the tags File.
     */
    if (toStdout)
    {
	TagFile.name = tmpnam(tempName);
	TagFile.fp = fopen(TagFile.name, "w");
    }
    else
    {
	const char *const fname  = Option.tagFileName;
	const boolean fileExists = doesFileExist(fname);

	TagFile.name = fname;
	if (fileExists  &&  ! isTagFile(fname))
	    error(FATAL,
	      "\"%s\" doesn't look like a tag file; I refuse to overwrite it.",
		  fname);
	if (Option.append  &&  fileExists)
	{
	    TagFile.fp = fopen(fname, "r+");
	    if (TagFile.fp != NULL)
	    {
		TagFile.numTags.prev = updatePseudoTags();
		fseek(TagFile.fp, 0L, SEEK_END);
	    }
	}
	else
	{
	    TagFile.fp = fopen(fname, "w");
	    if (TagFile.fp != NULL)
		addPseudoTags();
	}
    }
    if (TagFile.fp == NULL)
    {
	error(FATAL | PERROR, "cannot open tag file");
	exit(1);
    }
}

#ifdef USE_REPLACEMENT_TRUNCATE

static int copyChars __ARGS((FILE *const fpFrom, FILE *const fpTo, const off_t size));
static int copyFile __ARGS((const char *const from, const char *const to, const off_t size));
static int replacementTruncate __ARGS((const char *const name, const off_t size));

static int copyChars( fpFrom, fpTo, size )
    FILE *const fpFrom;
    FILE *const fpTo;
    const off_t size;
{
    off_t count;
    int result = -1;

    for (count = 0  ;  count < size  ;  ++count)
    {
	const int c = getc(fpFrom);

	if (c == EOF  ||  putc(c, fpTo) == EOF)
	    break;
    }
    if (count == size)
	result = 0;
    return result;
}

static int copyFile( from, to, size )
    const char *const from;
    const char *const to;
    const off_t size;
{
    int result = -1;
    FILE *const fpFrom = fopen(from, "r");

    if (fpFrom != NULL)
    {
	FILE *const fpTo = fopen(to, "w");

	if (fpFrom != NULL)
	{
	    result = copyChars(fpFrom, fpTo, size);
	    if (result == 0)
		result = fclose(fpTo);
	}
	if (result == 0)
	    result = fclose(fpFrom);
    }
    return result;
}

/*  Replacement for missing library function.
 */
static int replacementTruncate( name, size )
    const char *const name;
    const off_t size;
{
    char tempName[L_tmpnam];
    int result = -1;

    if (tmpnam(tempName) != NULL)
    {
	result = copyFile(name, tempName, size);
	if (result == 0)
	    result = copyFile(tempName, name, size);
	if (result == 0)
	    result = remove(tempName);
    }
    return result;
}

#endif

static void closeTagFile( resize )
    const boolean resize;
{
    const long __unused__ size = ftell(TagFile.fp);

    fclose(TagFile.fp);
    if (resize)
    {
	int __unused__ result = 0;

#ifdef USE_REPLACEMENT_TRUNCATE
	result = replacementTruncate(TagFile.name, (off_t)size);
#else
# ifdef HAVE_TRUNCATE
	result = truncate(TagFile.name, (off_t)size);
# else
	const int fd = open(TagFile.name, O_RDWR);

	if (fd != -1)
	{
#  ifdef HAVE_FTRUNCATE
	    result = ftruncate(fd, (off_t)size);
#  else
#   ifdef HAVE_CHSIZE
	    result = chsize(fd, size);
#   endif
#  endif
	    close(fd);
	}
# endif
#endif
	if (result == -1)
	    fprintf(errout, "Cannot shorten tag file: errno = %d\n", errno);
    }
}

/*----------------------------------------------------------------------------
 *	Create tags
 *--------------------------------------------------------------------------*/

static void beginEtagsFile()
{
    tmpnam(TagFile.etags.name);
    TagFile.etags.fp = fopen(TagFile.etags.name, "w+b");
    if (TagFile.etags.fp == NULL)
	error(FATAL | PERROR, "cannot open \"%s\"", TagFile.etags.name);
    TagFile.etags.byteCount = 0;
}

static void endEtagsFile( name )
    const char *const name;
{
    const char *line;

    fprintf(TagFile.fp, "\f\n%s,%ld\n", name, (long)TagFile.etags.byteCount);
    if (TagFile.etags.fp != NULL)
    {
	rewind(TagFile.etags.fp);
	while ((line = readLine(&TagFile.line, TagFile.etags.fp)) != NULL)
	    fputs(line, TagFile.fp);
	fclose(TagFile.etags.fp);
	remove(TagFile.etags.name);
    }
    TagFile.etags.name[0] = '\0';
}

static boolean createTagsForFile( filePath, language )
    const char *const filePath;
    const langType language;
{
    boolean ok;

    if (filePath == NULL)
	ok = FALSE;
    else
    {
	const boolean isHeader = isFileHeader(filePath);

	ok = TRUE;
	if (Option.etags)
	    beginEtagsFile();
	if (cppOpen(filePath, language, isHeader))
	{
	    tagInfo tag;

	    DebugStatement( clearString(tag.name, MaxNameLength); )
	    strcpy(tag.name, baseFilename(filePath));
	    tag.location   = 0;
	    tag.lineNumber = 1;

	    makeTag(&tag, &NoClass, SCOPE_GLOBAL, TAG_SOURCE_FILE);
	    ok = createTags(0, NULL);
	    cppClose();
	}
	if (Option.etags)
	    endEtagsFile(filePath);
    }
    return ok;
}

static const char *getNextListFile( fp )
    FILE *const fp;
{
    static char fileName[PATH_MAX + 1];
    const char *const buf = fgets(fileName, PATH_MAX + 1, fp);

    if (buf != NULL)
    {
	char *const newline = strchr(fileName, '\n');

	if (newline == NULL)
	    fileName[PATH_MAX] = '\0';
	else
	    *newline = '\0';
    }
    return buf;
}

static const char *sourceFilePath( file )
    const char *const file;
{
    const char *result = NULL;

    if (Option.path == NULL  ||  isAbsolutePath(file))
	result = file;
    else if (strlen(Option.path) + strlen(file) < (size_t)PATH_MAX)
    {
	static char filePath[PATH_MAX + 1];

	combinePathAndFile(filePath, Option.path, file);
	result = filePath;
    }
    return result;
}

static boolean createTagsWithFallback( fileName, language )
    const char *const fileName;
    const langType language;
{
    const char *const filePath	= sourceFilePath(fileName);
    const unsigned long numTags	= TagFile.numTags.added;
    const long tagFilePosition	= ftell(TagFile.fp);
    boolean resize = FALSE;

    if (! createTagsForFile(filePath, language))
    {
	/*  Restore prior state of tag file.
	 */
	fseek(TagFile.fp, tagFilePosition, SEEK_SET);
	TagFile.numTags.added = numTags;

⌨️ 快捷键说明

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