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

📄 options.c

📁 Exuberant Ctags is a multilanguage reimplementation of the much-underused ctags(1) program and is i
💻 C
📖 第 1 页 / 共 3 页
字号:
/**   $Id: options.c,v 1.32 2006/05/30 04:37:12 darren Exp $**   Copyright (c) 1996-2003, Darren Hiebert**   This source code is released for free distribution under the terms of the*   GNU General Public License.**   This module contains functions to process command line options.*//**   INCLUDE FILES*/#include "general.h"  /* must always come first */#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>  /* to declare isspace () */#include "ctags.h"#include "debug.h"#include "main.h"#define OPTION_WRITE#include "options.h"#include "parse.h"#include "routines.h"/**   MACROS*/#define INVOCATION  "Usage: %s [options] [file(s)]\n"#define CTAGS_ENVIRONMENT  "CTAGS"#define ETAGS_ENVIRONMENT  "ETAGS"#define CTAGS_FILE  "tags"#define ETAGS_FILE  "TAGS"#ifndef ETAGS# define ETAGS	"etags"  /* name which causes default use of to -e */#endif/*  The following separators are permitted for list options. */#define EXTENSION_SEPARATOR '.'#define PATTERN_START '('#define PATTERN_STOP  ')'#define IGNORE_SEPARATORS   ", \t\n"#ifndef DEFAULT_FILE_FORMAT# define DEFAULT_FILE_FORMAT  2#endif#if defined (HAVE_OPENDIR) || defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST) || defined (AMIGA)# define RECURSE_SUPPORTED#endif#define isCompoundOption(c)  (boolean) (strchr ("fohiILpDb", (c)) != NULL)/**   Data declarations*/enum eOptionLimits {	MaxHeaderExtensions	= 100,  /* maximum number of extensions in -h option */	MaxSupportedTagFormat = 2};typedef struct sOptionDescription {	int usedByEtags;	const char *description;} optionDescription;typedef void (*parametricOptionHandler) (const char *const option, const char *const parameter);typedef const struct {	const char* name;   /* name of option as specified by user */	parametricOptionHandler handler;  /* routine to handle option */	boolean initOnly;   /* option must be specified before any files */} parametricOption;typedef const struct {	const char* name;   /* name of option as specified by user */	boolean* pValue;    /* pointer to option value */	boolean initOnly;   /* option must be specified before any files */} booleanOption;/**   DATA DEFINITIONS*/static boolean NonOptionEncountered;static stringList *OptionFiles;static stringList* Excluded;static boolean FilesRequired = TRUE;static boolean SkipConfiguration;static const char *const HeaderExtensions [] = {	"h", "H", "hh", "hpp", "hxx", "h++", "inc", "def", NULL};optionValues Option = {	{		FALSE,  /* --extra=f */		FALSE,  /* --extra=q */		TRUE,   /* --file-scope */	},	{		FALSE,  /* -fields=a */		TRUE,   /* -fields=f */		FALSE,  /* -fields=m */		FALSE,  /* -fields=i */		TRUE,   /* -fields=k */		FALSE,  /* -fields=z */		FALSE,  /* -fields=K */		FALSE,  /* -fields=l */		FALSE,  /* -fields=n */		TRUE,   /* -fields=s */		FALSE,  /* -fields=S */		TRUE    /* -fields=t */	},	NULL,       /* -I */	FALSE,      /* -a */	FALSE,      /* -B */	FALSE,      /* -e */#ifdef MACROS_USE_PATTERNS	EX_PATTERN, /* -n, --excmd */#else	EX_MIX,     /* -n, --excmd */#endif	FALSE,      /* -R */	SO_SORTED,  /* -u, --sort */	FALSE,      /* -V */	FALSE,      /* -x */	NULL,       /* -L */	NULL,       /* -o */	NULL,       /* -h */	NULL,       /* --etags-include */	DEFAULT_FILE_FORMAT,/* --format */	FALSE,      /* --if0 */	FALSE,      /* --kind-long */	LANG_AUTO,  /* --lang */	TRUE,       /* --links */	FALSE,      /* --filter */	NULL,       /* --filter-terminator */	FALSE,      /* --tag-relative */	FALSE,      /* --totals */	FALSE,      /* --line-directives */#ifdef DEBUG	0, 0        /* -D, -b */#endif};/*-   Locally used only*/static optionDescription LongOptionDescription [] = { {1,"  -a   Append the tags to an existing tag file."},#ifdef DEBUG {1,"  -b <line>"}, {1,"       Set break line."},#endif {0,"  -B   Use backward searching patterns (?...?)."},#ifdef DEBUG {1,"  -D <level>"}, {1,"       Set debug level."},#endif {0,"  -e   Output tag file for use with Emacs."}, {1,"  -f <name>"}, {1,"       Write tags to specified file. Value of \"-\" writes tags to stdout"}, {1,"       [\"tags\"; or \"TAGS\" when -e supplied]."}, {0,"  -F   Use forward searching patterns (/.../) (default)."}, {1,"  -h <list>"}, {1,"       Specify list of file extensions to be treated as include files."}, {1,"       [\".h.H.hh.hpp.hxx.h++\"]."}, {1,"  -I <list|@file>"}, {1,"       A list of tokens to be specially handled is read from either the"}, {1,"       command line or the specified file."}, {1,"  -L <file>"}, {1,"       A list of source file names are read from the specified file."}, {1,"       If specified as \"-\", then standard input is read."}, {0,"  -n   Equivalent to --excmd=number."}, {0,"  -N   Equivalent to --excmd=pattern."}, {1,"  -o   Alternative for -f."},#ifdef RECURSE_SUPPORTED {1,"  -R   Equivalent to --recurse."},#else {1,"  -R   Not supported on this platform."},#endif {0,"  -u   Equivalent to --sort=no."}, {1,"  -V   Equivalent to --verbose."}, {1,"  -x   Print a tabular cross reference file to standard output."}, {1,"  --append=[yes|no]"}, {1,"       Should tags should be appended to existing tag file [no]?"}, {1,"  --etags-include=file"}, {1,"      Include reference to 'file' in Emacs-style tag file (requires -e)."}, {1,"  --exclude=pattern"}, {1,"      Exclude files and directories matching 'pattern'."}, {0,"  --excmd=number|pattern|mix"},#ifdef MACROS_USE_PATTERNS {0,"       Uses the specified type of EX command to locate tags [pattern]."},#else {0,"       Uses the specified type of EX command to locate tags [mix]."},#endif {1,"  --extra=[+|-]flags"}, {1,"      Include extra tag entries for selected information (flags: \"fq\")."}, {1,"  --fields=[+|-]flags"}, {1,"      Include selected extension fields (flags: \"afmikKlnsStz\") [fks]."}, {1,"  --file-scope=[yes|no]"}, {1,"       Should tags scoped only for a single file (e.g. \"static\" tags"}, {1,"       be included in the output [yes]?"}, {1,"  --filter=[yes|no]"}, {1,"       Behave as a filter, reading file names from standard input and"}, {1,"       writing tags to standard output [no]."}, {1,"  --filter-terminator=string"}, {1,"       Specify string to print to stdout following the tags for each file"}, {1,"       parsed when --filter is enabled."}, {0,"  --format=level"},#if DEFAULT_FILE_FORMAT == 1 {0,"       Force output of specified tag file format [1]."},#else {0,"       Force output of specified tag file format [2]."},#endif {1,"  --help"}, {1,"       Print this option summary."}, {1,"  --if0=[yes|no]"}, {1,"       Should C code within #if 0 conditional branches be parsed [no]?"}, {1,"  --<LANG>-kinds=[+|-]kinds"}, {1,"       Enable/disable tag kinds for language <LANG>."}, {1,"  --langdef=name"}, {1,"       Define a new language to be parsed with regular expressions."}, {1,"  --langmap=map(s)"}, {1,"       Override default mapping of language to source file extension."}, {1,"  --language-force=language"}, {1,"       Force all files to be interpreted using specified language."}, {1,"  --languages=[+|-]list"}, {1,"       Restrict files scanned for tags to those mapped to langauges"}, {1,"       specified in the comma-separated 'list'. The list can contain any"}, {1,"       built-in or user-defined language [all]."}, {1,"  --license"}, {1,"       Print details of software license."}, {0,"  --line-directives=[yes|no]"}, {0,"       Should #line directives be processed [no]?"}, {1,"  --links=[yes|no]"}, {1,"       Indicate whether symbolic links should be followed [yes]."}, {1,"  --list-kinds=[language|all]"}, {1,"       Output a list of all tag kinds for specified language or all."}, {1,"  --list-languages"}, {1,"       Output list of supported languages."}, {1,"  --list-maps=[language|all]"}, {1,"       Output list of language mappings."}, {1,"  --options=file"}, {1,"       Specify file from which command line options should be read."}, {1,"  --recurse=[yes|no]"},#ifdef RECURSE_SUPPORTED {1,"       Recurse into directories supplied on command line [no]."},#else {1,"       Not supported on this platform."},#endif#ifdef HAVE_REGEX {1,"  --regex-<LANG>=/line_pattern/name_pattern/[flags]"}, {1,"       Define regular expression for locating tags in specific language."},#endif {0,"  --sort=[yes|no|foldcase]"}, {0,"       Should tags be sorted (optionally ignoring case) [yes]?."}, {0,"  --tag-relative=[yes|no]"}, {0,"       Should paths be relative to location of tag file [no; yes when -e]?"}, {1,"  --totals=[yes|no]"}, {1,"       Print statistics about source and tag files [no]."}, {1,"  --verbose=[yes|no]"}, {1,"       Enable verbose messages describing actions on each source file."}, {1,"  --version"}, {1,"       Print version identifier to standard output."}, {1, NULL}};static const char* const License1 ="This program is free software; you can redistribute it and/or\n""modify it under the terms of the GNU General Public License\n""as published by the Free Software Foundation; either version 2\n""of the License, or (at your option) any later version.\n""\n";static const char* const License2 ="This program is distributed in the hope that it will be useful,\n""but WITHOUT ANY WARRANTY; without even the implied warranty of\n""MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n""GNU General Public License for more details.\n""\n""You should have received a copy of the GNU General Public License\n""along with this program; if not, write to the Free Software\n""Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n";/*  Contains a set of strings describing the set of "features" compiled into *  the code. */static const char *const Features [] = {#ifdef WIN32	"win32",#endif#ifdef DJGPP	"msdos_32",#else# ifdef MSDOS	"msdos_16",# endif#endif#ifdef OS2	"os2",#endif#ifdef AMIGA	"amiga",#endif#ifdef VMS	"vms",#endif#ifdef HAVE_FNMATCH	"wildcards",#endif#ifdef HAVE_REGEX	"regex",#endif#ifndef EXTERNAL_SORT	"internal-sort",#endif#ifdef CUSTOM_CONFIGURATION_FILE	"custom-conf",#endif#if (defined (MSDOS) || defined (WIN32) || defined (OS2)) && defined (UNIX_PATH_SEPARATOR)	"unix-path-separator",#endif#ifdef DEBUG	"debug",#endif	NULL};/**   FUNCTION PROTOTYPES*/static boolean parseFileOptions (const char *const fileName);/**   FUNCTION DEFINITIONS*/extern void verbose (const char *const format, ...){	if (Option.verbose)	{		va_list ap;		va_start (ap, format);		vprintf (format, ap);		va_end (ap);	}}static char *stringCopy (const char *const string){	char* result = NULL;	if (string != NULL)		result = eStrdup (string);	return result;}static void freeString (char **const pString){	if (*pString != NULL)	{		eFree (*pString);		*pString = NULL;	}}extern void freeList (stringList** const pList){	if (*pList != NULL)	{		stringListDelete (*pList);		*pList = NULL;	}}extern void setDefaultTagFileName (void){	if (Option.tagFileName != NULL)		;  /* accept given name */	else if (Option.etags)		Option.tagFileName = stringCopy (ETAGS_FILE);	else		Option.tagFileName = stringCopy (CTAGS_FILE);}extern boolean filesRequired (void){	boolean result = FilesRequired;	if (Option.recurse)		result = FALSE;	return result;}extern void checkOptions (void){	const char* notice;	if (Option.xref)	{		notice = "xref output";		if (Option.include.fileNames)		{			error (WARNING, "%s disables file name tags", notice);			Option.include.fileNames = FALSE;		}	}	if (Option.append)	{		notice = "append mode is not compatible with";		if (isDestinationStdout ())			error (FATAL, "%s tags to stdout", notice);	}	if (Option.filter)	{		notice = "filter mode";		if (Option.printTotals)		{			error (WARNING, "%s disables totals", notice);			Option.printTotals = FALSE;		}		if (Option.tagFileName != NULL)			error (WARNING, "%s ignores output tag file name", notice);	}}static void setEtagsMode (void){	Option.etags = TRUE;	Option.sorted = SO_UNSORTED;	Option.lineDirectives = FALSE;	Option.tagRelative = TRUE;}extern void testEtagsInvocation (void){	char* const execName = eStrdup (getExecutableName ());	char* const etags = eStrdup (ETAGS);#ifdef CASE_INSENSITIVE_FILENAMES	toLowerString (execName);	toLowerString (etags);#endif	if (strstr (execName, etags) != NULL)	{		verbose ("Running in etags mode\n");		setEtagsMode ();	}}/* *  Cooked argument parsing */static void parseShortOption (cookedArgs *const args){	args->simple [0] = *args->shortOptions++;	args->simple [1] = '\0';	args->item = args->simple;	if (! isCompoundOption (*args->simple))		args->parameter = "";	else if (*args->shortOptions == '\0')	{		argForth (args->args);		if (argOff (args->args))			args->parameter = NULL;		else			args->parameter = argItem (args->args);		args->shortOptions = NULL;	}	else	{		args->parameter = args->shortOptions;		args->shortOptions = NULL;	}}static void parseLongOption (cookedArgs *const args, const char *item){	const char* const equal = strchr (item, '=');	if (equal == NULL)	{		args->item = eStrdup (item);		args->parameter = "";	}	else	{		const size_t length = equal - item;		args->item = xMalloc (length + 1, char);		strncpy (args->item, item, length);		args->item [length] = '\0';		args->parameter = equal + 1;	}	Assert (args->item != NULL);	Assert (args->parameter != NULL);}static void cArgRead (cookedArgs *const current){	char* item;	Assert (current != NULL);	if (! argOff (current->args))	{		item = argItem (current->args);		current->shortOptions = NULL;		Assert (item != NULL);		if (strncmp (item, "--", (size_t) 2) == 0)		{			current->isOption = TRUE;			current->longOption = TRUE;			parseLongOption (current, item + 2);			Assert (current->item != NULL);			Assert (current->parameter != NULL);		}		else if (*item == '-')		{			current->isOption = TRUE;			current->longOption = FALSE;			current->shortOptions = item + 1;			parseShortOption (current);		}		else		{			current->isOption = FALSE;			current->longOption = FALSE;			current->item = item;			current->parameter = NULL;		}	}}extern cookedArgs* cArgNewFromString (const char* string){	cookedArgs* const result = xMalloc (1, cookedArgs);	memset (result, 0, sizeof (cookedArgs));	result->args = argNewFromString (string);	cArgRead (result);	return result;}extern cookedArgs* cArgNewFromArgv (char* const* const argv){	cookedArgs* const result = xMalloc (1, cookedArgs);	memset (result, 0, sizeof (cookedArgs));	result->args = argNewFromArgv (argv);	cArgRead (result);	return result;}extern cookedArgs* cArgNewFromFile (FILE* const fp){	cookedArgs* const result = xMalloc (1, cookedArgs);	memset (result, 0, sizeof (cookedArgs));	result->args = argNewFromFile (fp);	cArgRead (result);	return result;}extern cookedArgs* cArgNewFromLineFile (FILE* const fp){	cookedArgs* const result = xMalloc (1, cookedArgs);	memset (result, 0, sizeof (cookedArgs));	result->args = argNewFromLineFile (fp);	cArgRead (result);	return result;}extern void cArgDelete (cookedArgs* const current){	Assert (current != NULL);	argDelete (current->args);	memset (current, 0, sizeof (cookedArgs));	eFree (current);}static boolean cArgOptionPending (cookedArgs* const current){	boolean result = FALSE;	if (current->shortOptions != NULL)		if (*current->shortOptions != '\0')			result = TRUE;	return result;}extern boolean cArgOff (cookedArgs* const current){	Assert (current != NULL);

⌨️ 快捷键说明

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