📄 options.c
字号:
/** $Id: options.c,v 1.25 2004/02/28 15:19:45 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 */ }, 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: \"afmikKlnsSz\") [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," --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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -