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

📄 main.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
*   $Id: main.c,v 6.23 1998/08/18 04:26:50 darren Exp $
*
*   Copyright (c) 1996-1998, Darren Hiebert
*
*   Author: Darren Hiebert <darren@hiebert.com>, <darren@hiwaay.net>
*           http://darren.hiebert.com
*
*   This source code is released for free distribution under the terms of the
*   GNU General Public License. It is provided on an as-is basis and no
*   responsibility is accepted for its failure to perform as expected.
*
*   This is a reimplementation of the ctags(1) program. It is an attempt to
*   provide a fully featured ctags program which is free of the limitations
*   which most (all?) others are subject to.
*
*   It is derived from and inspired by the ctags program by Steve Kirkendall
*   (kirkenda@cs.pdx.edu) that comes with the Elvis vi clone (though almost
*   none of the original code remains). This, too, was freely available.
*
*   This program provides the following features:
*
*   Support for both K&R style and new ANSI style function definitions.
*
*   Generates tags for the following objects:
*	- macro definitions
*	- enumeration values
*	- function definitions (and C++ methods)
*	- function declarations (optional)
*	- enum, struct and union tags and C++ class names
*	- typedefs
*	- variables
*
*   This module contains top level start-up and portability functions.
*****************************************************************************/

/*============================================================================
=   Include files
============================================================================*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2)
# define ENABLE_STDARG
#endif

#if defined(MSDOS) || defined(WIN32)
# define HAVE_DOS_H
# define HAVE_IO_H
# define HAVE_TIME_H
# define HAVE_CLOCK
# define HAVE_CHSIZE
# define HAVE_STRERROR
# define HAVE_FINDNEXT
# ifdef __BORLANDC__
#  define HAVE_DIR_H
#  define HAVE_DIRENT_H
#  define HAVE_FINDFIRST
# else
#  ifdef _MSC_VER
#   define HAVE__FINDFIRST
#  endif
# endif
#endif

#ifdef DJGPP
# define HAVE_DIR_H
# define HAVE_UNISTD_H
# define HAVE_FINDFIRST
# define HAVE_TRUNCATE
#endif

#if defined(OS2)
# define HAVE_DIRENT_H
# define HAVE_TIME_H
# define HAVE_IO_H
# define HAVE_CLOCK
# define HAVE_CHSIZE
# define HAVE_OPENDIR
# define HAVE_STRERROR
#endif

#ifdef AMIGA
# define HAVE_TIME_H
# define HAVE_SYS_STAT_H
# define HAVE_CLOCK
# define HAVE_STRERROR
# define PATH_MAX 255
# include <dos/dosasl.h>	/* for struct AnchorPath */
# include <clib/dos_protos.h>	/* function prototypes */
# define ANCHOR_BUF_SIZE (512)
# define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
#endif

#if defined(HAVE_UNISTD_H)
# include <unistd.h>	/* to declare close(), ftruncate(), truncate() */
#endif

#include <errno.h>

#ifdef ENABLE_STDARG
# include <stdarg.h>
#else
# include <varargs.h>
#endif

/*  To declare "struct stat" and stat().
 */
#if defined(__MWERKS__) && defined(__MACINTOSH__)
# include <stat.h>		/* there is no sys directory on the Mac */
#else
# include <sys/types.h>
# include <sys/stat.h>
#endif

#ifdef HAVE_DIRENT_H
# ifdef __BORLANDC__
#  define boolean BORLAND_boolean
# endif
# include <dirent.h>
# undef boolean
#endif

/*  These header files provide for the functions necessary to do file
 *  truncation.
 */
#include <fcntl.h>
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_DOS_H
# include <dos.h>
#endif
#ifdef HAVE_DIR_H
# include <dir.h>
#endif

/*  To define the maximum path length
 */
#include <limits.h>			/* to define PATH_MAX (hopefully) */
#ifndef PATH_MAX
# ifdef MAXNAMLEN
#  define PATH_MAX MAXNAMLEN
# endif
#endif
#if !defined(PATH_MAX) && defined(MAXPATH)	/* found in Borland C <dir.h> */
# define PATH_MAX MAXPATH
#endif
#ifndef PATH_MAX
# define PATH_MAX 127			/* ultimate fall-back */
#endif

/*  To provide timings features if available.
 */
#ifdef HAVE_CLOCK
# ifdef HAVE_TIME_H
#  include <time.h>
# endif
#else
# ifdef HAVE_TIMES
#  ifdef HAVE_SYS_TIMES_H
#   include <sys/times.h>
#  endif
# endif
#endif

#ifdef DEBUG
# include <assert.h>
#endif

#include "ctags.h"

/*============================================================================
=   Defines
============================================================================*/

/*----------------------------------------------------------------------------
 *  Portability defines
 *--------------------------------------------------------------------------*/
#if !defined(HAVE_TRUNCATE) && !defined(HAVE_FTRUNCATE) && !defined(HAVE_CHSIZE)
# define USE_REPLACEMENT_TRUNCATE
#endif

#if defined(MSDOS) || defined(WIN32) || defined(OS2)
# define PATH_SEPARATOR	'\\'
#else
# define PATH_SEPARATOR	'/'
#endif

/*  File type tests.
 */
#ifndef S_ISREG
# if defined(S_IFREG) && !defined(AMIGA)
#  define S_ISREG(mode)	    ((mode) & S_IFREG)
# else
#  define S_ISREG(mode)	    TRUE	/* assume regular file */
# endif
#endif

#ifndef S_ISLNK
# ifdef S_IFLNK
#  define S_ISLNK(mode)	    (((mode) & S_IFMT) == S_IFLNK)
# else
#  define S_ISLNK(mode)	    FALSE	/* assume no soft links */
# endif
#endif

#ifndef S_ISDIR
# ifdef S_IFDIR
#  define S_ISDIR(mode)	    (((mode) & S_IFMT) == S_IFDIR)
# else
#  define S_ISDIR(mode)	    FALSE	/* assume no soft links */
# endif
#endif

/*  Hack for rediculous practice of Microsoft Visual C++.
 */
#if defined(WIN32) && defined(_MSC_VER)
# define chsize		_chsize
# define open		_open
# define close		_close
# define stat		_stat
# define O_RDWR 	_O_RDWR
#endif

/*----------------------------------------------------------------------------
 *  Miscellaneous defines
 *--------------------------------------------------------------------------*/
#ifndef ETAGS
# define ETAGS	"etags"		/* name which causes default use of to -e */
#endif

#define selected(var,feature)	(((int)(var) & (int)(feature)) == (int)feature)

#define plural(value)		(((unsigned long)(value) == 1L) ? "" : "s")

/*============================================================================
=   Data definitions
============================================================================*/
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
static const char DosPathDelimiters[] = ":/\\";
#endif

static const char *ExecutableName = NULL;

static struct { long files, lines, bytes; } Totals = { 0, 0, 0 };

tagFile TagFile = {
    NULL,		/* file name */
    NULL,		/* file pointer */
    { 0, 0 },		/* numTags */
    { 0, 0, 0 },	/* max */
    { "", NULL },	/* etags */
    { 0, NULL }		/* line */
};

memberInfo NoClass = { MEMBER_NONE, VIS_UNDEFINED, FALSE, "" };

/*============================================================================
=   Function prototypes
============================================================================*/
#ifdef NEED_PROTO_STAT
extern int stat __ARGS((const char *, struct stat *));
#endif

#ifdef NEED_PROTO_TRUNCATE
extern int truncate __ARGS((const char *path, off_t length));
#endif

#ifdef NEED_PROTO_FTRUNCATE
extern int ftruncate __ARGS((int fd, off_t length));
#endif

static const char *baseFilename __ARGS((const char *const path));
static boolean isAbsolutePath __ARGS((const char *const path));
static void combinePathAndFile __ARGS((char *const filePath, const char *const path, const char *const file));

static const char *findExtension __ARGS((const char *const fileName));
static boolean isFileHeader __ARGS((const char *const FileName));
static boolean isExtensionInList __ARGS((const char *const extension, const char *const *const list));
static langType getExtensionLanguage __ARGS((const char *const extension));
static langType getFileLanguage __ARGS((const char *const FileName));

static boolean isValidTagAddress __ARGS((const char *const tag));
static boolean isCtagsLine __ARGS((const char *const tag));
static boolean isEtagsLine __ARGS((const char *const tag));
static boolean isTagFile __ARGS((const char *const filename));
static void openTagFile __ARGS((const boolean toStdout));
static void closeTagFile __ARGS((const boolean resize));

static void beginEtagsFile __ARGS((void));
static void endEtagsFile __ARGS((const char *const name));
static boolean createTagsForFile __ARGS((const char *const filePath, const langType language));
static const char *getNextListFile __ARGS((FILE *const fp));
static const char *sourceFilePath __ARGS((const char *const file));
static boolean createTagsWithFallback __ARGS((const char *const fileName, const langType language));
static boolean createTagsForDirectory __ARGS((const char *const dirName));
static boolean createTagsForEntry __ARGS((const char *const entryName));
static boolean createTagsForList __ARGS((const char *const listFile));
static boolean createTagsForArgs __ARGS((const char *const *const argList));
static void printTotals __ARGS((const clock_t *const timeStamps));
static void makeTags __ARGS((const char *const *const argList));

static void setExecutableName __ARGS((const char *const path));
static void setDefaultTagFileName __ARGS((void));
static void setOptionDefaults __ARGS((void));
static void testEtagsInvocation __ARGS((void));

extern int main __ARGS((int argc, char **argv));

/*============================================================================
=   Function definitions
============================================================================*/

#ifdef ENABLE_STDARG
extern void error( const errorSelection selection,
		   const char *const format, ... )
#else
extern void error( va_alist )
    va_dcl
#endif
{
    va_list ap;

#ifdef ENABLE_STDARG
    va_start(ap, format);
#else
    const char *format;
    errorSelection selection;

    va_start(ap);
    selection = va_arg(ap, errorSelection);
    format = va_arg(ap, char *);
#endif
    fprintf(errout, "%s: %s", getExecutableName(),
	    selected(selection, WARNING) ? "warning: " : "");
    vfprintf(errout, format, ap);
    if (selected(selection, PERROR))
#ifdef HAVE_STRERROR
	fprintf(errout, " : %s", strerror(errno));
#else
	perror(" ");
#endif
    fputs("\n", errout);
    va_end(ap);
    if (selected(selection, FATAL))
	exit(1);
}

extern unsigned long getFileSize( name )
    const char *const __unused__ name;
{
    struct stat fileStatus;
    unsigned long size = 0;

    if (stat(name, &fileStatus) == 0)
	size = fileStatus.st_size;

    return size;
}

extern boolean isNormalFile( name )
    const char *const name;
{
    struct stat fileStatus;
    boolean isNormal = FALSE;

    if (stat(name, &fileStatus) == 0)
	isNormal = (boolean)(S_ISLNK(fileStatus.st_mode) ||
			     S_ISREG(fileStatus.st_mode)  );

    return isNormal;
}

extern boolean isDirectory( name )
    const char *const name;
{
    boolean isDir = FALSE;
#ifdef AMIGA
    struct FileInfoBlock *const fib = (struct FileInfoBlock *)
					malloc(sizeof(struct FileInfoBlock));

    if (fib != NULL)
    {
	const BPTR flock = Lock((UBYTE *)name, (long)ACCESS_READ);

	if (flock != (BPTR)NULL)
	{
	    if (Examine(flock, fib))
		isDir = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
	    UnLock(flock);
	}
	free(fib);
    }
#else
    struct stat fileStatus;

    if (stat(name, &fileStatus) == 0)
	isDir = (boolean)S_ISDIR(fileStatus.st_mode);
#endif
    return isDir;
}

extern boolean doesFileExist( fileName )
    const char *const fileName;
{
    struct stat fileStatus;

    return (boolean)(stat(fileName, &fileStatus) == 0);
}

extern void addTotals( files, lines, bytes )
    const unsigned int files;
    const unsigned long lines;
    const unsigned long bytes;
{
    Totals.files += files;
    Totals.lines += lines;
    Totals.bytes += bytes;
}

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

static const char *baseFilename( filePath )
    const char *const filePath;
{
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
    const char *tail = NULL;
    unsigned int i;

    /*  Find whichever of the path delimiters is last.
     */
    for (i = 0  ;  i < strlen(DosPathDelimiters)  ;  ++i)
    {
	const char *sep = strrchr(filePath, DosPathDelimiters[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 */

    return tail;
}

static boolean isAbsolutePath( path )
    const char *const path;
{
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
    return (strchr(DosPathDelimiters, path[0]) != NULL);
#else
    return (boolean)(path[0] == PATH_SEPARATOR);
#endif
}

static void combinePathAndFile( filePath, path, file )
    char *const filePath;
    const char *const path;
    const char *const file;
{
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
    if (strchr(DosPathDelimiters, path[strlen(path)-1]) != NULL)
	sprintf(filePath, "%s%s", path, file);
    else

⌨️ 快捷键说明

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