ctags.rb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Rakefile +23 -0
- data/ctags.rb.gemspec +23 -0
- data/ext/.gitignore +3 -0
- data/ext/extconf.rb +15 -0
- data/ext/vendor/exuberant-ctags/.gitignore +6 -0
- data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
- data/ext/vendor/exuberant-ctags/COPYING +340 -0
- data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
- data/ext/vendor/exuberant-ctags/FAQ +371 -0
- data/ext/vendor/exuberant-ctags/INSTALL +215 -0
- data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
- data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
- data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
- data/ext/vendor/exuberant-ctags/NEWS +871 -0
- data/ext/vendor/exuberant-ctags/README +73 -0
- data/ext/vendor/exuberant-ctags/ant.c +42 -0
- data/ext/vendor/exuberant-ctags/argproc.c +505 -0
- data/ext/vendor/exuberant-ctags/args.c +274 -0
- data/ext/vendor/exuberant-ctags/args.h +63 -0
- data/ext/vendor/exuberant-ctags/asm.c +387 -0
- data/ext/vendor/exuberant-ctags/asp.c +328 -0
- data/ext/vendor/exuberant-ctags/awk.c +81 -0
- data/ext/vendor/exuberant-ctags/basic.c +203 -0
- data/ext/vendor/exuberant-ctags/beta.c +321 -0
- data/ext/vendor/exuberant-ctags/c.c +2932 -0
- data/ext/vendor/exuberant-ctags/cobol.c +50 -0
- data/ext/vendor/exuberant-ctags/config.h.in +277 -0
- data/ext/vendor/exuberant-ctags/configure +7704 -0
- data/ext/vendor/exuberant-ctags/configure.ac +532 -0
- data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
- data/ext/vendor/exuberant-ctags/ctags.h +28 -0
- data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
- data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
- data/ext/vendor/exuberant-ctags/debug.c +113 -0
- data/ext/vendor/exuberant-ctags/debug.h +70 -0
- data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
- data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
- data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
- data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
- data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
- data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
- data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
- data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
- data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
- data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
- data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
- data/ext/vendor/exuberant-ctags/entry.c +847 -0
- data/ext/vendor/exuberant-ctags/entry.h +103 -0
- data/ext/vendor/exuberant-ctags/erlang.c +189 -0
- data/ext/vendor/exuberant-ctags/flex.c +2243 -0
- data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
- data/ext/vendor/exuberant-ctags/general.h +127 -0
- data/ext/vendor/exuberant-ctags/get.c +669 -0
- data/ext/vendor/exuberant-ctags/get.h +50 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
- data/ext/vendor/exuberant-ctags/html.c +49 -0
- data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
- data/ext/vendor/exuberant-ctags/keyword.c +258 -0
- data/ext/vendor/exuberant-ctags/keyword.h +34 -0
- data/ext/vendor/exuberant-ctags/lisp.c +139 -0
- data/ext/vendor/exuberant-ctags/lregex.c +704 -0
- data/ext/vendor/exuberant-ctags/lua.c +133 -0
- data/ext/vendor/exuberant-ctags/mac.c +273 -0
- data/ext/vendor/exuberant-ctags/magic.diff +21 -0
- data/ext/vendor/exuberant-ctags/main.c +584 -0
- data/ext/vendor/exuberant-ctags/main.h +32 -0
- data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
- data/ext/vendor/exuberant-ctags/make.c +217 -0
- data/ext/vendor/exuberant-ctags/matlab.c +44 -0
- data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
- data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
- data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
- data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
- data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
- data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
- data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
- data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
- data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
- data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
- data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
- data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.h +155 -0
- data/ext/vendor/exuberant-ctags/parse.c +677 -0
- data/ext/vendor/exuberant-ctags/parse.h +129 -0
- data/ext/vendor/exuberant-ctags/parsers.h +63 -0
- data/ext/vendor/exuberant-ctags/pascal.c +267 -0
- data/ext/vendor/exuberant-ctags/perl.c +382 -0
- data/ext/vendor/exuberant-ctags/php.c +237 -0
- data/ext/vendor/exuberant-ctags/python.c +771 -0
- data/ext/vendor/exuberant-ctags/qdos.c +106 -0
- data/ext/vendor/exuberant-ctags/read.c +569 -0
- data/ext/vendor/exuberant-ctags/read.h +116 -0
- data/ext/vendor/exuberant-ctags/readtags.c +959 -0
- data/ext/vendor/exuberant-ctags/readtags.h +252 -0
- data/ext/vendor/exuberant-ctags/rexx.c +39 -0
- data/ext/vendor/exuberant-ctags/routines.c +891 -0
- data/ext/vendor/exuberant-ctags/routines.h +134 -0
- data/ext/vendor/exuberant-ctags/ruby.c +408 -0
- data/ext/vendor/exuberant-ctags/scheme.c +111 -0
- data/ext/vendor/exuberant-ctags/sh.c +115 -0
- data/ext/vendor/exuberant-ctags/slang.c +41 -0
- data/ext/vendor/exuberant-ctags/sml.c +212 -0
- data/ext/vendor/exuberant-ctags/sort.c +230 -0
- data/ext/vendor/exuberant-ctags/sort.h +32 -0
- data/ext/vendor/exuberant-ctags/source.mak +122 -0
- data/ext/vendor/exuberant-ctags/sql.c +2112 -0
- data/ext/vendor/exuberant-ctags/strlist.c +281 -0
- data/ext/vendor/exuberant-ctags/strlist.h +54 -0
- data/ext/vendor/exuberant-ctags/tcl.c +116 -0
- data/ext/vendor/exuberant-ctags/tex.c +524 -0
- data/ext/vendor/exuberant-ctags/verilog.c +340 -0
- data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
- data/ext/vendor/exuberant-ctags/vim.c +636 -0
- data/ext/vendor/exuberant-ctags/vstring.c +232 -0
- data/ext/vendor/exuberant-ctags/vstring.h +85 -0
- data/ext/vendor/exuberant-ctags/yacc.c +40 -0
- data/lib/ctags/exuberant.rb +45 -0
- data/lib/ctags/version.rb +3 -0
- data/lib/ctags.rb +6 -0
- data/test/test_ctags.rb +24 -0
- metadata +233 -0
|
@@ -0,0 +1,1842 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* $Id: options.c 576 2007-06-30 04:16:23Z elliotth $
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 1996-2003, Darren Hiebert
|
|
5
|
+
*
|
|
6
|
+
* This source code is released for free distribution under the terms of the
|
|
7
|
+
* GNU General Public License.
|
|
8
|
+
*
|
|
9
|
+
* This module contains functions to process command line options.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* INCLUDE FILES
|
|
14
|
+
*/
|
|
15
|
+
#include "general.h" /* must always come first */
|
|
16
|
+
|
|
17
|
+
#include <stdlib.h>
|
|
18
|
+
#include <string.h>
|
|
19
|
+
#include <stdio.h>
|
|
20
|
+
#include <ctype.h> /* to declare isspace () */
|
|
21
|
+
|
|
22
|
+
#include "ctags.h"
|
|
23
|
+
#include "debug.h"
|
|
24
|
+
#include "main.h"
|
|
25
|
+
#define OPTION_WRITE
|
|
26
|
+
#include "options.h"
|
|
27
|
+
#include "parse.h"
|
|
28
|
+
#include "routines.h"
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* MACROS
|
|
32
|
+
*/
|
|
33
|
+
#define INVOCATION "Usage: %s [options] [file(s)]\n"
|
|
34
|
+
|
|
35
|
+
#define CTAGS_ENVIRONMENT "CTAGS"
|
|
36
|
+
#define ETAGS_ENVIRONMENT "ETAGS"
|
|
37
|
+
|
|
38
|
+
#define CTAGS_FILE "tags"
|
|
39
|
+
#define ETAGS_FILE "TAGS"
|
|
40
|
+
|
|
41
|
+
#ifndef ETAGS
|
|
42
|
+
# define ETAGS "etags" /* name which causes default use of to -e */
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
/* The following separators are permitted for list options.
|
|
46
|
+
*/
|
|
47
|
+
#define EXTENSION_SEPARATOR '.'
|
|
48
|
+
#define PATTERN_START '('
|
|
49
|
+
#define PATTERN_STOP ')'
|
|
50
|
+
#define IGNORE_SEPARATORS ", \t\n"
|
|
51
|
+
|
|
52
|
+
#ifndef DEFAULT_FILE_FORMAT
|
|
53
|
+
# define DEFAULT_FILE_FORMAT 2
|
|
54
|
+
#endif
|
|
55
|
+
|
|
56
|
+
#if defined (HAVE_OPENDIR) || defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST) || defined (AMIGA)
|
|
57
|
+
# define RECURSE_SUPPORTED
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
#define isCompoundOption(c) (boolean) (strchr ("fohiILpDb", (c)) != NULL)
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* Data declarations
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
enum eOptionLimits {
|
|
67
|
+
MaxHeaderExtensions = 100, /* maximum number of extensions in -h option */
|
|
68
|
+
MaxSupportedTagFormat = 2
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
typedef struct sOptionDescription {
|
|
72
|
+
int usedByEtags;
|
|
73
|
+
const char *description;
|
|
74
|
+
} optionDescription;
|
|
75
|
+
|
|
76
|
+
typedef void (*parametricOptionHandler) (const char *const option, const char *const parameter);
|
|
77
|
+
|
|
78
|
+
typedef const struct {
|
|
79
|
+
const char* name; /* name of option as specified by user */
|
|
80
|
+
parametricOptionHandler handler; /* routine to handle option */
|
|
81
|
+
boolean initOnly; /* option must be specified before any files */
|
|
82
|
+
} parametricOption;
|
|
83
|
+
|
|
84
|
+
typedef const struct {
|
|
85
|
+
const char* name; /* name of option as specified by user */
|
|
86
|
+
boolean* pValue; /* pointer to option value */
|
|
87
|
+
boolean initOnly; /* option must be specified before any files */
|
|
88
|
+
} booleanOption;
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* DATA DEFINITIONS
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
static boolean NonOptionEncountered;
|
|
95
|
+
static stringList *OptionFiles;
|
|
96
|
+
static stringList* Excluded;
|
|
97
|
+
static boolean FilesRequired = TRUE;
|
|
98
|
+
static boolean SkipConfiguration;
|
|
99
|
+
|
|
100
|
+
static const char *const HeaderExtensions [] = {
|
|
101
|
+
"h", "H", "hh", "hpp", "hxx", "h++", "inc", "def", NULL
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
optionValues Option = {
|
|
105
|
+
{
|
|
106
|
+
FALSE, /* --extra=f */
|
|
107
|
+
FALSE, /* --extra=q */
|
|
108
|
+
TRUE, /* --file-scope */
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
FALSE, /* -fields=a */
|
|
112
|
+
TRUE, /* -fields=f */
|
|
113
|
+
FALSE, /* -fields=m */
|
|
114
|
+
FALSE, /* -fields=i */
|
|
115
|
+
TRUE, /* -fields=k */
|
|
116
|
+
FALSE, /* -fields=z */
|
|
117
|
+
FALSE, /* -fields=K */
|
|
118
|
+
FALSE, /* -fields=l */
|
|
119
|
+
FALSE, /* -fields=n */
|
|
120
|
+
TRUE, /* -fields=s */
|
|
121
|
+
FALSE, /* -fields=S */
|
|
122
|
+
TRUE /* -fields=t */
|
|
123
|
+
},
|
|
124
|
+
NULL, /* -I */
|
|
125
|
+
FALSE, /* -a */
|
|
126
|
+
FALSE, /* -B */
|
|
127
|
+
FALSE, /* -e */
|
|
128
|
+
#ifdef MACROS_USE_PATTERNS
|
|
129
|
+
EX_PATTERN, /* -n, --excmd */
|
|
130
|
+
#else
|
|
131
|
+
EX_MIX, /* -n, --excmd */
|
|
132
|
+
#endif
|
|
133
|
+
FALSE, /* -R */
|
|
134
|
+
SO_SORTED, /* -u, --sort */
|
|
135
|
+
FALSE, /* -V */
|
|
136
|
+
FALSE, /* -x */
|
|
137
|
+
NULL, /* -L */
|
|
138
|
+
NULL, /* -o */
|
|
139
|
+
NULL, /* -h */
|
|
140
|
+
NULL, /* --etags-include */
|
|
141
|
+
DEFAULT_FILE_FORMAT,/* --format */
|
|
142
|
+
FALSE, /* --if0 */
|
|
143
|
+
FALSE, /* --kind-long */
|
|
144
|
+
LANG_AUTO, /* --lang */
|
|
145
|
+
TRUE, /* --links */
|
|
146
|
+
FALSE, /* --filter */
|
|
147
|
+
NULL, /* --filter-terminator */
|
|
148
|
+
FALSE, /* --tag-relative */
|
|
149
|
+
FALSE, /* --totals */
|
|
150
|
+
FALSE, /* --line-directives */
|
|
151
|
+
#ifdef DEBUG
|
|
152
|
+
0, 0 /* -D, -b */
|
|
153
|
+
#endif
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
- Locally used only
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
static optionDescription LongOptionDescription [] = {
|
|
161
|
+
{1," -a Append the tags to an existing tag file."},
|
|
162
|
+
#ifdef DEBUG
|
|
163
|
+
{1," -b <line>"},
|
|
164
|
+
{1," Set break line."},
|
|
165
|
+
#endif
|
|
166
|
+
{0," -B Use backward searching patterns (?...?)."},
|
|
167
|
+
#ifdef DEBUG
|
|
168
|
+
{1," -D <level>"},
|
|
169
|
+
{1," Set debug level."},
|
|
170
|
+
#endif
|
|
171
|
+
{0," -e Output tag file for use with Emacs."},
|
|
172
|
+
{1," -f <name>"},
|
|
173
|
+
{1," Write tags to specified file. Value of \"-\" writes tags to stdout"},
|
|
174
|
+
{1," [\"tags\"; or \"TAGS\" when -e supplied]."},
|
|
175
|
+
{0," -F Use forward searching patterns (/.../) (default)."},
|
|
176
|
+
{1," -h <list>"},
|
|
177
|
+
{1," Specify list of file extensions to be treated as include files."},
|
|
178
|
+
{1," [\".h.H.hh.hpp.hxx.h++\"]."},
|
|
179
|
+
{1," -I <list|@file>"},
|
|
180
|
+
{1," A list of tokens to be specially handled is read from either the"},
|
|
181
|
+
{1," command line or the specified file."},
|
|
182
|
+
{1," -L <file>"},
|
|
183
|
+
{1," A list of source file names are read from the specified file."},
|
|
184
|
+
{1," If specified as \"-\", then standard input is read."},
|
|
185
|
+
{0," -n Equivalent to --excmd=number."},
|
|
186
|
+
{0," -N Equivalent to --excmd=pattern."},
|
|
187
|
+
{1," -o Alternative for -f."},
|
|
188
|
+
#ifdef RECURSE_SUPPORTED
|
|
189
|
+
{1," -R Equivalent to --recurse."},
|
|
190
|
+
#else
|
|
191
|
+
{1," -R Not supported on this platform."},
|
|
192
|
+
#endif
|
|
193
|
+
{0," -u Equivalent to --sort=no."},
|
|
194
|
+
{1," -V Equivalent to --verbose."},
|
|
195
|
+
{1," -x Print a tabular cross reference file to standard output."},
|
|
196
|
+
{1," --append=[yes|no]"},
|
|
197
|
+
{1," Should tags should be appended to existing tag file [no]?"},
|
|
198
|
+
{1," --etags-include=file"},
|
|
199
|
+
{1," Include reference to 'file' in Emacs-style tag file (requires -e)."},
|
|
200
|
+
{1," --exclude=pattern"},
|
|
201
|
+
{1," Exclude files and directories matching 'pattern'."},
|
|
202
|
+
{0," --excmd=number|pattern|mix"},
|
|
203
|
+
#ifdef MACROS_USE_PATTERNS
|
|
204
|
+
{0," Uses the specified type of EX command to locate tags [pattern]."},
|
|
205
|
+
#else
|
|
206
|
+
{0," Uses the specified type of EX command to locate tags [mix]."},
|
|
207
|
+
#endif
|
|
208
|
+
{1," --extra=[+|-]flags"},
|
|
209
|
+
{1," Include extra tag entries for selected information (flags: \"fq\")."},
|
|
210
|
+
{1," --fields=[+|-]flags"},
|
|
211
|
+
{1," Include selected extension fields (flags: \"afmikKlnsStz\") [fks]."},
|
|
212
|
+
{1," --file-scope=[yes|no]"},
|
|
213
|
+
{1," Should tags scoped only for a single file (e.g. \"static\" tags"},
|
|
214
|
+
{1," be included in the output [yes]?"},
|
|
215
|
+
{1," --filter=[yes|no]"},
|
|
216
|
+
{1," Behave as a filter, reading file names from standard input and"},
|
|
217
|
+
{1," writing tags to standard output [no]."},
|
|
218
|
+
{1," --filter-terminator=string"},
|
|
219
|
+
{1," Specify string to print to stdout following the tags for each file"},
|
|
220
|
+
{1," parsed when --filter is enabled."},
|
|
221
|
+
{0," --format=level"},
|
|
222
|
+
#if DEFAULT_FILE_FORMAT == 1
|
|
223
|
+
{0," Force output of specified tag file format [1]."},
|
|
224
|
+
#else
|
|
225
|
+
{0," Force output of specified tag file format [2]."},
|
|
226
|
+
#endif
|
|
227
|
+
{1," --help"},
|
|
228
|
+
{1," Print this option summary."},
|
|
229
|
+
{1," --if0=[yes|no]"},
|
|
230
|
+
{1," Should C code within #if 0 conditional branches be parsed [no]?"},
|
|
231
|
+
{1," --<LANG>-kinds=[+|-]kinds"},
|
|
232
|
+
{1," Enable/disable tag kinds for language <LANG>."},
|
|
233
|
+
{1," --langdef=name"},
|
|
234
|
+
{1," Define a new language to be parsed with regular expressions."},
|
|
235
|
+
{1," --langmap=map(s)"},
|
|
236
|
+
{1," Override default mapping of language to source file extension."},
|
|
237
|
+
{1," --language-force=language"},
|
|
238
|
+
{1," Force all files to be interpreted using specified language."},
|
|
239
|
+
{1," --languages=[+|-]list"},
|
|
240
|
+
{1," Restrict files scanned for tags to those mapped to langauges"},
|
|
241
|
+
{1," specified in the comma-separated 'list'. The list can contain any"},
|
|
242
|
+
{1," built-in or user-defined language [all]."},
|
|
243
|
+
{1," --license"},
|
|
244
|
+
{1," Print details of software license."},
|
|
245
|
+
{0," --line-directives=[yes|no]"},
|
|
246
|
+
{0," Should #line directives be processed [no]?"},
|
|
247
|
+
{1," --links=[yes|no]"},
|
|
248
|
+
{1," Indicate whether symbolic links should be followed [yes]."},
|
|
249
|
+
{1," --list-kinds=[language|all]"},
|
|
250
|
+
{1," Output a list of all tag kinds for specified language or all."},
|
|
251
|
+
{1," --list-languages"},
|
|
252
|
+
{1," Output list of supported languages."},
|
|
253
|
+
{1," --list-maps=[language|all]"},
|
|
254
|
+
{1," Output list of language mappings."},
|
|
255
|
+
{1," --options=file"},
|
|
256
|
+
{1," Specify file from which command line options should be read."},
|
|
257
|
+
{1," --recurse=[yes|no]"},
|
|
258
|
+
#ifdef RECURSE_SUPPORTED
|
|
259
|
+
{1," Recurse into directories supplied on command line [no]."},
|
|
260
|
+
#else
|
|
261
|
+
{1," Not supported on this platform."},
|
|
262
|
+
#endif
|
|
263
|
+
#ifdef HAVE_REGEX
|
|
264
|
+
{1," --regex-<LANG>=/line_pattern/name_pattern/[flags]"},
|
|
265
|
+
{1," Define regular expression for locating tags in specific language."},
|
|
266
|
+
#endif
|
|
267
|
+
{0," --sort=[yes|no|foldcase]"},
|
|
268
|
+
{0," Should tags be sorted (optionally ignoring case) [yes]?."},
|
|
269
|
+
{0," --tag-relative=[yes|no]"},
|
|
270
|
+
{0," Should paths be relative to location of tag file [no; yes when -e]?"},
|
|
271
|
+
{1," --totals=[yes|no]"},
|
|
272
|
+
{1," Print statistics about source and tag files [no]."},
|
|
273
|
+
{1," --verbose=[yes|no]"},
|
|
274
|
+
{1," Enable verbose messages describing actions on each source file."},
|
|
275
|
+
{1," --version"},
|
|
276
|
+
{1," Print version identifier to standard output."},
|
|
277
|
+
{1, NULL}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
static const char* const License1 =
|
|
281
|
+
"This program is free software; you can redistribute it and/or\n"
|
|
282
|
+
"modify it under the terms of the GNU General Public License\n"
|
|
283
|
+
"as published by the Free Software Foundation; either version 2\n"
|
|
284
|
+
"of the License, or (at your option) any later version.\n"
|
|
285
|
+
"\n";
|
|
286
|
+
static const char* const License2 =
|
|
287
|
+
"This program is distributed in the hope that it will be useful,\n"
|
|
288
|
+
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
289
|
+
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
290
|
+
"GNU General Public License for more details.\n"
|
|
291
|
+
"\n"
|
|
292
|
+
"You should have received a copy of the GNU General Public License\n"
|
|
293
|
+
"along with this program; if not, write to the Free Software\n"
|
|
294
|
+
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
|
|
295
|
+
|
|
296
|
+
/* Contains a set of strings describing the set of "features" compiled into
|
|
297
|
+
* the code.
|
|
298
|
+
*/
|
|
299
|
+
static const char *const Features [] = {
|
|
300
|
+
#ifdef WIN32
|
|
301
|
+
"win32",
|
|
302
|
+
#endif
|
|
303
|
+
#ifdef DJGPP
|
|
304
|
+
"msdos_32",
|
|
305
|
+
#else
|
|
306
|
+
# ifdef MSDOS
|
|
307
|
+
"msdos_16",
|
|
308
|
+
# endif
|
|
309
|
+
#endif
|
|
310
|
+
#ifdef OS2
|
|
311
|
+
"os2",
|
|
312
|
+
#endif
|
|
313
|
+
#ifdef AMIGA
|
|
314
|
+
"amiga",
|
|
315
|
+
#endif
|
|
316
|
+
#ifdef VMS
|
|
317
|
+
"vms",
|
|
318
|
+
#endif
|
|
319
|
+
#ifdef HAVE_FNMATCH
|
|
320
|
+
"wildcards",
|
|
321
|
+
#endif
|
|
322
|
+
#ifdef HAVE_REGEX
|
|
323
|
+
"regex",
|
|
324
|
+
#endif
|
|
325
|
+
#ifndef EXTERNAL_SORT
|
|
326
|
+
"internal-sort",
|
|
327
|
+
#endif
|
|
328
|
+
#ifdef CUSTOM_CONFIGURATION_FILE
|
|
329
|
+
"custom-conf",
|
|
330
|
+
#endif
|
|
331
|
+
#if (defined (MSDOS) || defined (WIN32) || defined (OS2)) && defined (UNIX_PATH_SEPARATOR)
|
|
332
|
+
"unix-path-separator",
|
|
333
|
+
#endif
|
|
334
|
+
#ifdef DEBUG
|
|
335
|
+
"debug",
|
|
336
|
+
#endif
|
|
337
|
+
NULL
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/*
|
|
341
|
+
* FUNCTION PROTOTYPES
|
|
342
|
+
*/
|
|
343
|
+
static boolean parseFileOptions (const char *const fileName);
|
|
344
|
+
|
|
345
|
+
/*
|
|
346
|
+
* FUNCTION DEFINITIONS
|
|
347
|
+
*/
|
|
348
|
+
|
|
349
|
+
extern void verbose (const char *const format, ...)
|
|
350
|
+
{
|
|
351
|
+
if (Option.verbose)
|
|
352
|
+
{
|
|
353
|
+
va_list ap;
|
|
354
|
+
va_start (ap, format);
|
|
355
|
+
vprintf (format, ap);
|
|
356
|
+
va_end (ap);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
static char *stringCopy (const char *const string)
|
|
361
|
+
{
|
|
362
|
+
char* result = NULL;
|
|
363
|
+
if (string != NULL)
|
|
364
|
+
result = eStrdup (string);
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
static void freeString (char **const pString)
|
|
369
|
+
{
|
|
370
|
+
if (*pString != NULL)
|
|
371
|
+
{
|
|
372
|
+
eFree (*pString);
|
|
373
|
+
*pString = NULL;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
extern void freeList (stringList** const pList)
|
|
378
|
+
{
|
|
379
|
+
if (*pList != NULL)
|
|
380
|
+
{
|
|
381
|
+
stringListDelete (*pList);
|
|
382
|
+
*pList = NULL;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
extern void setDefaultTagFileName (void)
|
|
387
|
+
{
|
|
388
|
+
if (Option.tagFileName != NULL)
|
|
389
|
+
; /* accept given name */
|
|
390
|
+
else if (Option.etags)
|
|
391
|
+
Option.tagFileName = stringCopy (ETAGS_FILE);
|
|
392
|
+
else
|
|
393
|
+
Option.tagFileName = stringCopy (CTAGS_FILE);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
extern boolean filesRequired (void)
|
|
397
|
+
{
|
|
398
|
+
boolean result = FilesRequired;
|
|
399
|
+
if (Option.recurse || Option.stdinFileName)
|
|
400
|
+
result = FALSE;
|
|
401
|
+
return result;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
extern void checkOptions (void)
|
|
405
|
+
{
|
|
406
|
+
const char* notice;
|
|
407
|
+
if (Option.xref)
|
|
408
|
+
{
|
|
409
|
+
notice = "xref output";
|
|
410
|
+
if (Option.include.fileNames)
|
|
411
|
+
{
|
|
412
|
+
error (WARNING, "%s disables file name tags", notice);
|
|
413
|
+
Option.include.fileNames = FALSE;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (Option.append)
|
|
417
|
+
{
|
|
418
|
+
notice = "append mode is not compatible with";
|
|
419
|
+
if (isDestinationStdout ())
|
|
420
|
+
error (FATAL, "%s tags to stdout", notice);
|
|
421
|
+
}
|
|
422
|
+
if (Option.filter)
|
|
423
|
+
{
|
|
424
|
+
notice = "filter mode";
|
|
425
|
+
if (Option.printTotals)
|
|
426
|
+
{
|
|
427
|
+
error (WARNING, "%s disables totals", notice);
|
|
428
|
+
Option.printTotals = FALSE;
|
|
429
|
+
}
|
|
430
|
+
if (Option.tagFileName != NULL)
|
|
431
|
+
error (WARNING, "%s ignores output tag file name", notice);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
static void setEtagsMode (void)
|
|
436
|
+
{
|
|
437
|
+
Option.etags = TRUE;
|
|
438
|
+
Option.sorted = SO_UNSORTED;
|
|
439
|
+
Option.lineDirectives = FALSE;
|
|
440
|
+
Option.tagRelative = TRUE;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
extern void testEtagsInvocation (void)
|
|
444
|
+
{
|
|
445
|
+
char* const execName = eStrdup (getExecutableName ());
|
|
446
|
+
char* const etags = eStrdup (ETAGS);
|
|
447
|
+
#ifdef CASE_INSENSITIVE_FILENAMES
|
|
448
|
+
toLowerString (execName);
|
|
449
|
+
toLowerString (etags);
|
|
450
|
+
#endif
|
|
451
|
+
if (strstr (execName, etags) != NULL)
|
|
452
|
+
{
|
|
453
|
+
verbose ("Running in etags mode\n");
|
|
454
|
+
setEtagsMode ();
|
|
455
|
+
}
|
|
456
|
+
eFree (execName);
|
|
457
|
+
eFree (etags);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/*
|
|
461
|
+
* Cooked argument parsing
|
|
462
|
+
*/
|
|
463
|
+
|
|
464
|
+
static void parseShortOption (cookedArgs *const args)
|
|
465
|
+
{
|
|
466
|
+
args->simple [0] = *args->shortOptions++;
|
|
467
|
+
args->simple [1] = '\0';
|
|
468
|
+
args->item = args->simple;
|
|
469
|
+
if (! isCompoundOption (*args->simple))
|
|
470
|
+
args->parameter = "";
|
|
471
|
+
else if (*args->shortOptions == '\0')
|
|
472
|
+
{
|
|
473
|
+
argForth (args->args);
|
|
474
|
+
if (argOff (args->args))
|
|
475
|
+
args->parameter = NULL;
|
|
476
|
+
else
|
|
477
|
+
args->parameter = argItem (args->args);
|
|
478
|
+
args->shortOptions = NULL;
|
|
479
|
+
}
|
|
480
|
+
else
|
|
481
|
+
{
|
|
482
|
+
args->parameter = args->shortOptions;
|
|
483
|
+
args->shortOptions = NULL;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
static void parseLongOption (cookedArgs *const args, const char *item)
|
|
488
|
+
{
|
|
489
|
+
const char* const equal = strchr (item, '=');
|
|
490
|
+
if (equal == NULL)
|
|
491
|
+
{
|
|
492
|
+
args->item = eStrdup (item); /* FIXME: memory leak. */
|
|
493
|
+
args->parameter = "";
|
|
494
|
+
}
|
|
495
|
+
else
|
|
496
|
+
{
|
|
497
|
+
const size_t length = equal - item;
|
|
498
|
+
args->item = xMalloc (length + 1, char); /* FIXME: memory leak. */
|
|
499
|
+
strncpy (args->item, item, length);
|
|
500
|
+
args->item [length] = '\0';
|
|
501
|
+
args->parameter = equal + 1;
|
|
502
|
+
}
|
|
503
|
+
Assert (args->item != NULL);
|
|
504
|
+
Assert (args->parameter != NULL);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
static void cArgRead (cookedArgs *const current)
|
|
508
|
+
{
|
|
509
|
+
char* item;
|
|
510
|
+
|
|
511
|
+
Assert (current != NULL);
|
|
512
|
+
if (! argOff (current->args))
|
|
513
|
+
{
|
|
514
|
+
item = argItem (current->args);
|
|
515
|
+
current->shortOptions = NULL;
|
|
516
|
+
Assert (item != NULL);
|
|
517
|
+
if (strncmp (item, "--", (size_t) 2) == 0)
|
|
518
|
+
{
|
|
519
|
+
current->isOption = TRUE;
|
|
520
|
+
current->longOption = TRUE;
|
|
521
|
+
parseLongOption (current, item + 2);
|
|
522
|
+
Assert (current->item != NULL);
|
|
523
|
+
Assert (current->parameter != NULL);
|
|
524
|
+
}
|
|
525
|
+
else if (*item == '-')
|
|
526
|
+
{
|
|
527
|
+
current->isOption = TRUE;
|
|
528
|
+
current->longOption = FALSE;
|
|
529
|
+
current->shortOptions = item + 1;
|
|
530
|
+
parseShortOption (current);
|
|
531
|
+
}
|
|
532
|
+
else
|
|
533
|
+
{
|
|
534
|
+
current->isOption = FALSE;
|
|
535
|
+
current->longOption = FALSE;
|
|
536
|
+
current->item = item;
|
|
537
|
+
current->parameter = NULL;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
extern cookedArgs* cArgNewFromString (const char* string)
|
|
543
|
+
{
|
|
544
|
+
cookedArgs* const result = xMalloc (1, cookedArgs);
|
|
545
|
+
memset (result, 0, sizeof (cookedArgs));
|
|
546
|
+
result->args = argNewFromString (string);
|
|
547
|
+
cArgRead (result);
|
|
548
|
+
return result;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
extern cookedArgs* cArgNewFromArgv (char* const* const argv)
|
|
552
|
+
{
|
|
553
|
+
cookedArgs* const result = xMalloc (1, cookedArgs);
|
|
554
|
+
memset (result, 0, sizeof (cookedArgs));
|
|
555
|
+
result->args = argNewFromArgv (argv);
|
|
556
|
+
cArgRead (result);
|
|
557
|
+
return result;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
extern cookedArgs* cArgNewFromFile (FILE* const fp)
|
|
561
|
+
{
|
|
562
|
+
cookedArgs* const result = xMalloc (1, cookedArgs);
|
|
563
|
+
memset (result, 0, sizeof (cookedArgs));
|
|
564
|
+
result->args = argNewFromFile (fp);
|
|
565
|
+
cArgRead (result);
|
|
566
|
+
return result;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
extern cookedArgs* cArgNewFromLineFile (FILE* const fp)
|
|
570
|
+
{
|
|
571
|
+
cookedArgs* const result = xMalloc (1, cookedArgs);
|
|
572
|
+
memset (result, 0, sizeof (cookedArgs));
|
|
573
|
+
result->args = argNewFromLineFile (fp);
|
|
574
|
+
cArgRead (result);
|
|
575
|
+
return result;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
extern void cArgDelete (cookedArgs* const current)
|
|
579
|
+
{
|
|
580
|
+
Assert (current != NULL);
|
|
581
|
+
argDelete (current->args);
|
|
582
|
+
memset (current, 0, sizeof (cookedArgs));
|
|
583
|
+
eFree (current);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
static boolean cArgOptionPending (cookedArgs* const current)
|
|
587
|
+
{
|
|
588
|
+
boolean result = FALSE;
|
|
589
|
+
if (current->shortOptions != NULL)
|
|
590
|
+
if (*current->shortOptions != '\0')
|
|
591
|
+
result = TRUE;
|
|
592
|
+
return result;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
extern boolean cArgOff (cookedArgs* const current)
|
|
596
|
+
{
|
|
597
|
+
Assert (current != NULL);
|
|
598
|
+
return (boolean) (argOff (current->args) && ! cArgOptionPending (current));
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
extern boolean cArgIsOption (cookedArgs* const current)
|
|
602
|
+
{
|
|
603
|
+
Assert (current != NULL);
|
|
604
|
+
return current->isOption;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
extern const char* cArgItem (cookedArgs* const current)
|
|
608
|
+
{
|
|
609
|
+
Assert (current != NULL);
|
|
610
|
+
return current->item;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
extern void cArgForth (cookedArgs* const current)
|
|
614
|
+
{
|
|
615
|
+
Assert (current != NULL);
|
|
616
|
+
Assert (! cArgOff (current));
|
|
617
|
+
if (cArgOptionPending (current))
|
|
618
|
+
parseShortOption (current);
|
|
619
|
+
else
|
|
620
|
+
{
|
|
621
|
+
Assert (! argOff (current->args));
|
|
622
|
+
argForth (current->args);
|
|
623
|
+
if (! argOff (current->args))
|
|
624
|
+
cArgRead (current);
|
|
625
|
+
else
|
|
626
|
+
{
|
|
627
|
+
current->isOption = FALSE;
|
|
628
|
+
current->longOption = FALSE;
|
|
629
|
+
current->shortOptions = NULL;
|
|
630
|
+
current->item = NULL;
|
|
631
|
+
current->parameter = NULL;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/*
|
|
637
|
+
* File extension and language mapping
|
|
638
|
+
*/
|
|
639
|
+
|
|
640
|
+
static void addExtensionList (
|
|
641
|
+
stringList *const slist, const char *const elist, const boolean clear)
|
|
642
|
+
{
|
|
643
|
+
char *const extensionList = eStrdup (elist);
|
|
644
|
+
const char *extension = NULL;
|
|
645
|
+
boolean first = TRUE;
|
|
646
|
+
|
|
647
|
+
if (clear)
|
|
648
|
+
{
|
|
649
|
+
verbose (" clearing\n");
|
|
650
|
+
stringListClear (slist);
|
|
651
|
+
}
|
|
652
|
+
verbose (" adding: ");
|
|
653
|
+
if (elist != NULL && *elist != '\0')
|
|
654
|
+
{
|
|
655
|
+
extension = extensionList;
|
|
656
|
+
if (elist [0] == EXTENSION_SEPARATOR)
|
|
657
|
+
++extension;
|
|
658
|
+
}
|
|
659
|
+
while (extension != NULL)
|
|
660
|
+
{
|
|
661
|
+
char *separator = strchr (extension, EXTENSION_SEPARATOR);
|
|
662
|
+
if (separator != NULL)
|
|
663
|
+
*separator = '\0';
|
|
664
|
+
verbose ("%s%s", first ? "" : ", ",
|
|
665
|
+
*extension == '\0' ? "(NONE)" : extension);
|
|
666
|
+
stringListAdd (slist, vStringNewInit (extension));
|
|
667
|
+
first = FALSE;
|
|
668
|
+
if (separator == NULL)
|
|
669
|
+
extension = NULL;
|
|
670
|
+
else
|
|
671
|
+
extension = separator + 1;
|
|
672
|
+
}
|
|
673
|
+
if (Option.verbose)
|
|
674
|
+
{
|
|
675
|
+
printf ("\n now: ");
|
|
676
|
+
stringListPrint (slist);
|
|
677
|
+
putchar ('\n');
|
|
678
|
+
}
|
|
679
|
+
eFree (extensionList);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
static boolean isFalse (const char *parameter)
|
|
683
|
+
{
|
|
684
|
+
return (boolean) (
|
|
685
|
+
strcasecmp (parameter, "0" ) == 0 ||
|
|
686
|
+
strcasecmp (parameter, "n" ) == 0 ||
|
|
687
|
+
strcasecmp (parameter, "no" ) == 0 ||
|
|
688
|
+
strcasecmp (parameter, "off") == 0);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
static boolean isTrue (const char *parameter)
|
|
692
|
+
{
|
|
693
|
+
return (boolean) (
|
|
694
|
+
strcasecmp (parameter, "1" ) == 0 ||
|
|
695
|
+
strcasecmp (parameter, "y" ) == 0 ||
|
|
696
|
+
strcasecmp (parameter, "yes") == 0 ||
|
|
697
|
+
strcasecmp (parameter, "on" ) == 0);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/* Determines whether the specified file name is considered to be a header
|
|
701
|
+
* file for the purposes of determining whether enclosed tags are global or
|
|
702
|
+
* static.
|
|
703
|
+
*/
|
|
704
|
+
extern boolean isIncludeFile (const char *const fileName)
|
|
705
|
+
{
|
|
706
|
+
boolean result = FALSE;
|
|
707
|
+
const char *const extension = fileExtension (fileName);
|
|
708
|
+
if (Option.headerExt != NULL)
|
|
709
|
+
result = stringListExtensionMatched (Option.headerExt, extension);
|
|
710
|
+
return result;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/*
|
|
714
|
+
* Specific option processing
|
|
715
|
+
*/
|
|
716
|
+
|
|
717
|
+
static void processEtagsInclude (
|
|
718
|
+
const char *const option, const char *const parameter)
|
|
719
|
+
{
|
|
720
|
+
if (! Option.etags)
|
|
721
|
+
error (FATAL, "Etags must be enabled to use \"%s\" option", option);
|
|
722
|
+
else
|
|
723
|
+
{
|
|
724
|
+
vString *const file = vStringNewInit (parameter);
|
|
725
|
+
if (Option.etagsInclude == NULL)
|
|
726
|
+
Option.etagsInclude = stringListNew ();
|
|
727
|
+
stringListAdd (Option.etagsInclude, file);
|
|
728
|
+
FilesRequired = FALSE;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
static void processExcludeOption (
|
|
733
|
+
const char *const option __unused__, const char *const parameter)
|
|
734
|
+
{
|
|
735
|
+
const char *const fileName = parameter + 1;
|
|
736
|
+
if (parameter [0] == '\0')
|
|
737
|
+
freeList (&Excluded);
|
|
738
|
+
else if (parameter [0] == '@')
|
|
739
|
+
{
|
|
740
|
+
stringList* const sl = stringListNewFromFile (fileName);
|
|
741
|
+
if (sl == NULL)
|
|
742
|
+
error (FATAL | PERROR, "cannot open \"%s\"", fileName);
|
|
743
|
+
if (Excluded == NULL)
|
|
744
|
+
Excluded = sl;
|
|
745
|
+
else
|
|
746
|
+
stringListCombine (Excluded, sl);
|
|
747
|
+
verbose (" adding exclude patterns from %s\n", fileName);
|
|
748
|
+
}
|
|
749
|
+
else
|
|
750
|
+
{
|
|
751
|
+
vString *const item = vStringNewInit (parameter);
|
|
752
|
+
if (Excluded == NULL)
|
|
753
|
+
Excluded = stringListNew ();
|
|
754
|
+
stringListAdd (Excluded, item);
|
|
755
|
+
verbose (" adding exclude pattern: %s\n", parameter);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
extern boolean isExcludedFile (const char* const name)
|
|
760
|
+
{
|
|
761
|
+
const char* base = baseFilename (name);
|
|
762
|
+
boolean result = FALSE;
|
|
763
|
+
if (Excluded != NULL)
|
|
764
|
+
{
|
|
765
|
+
result = stringListFileMatched (Excluded, base);
|
|
766
|
+
if (! result && name != base)
|
|
767
|
+
result = stringListFileMatched (Excluded, name);
|
|
768
|
+
}
|
|
769
|
+
#ifdef AMIGA
|
|
770
|
+
/* not a good solution, but the only one which works often */
|
|
771
|
+
if (! result)
|
|
772
|
+
result = (boolean) (strcmp (name, TagFile.name) == 0);
|
|
773
|
+
#endif
|
|
774
|
+
return result;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
static void processExcmdOption (
|
|
778
|
+
const char *const option, const char *const parameter)
|
|
779
|
+
{
|
|
780
|
+
switch (*parameter)
|
|
781
|
+
{
|
|
782
|
+
case 'm': Option.locate = EX_MIX; break;
|
|
783
|
+
case 'n': Option.locate = EX_LINENUM; break;
|
|
784
|
+
case 'p': Option.locate = EX_PATTERN; break;
|
|
785
|
+
default:
|
|
786
|
+
error (FATAL, "Invalid value for \"%s\" option", option);
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
static void processExtraTagsOption (
|
|
792
|
+
const char *const option, const char *const parameter)
|
|
793
|
+
{
|
|
794
|
+
struct sInclude *const inc = &Option.include;
|
|
795
|
+
const char *p = parameter;
|
|
796
|
+
boolean mode = TRUE;
|
|
797
|
+
int c;
|
|
798
|
+
|
|
799
|
+
if (*p != '+' && *p != '-')
|
|
800
|
+
{
|
|
801
|
+
inc->fileNames = FALSE;
|
|
802
|
+
inc->qualifiedTags = FALSE;
|
|
803
|
+
#if 0
|
|
804
|
+
inc->fileScope = FALSE;
|
|
805
|
+
#endif
|
|
806
|
+
}
|
|
807
|
+
while ((c = *p++) != '\0') switch (c)
|
|
808
|
+
{
|
|
809
|
+
case '+': mode = TRUE; break;
|
|
810
|
+
case '-': mode = FALSE; break;
|
|
811
|
+
|
|
812
|
+
case 'f': inc->fileNames = mode; break;
|
|
813
|
+
case 'q': inc->qualifiedTags = mode; break;
|
|
814
|
+
#if 0
|
|
815
|
+
case 'F': inc->fileScope = mode; break;
|
|
816
|
+
#endif
|
|
817
|
+
|
|
818
|
+
default: error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
|
|
819
|
+
c, option);
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
static void processFieldsOption (
|
|
825
|
+
const char *const option, const char *const parameter)
|
|
826
|
+
{
|
|
827
|
+
struct sExtFields *field = &Option.extensionFields;
|
|
828
|
+
const char *p = parameter;
|
|
829
|
+
boolean mode = TRUE;
|
|
830
|
+
int c;
|
|
831
|
+
|
|
832
|
+
if (*p != '+' && *p != '-')
|
|
833
|
+
{
|
|
834
|
+
field->access = FALSE;
|
|
835
|
+
field->fileScope = FALSE;
|
|
836
|
+
field->implementation = FALSE;
|
|
837
|
+
field->inheritance = FALSE;
|
|
838
|
+
field->kind = FALSE;
|
|
839
|
+
field->kindKey = FALSE;
|
|
840
|
+
field->kindLong = FALSE;
|
|
841
|
+
field->language = FALSE;
|
|
842
|
+
field->scope = FALSE;
|
|
843
|
+
field->typeRef = FALSE;
|
|
844
|
+
}
|
|
845
|
+
while ((c = *p++) != '\0') switch (c)
|
|
846
|
+
{
|
|
847
|
+
case '+': mode = TRUE; break;
|
|
848
|
+
case '-': mode = FALSE; break;
|
|
849
|
+
|
|
850
|
+
case 'a': field->access = mode; break;
|
|
851
|
+
case 'f': field->fileScope = mode; break;
|
|
852
|
+
case 'm': field->implementation = mode; break;
|
|
853
|
+
case 'i': field->inheritance = mode; break;
|
|
854
|
+
case 'k': field->kind = mode; break;
|
|
855
|
+
case 'K': field->kindLong = mode; break;
|
|
856
|
+
case 'l': field->language = mode; break;
|
|
857
|
+
case 'n': field->lineNumber = mode; break;
|
|
858
|
+
case 's': field->scope = mode; break;
|
|
859
|
+
case 'S': field->signature = mode; break;
|
|
860
|
+
case 'z': field->kindKey = mode; break;
|
|
861
|
+
case 't': field->typeRef = mode; break;
|
|
862
|
+
|
|
863
|
+
default: error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
|
|
864
|
+
c, option);
|
|
865
|
+
break;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
static void processFilterTerminatorOption (
|
|
870
|
+
const char *const option __unused__, const char *const parameter)
|
|
871
|
+
{
|
|
872
|
+
freeString (&Option.filterTerminator);
|
|
873
|
+
Option.filterTerminator = stringCopy (parameter);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
static void processFormatOption (
|
|
877
|
+
const char *const option, const char *const parameter)
|
|
878
|
+
{
|
|
879
|
+
unsigned int format;
|
|
880
|
+
|
|
881
|
+
if (sscanf (parameter, "%u", &format) < 1)
|
|
882
|
+
error (FATAL, "Invalid value for \"%s\" option",option);
|
|
883
|
+
else if (format <= (unsigned int) MaxSupportedTagFormat)
|
|
884
|
+
Option.tagFileFormat = format;
|
|
885
|
+
else
|
|
886
|
+
error (FATAL, "Unsupported value for \"%s\" option", option);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
static void printInvocationDescription (void)
|
|
890
|
+
{
|
|
891
|
+
printf (INVOCATION, getExecutableName ());
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
static void printOptionDescriptions (const optionDescription *const optDesc)
|
|
895
|
+
{
|
|
896
|
+
int i;
|
|
897
|
+
for (i = 0 ; optDesc [i].description != NULL ; ++i)
|
|
898
|
+
{
|
|
899
|
+
if (! Option.etags || optDesc [i].usedByEtags)
|
|
900
|
+
puts (optDesc [i].description);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
static void printFeatureList (void)
|
|
905
|
+
{
|
|
906
|
+
int i;
|
|
907
|
+
|
|
908
|
+
for (i = 0 ; Features [i] != NULL ; ++i)
|
|
909
|
+
{
|
|
910
|
+
if (i == 0)
|
|
911
|
+
printf (" Optional compiled features: ");
|
|
912
|
+
printf ("%s+%s", (i>0 ? ", " : ""), Features [i]);
|
|
913
|
+
#ifdef CUSTOM_CONFIGURATION_FILE
|
|
914
|
+
if (strcmp (Features [i], "custom-conf") == 0)
|
|
915
|
+
printf ("=%s", CUSTOM_CONFIGURATION_FILE);
|
|
916
|
+
#endif
|
|
917
|
+
}
|
|
918
|
+
if (i > 0)
|
|
919
|
+
putchar ('\n');
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
static void printProgramIdentification (void)
|
|
923
|
+
{
|
|
924
|
+
printf ("%s %s, %s %s\n",
|
|
925
|
+
PROGRAM_NAME, PROGRAM_VERSION,
|
|
926
|
+
PROGRAM_COPYRIGHT, AUTHOR_NAME);
|
|
927
|
+
printf (" Compiled: %s, %s\n", __DATE__, __TIME__);
|
|
928
|
+
printf (" Addresses: <%s>, %s\n", AUTHOR_EMAIL, PROGRAM_URL);
|
|
929
|
+
printFeatureList ();
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
static void processHelpOption (
|
|
933
|
+
const char *const option __unused__,
|
|
934
|
+
const char *const parameter __unused__)
|
|
935
|
+
{
|
|
936
|
+
printProgramIdentification ();
|
|
937
|
+
putchar ('\n');
|
|
938
|
+
printInvocationDescription ();
|
|
939
|
+
putchar ('\n');
|
|
940
|
+
printOptionDescriptions (LongOptionDescription);
|
|
941
|
+
exit (0);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
static void processLanguageForceOption (
|
|
945
|
+
const char *const option, const char *const parameter)
|
|
946
|
+
{
|
|
947
|
+
langType language;
|
|
948
|
+
if (strcasecmp (parameter, "auto") == 0)
|
|
949
|
+
language = LANG_AUTO;
|
|
950
|
+
else
|
|
951
|
+
language = getNamedLanguage (parameter);
|
|
952
|
+
|
|
953
|
+
if (strcmp (option, "lang") == 0 || strcmp (option, "language") == 0)
|
|
954
|
+
error (WARNING,
|
|
955
|
+
"\"--%s\" option is obsolete; use \"--language-force\" instead",
|
|
956
|
+
option);
|
|
957
|
+
if (language == LANG_IGNORE)
|
|
958
|
+
error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
|
|
959
|
+
else
|
|
960
|
+
Option.language = language;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
static void processStdinFileName (
|
|
964
|
+
const char *const option, const char *const parameter)
|
|
965
|
+
{
|
|
966
|
+
if (strlen(parameter) == 0) {
|
|
967
|
+
error (FATAL, "No filename specified for --stdin-filename");
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
Option.stdinFileName = stringCopy(parameter);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
static char* skipPastMap (char* p)
|
|
974
|
+
{
|
|
975
|
+
while (*p != EXTENSION_SEPARATOR &&
|
|
976
|
+
*p != PATTERN_START && *p != ',' && *p != '\0')
|
|
977
|
+
++p;
|
|
978
|
+
return p;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/* Parses the mapping beginning at `map', adds it to the language map, and
|
|
982
|
+
* returns first character past the map.
|
|
983
|
+
*/
|
|
984
|
+
static char* addLanguageMap (const langType language, char* map)
|
|
985
|
+
{
|
|
986
|
+
char* p = NULL;
|
|
987
|
+
const char first = *map;
|
|
988
|
+
if (first == EXTENSION_SEPARATOR) /* extension map */
|
|
989
|
+
{
|
|
990
|
+
++map;
|
|
991
|
+
p = skipPastMap (map);
|
|
992
|
+
if (*p == '\0')
|
|
993
|
+
{
|
|
994
|
+
verbose (" .%s", map);
|
|
995
|
+
addLanguageExtensionMap (language, map);
|
|
996
|
+
p = map + strlen (map);
|
|
997
|
+
}
|
|
998
|
+
else
|
|
999
|
+
{
|
|
1000
|
+
const char separator = *p;
|
|
1001
|
+
*p = '\0';
|
|
1002
|
+
verbose (" .%s", map);
|
|
1003
|
+
addLanguageExtensionMap (language, map);
|
|
1004
|
+
*p = separator;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
else if (first == PATTERN_START) /* pattern map */
|
|
1008
|
+
{
|
|
1009
|
+
++map;
|
|
1010
|
+
for (p = map ; *p != PATTERN_STOP && *p != '\0' ; ++p)
|
|
1011
|
+
{
|
|
1012
|
+
if (*p == '\\' && *(p + 1) == PATTERN_STOP)
|
|
1013
|
+
++p;
|
|
1014
|
+
}
|
|
1015
|
+
if (*p == '\0')
|
|
1016
|
+
error (FATAL, "Unterminated file name pattern for %s language",
|
|
1017
|
+
getLanguageName (language));
|
|
1018
|
+
else
|
|
1019
|
+
{
|
|
1020
|
+
*p++ = '\0';
|
|
1021
|
+
verbose (" (%s)", map);
|
|
1022
|
+
addLanguagePatternMap (language, map);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
else
|
|
1026
|
+
error (FATAL, "Badly formed language map for %s language",
|
|
1027
|
+
getLanguageName (language));
|
|
1028
|
+
return p;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
static char* processLanguageMap (char* map)
|
|
1032
|
+
{
|
|
1033
|
+
char* const separator = strchr (map, ':');
|
|
1034
|
+
char* result = NULL;
|
|
1035
|
+
if (separator != NULL)
|
|
1036
|
+
{
|
|
1037
|
+
langType language;
|
|
1038
|
+
char *list = separator + 1;
|
|
1039
|
+
boolean clear = FALSE;
|
|
1040
|
+
*separator = '\0';
|
|
1041
|
+
language = getNamedLanguage (map);
|
|
1042
|
+
if (language != LANG_IGNORE)
|
|
1043
|
+
{
|
|
1044
|
+
const char *const deflt = "default";
|
|
1045
|
+
char* p;
|
|
1046
|
+
if (*list == '+')
|
|
1047
|
+
++list;
|
|
1048
|
+
else
|
|
1049
|
+
clear = TRUE;
|
|
1050
|
+
for (p = list ; *p != ',' && *p != '\0' ; ++p) /*no-op*/ ;
|
|
1051
|
+
if ((size_t) (p - list) == strlen (deflt) &&
|
|
1052
|
+
strncasecmp (list, deflt, p - list) == 0)
|
|
1053
|
+
{
|
|
1054
|
+
verbose (" Restoring default %s language map: ", getLanguageName (language));
|
|
1055
|
+
installLanguageMapDefault (language);
|
|
1056
|
+
list = p;
|
|
1057
|
+
}
|
|
1058
|
+
else
|
|
1059
|
+
{
|
|
1060
|
+
if (clear)
|
|
1061
|
+
{
|
|
1062
|
+
verbose (" Setting %s language map:", getLanguageName (language));
|
|
1063
|
+
clearLanguageMap (language);
|
|
1064
|
+
}
|
|
1065
|
+
else
|
|
1066
|
+
verbose (" Adding to %s language map:", getLanguageName (language));
|
|
1067
|
+
while (list != NULL && *list != '\0' && *list != ',')
|
|
1068
|
+
list = addLanguageMap (language, list);
|
|
1069
|
+
verbose ("\n");
|
|
1070
|
+
}
|
|
1071
|
+
if (list != NULL && *list == ',')
|
|
1072
|
+
++list;
|
|
1073
|
+
result = list;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return result;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
static void processLanguageMapOption (
|
|
1080
|
+
const char *const option, const char *const parameter)
|
|
1081
|
+
{
|
|
1082
|
+
char *const maps = eStrdup (parameter);
|
|
1083
|
+
char *map = maps;
|
|
1084
|
+
|
|
1085
|
+
if (strcmp (parameter, "default") == 0)
|
|
1086
|
+
{
|
|
1087
|
+
verbose (" Restoring default language maps:\n");
|
|
1088
|
+
installLanguageMapDefaults ();
|
|
1089
|
+
}
|
|
1090
|
+
else while (map != NULL && *map != '\0')
|
|
1091
|
+
{
|
|
1092
|
+
char* const next = processLanguageMap (map);
|
|
1093
|
+
if (next == NULL)
|
|
1094
|
+
error (WARNING, "Unknown language \"%s\" in \"%s\" option", parameter, option);
|
|
1095
|
+
map = next;
|
|
1096
|
+
}
|
|
1097
|
+
eFree (maps);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
static void processLanguagesOption (
|
|
1101
|
+
const char *const option, const char *const parameter)
|
|
1102
|
+
{
|
|
1103
|
+
char *const langs = eStrdup (parameter);
|
|
1104
|
+
enum { Add, Remove, Replace } mode = Replace;
|
|
1105
|
+
boolean first = TRUE;
|
|
1106
|
+
char *lang = langs;
|
|
1107
|
+
const char* prefix = "";
|
|
1108
|
+
verbose (" Enabled languages: ");
|
|
1109
|
+
while (lang != NULL)
|
|
1110
|
+
{
|
|
1111
|
+
char *const end = strchr (lang, ',');
|
|
1112
|
+
if (lang [0] == '+')
|
|
1113
|
+
{
|
|
1114
|
+
++lang;
|
|
1115
|
+
mode = Add;
|
|
1116
|
+
prefix = "+ ";
|
|
1117
|
+
}
|
|
1118
|
+
else if (lang [0] == '-')
|
|
1119
|
+
{
|
|
1120
|
+
++lang;
|
|
1121
|
+
mode = Remove;
|
|
1122
|
+
prefix = "- ";
|
|
1123
|
+
}
|
|
1124
|
+
if (mode == Replace)
|
|
1125
|
+
enableLanguages (FALSE);
|
|
1126
|
+
if (end != NULL)
|
|
1127
|
+
*end = '\0';
|
|
1128
|
+
if (lang [0] != '\0')
|
|
1129
|
+
{
|
|
1130
|
+
if (strcmp (lang, "all") == 0)
|
|
1131
|
+
enableLanguages ((boolean) (mode != Remove));
|
|
1132
|
+
else
|
|
1133
|
+
{
|
|
1134
|
+
const langType language = getNamedLanguage (lang);
|
|
1135
|
+
if (language == LANG_IGNORE)
|
|
1136
|
+
error (WARNING, "Unknown language \"%s\" in \"%s\" option", lang, option);
|
|
1137
|
+
else
|
|
1138
|
+
enableLanguage (language, (boolean) (mode != Remove));
|
|
1139
|
+
}
|
|
1140
|
+
verbose ("%s%s%s", (first ? "" : ", "), prefix, lang);
|
|
1141
|
+
prefix = "";
|
|
1142
|
+
first = FALSE;
|
|
1143
|
+
if (mode == Replace)
|
|
1144
|
+
mode = Add;
|
|
1145
|
+
}
|
|
1146
|
+
lang = (end != NULL ? end + 1 : NULL);
|
|
1147
|
+
}
|
|
1148
|
+
verbose ("\n");
|
|
1149
|
+
eFree (langs);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
static void processLicenseOption (
|
|
1153
|
+
const char *const option __unused__,
|
|
1154
|
+
const char *const parameter __unused__)
|
|
1155
|
+
{
|
|
1156
|
+
printProgramIdentification ();
|
|
1157
|
+
puts ("");
|
|
1158
|
+
puts (License1);
|
|
1159
|
+
puts (License2);
|
|
1160
|
+
exit (0);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
static void processListKindsOption (
|
|
1164
|
+
const char *const option, const char *const parameter)
|
|
1165
|
+
{
|
|
1166
|
+
if (parameter [0] == '\0' || strcasecmp (parameter, "all") == 0)
|
|
1167
|
+
printLanguageKinds (LANG_AUTO);
|
|
1168
|
+
else
|
|
1169
|
+
{
|
|
1170
|
+
langType language = getNamedLanguage (parameter);
|
|
1171
|
+
if (language == LANG_IGNORE)
|
|
1172
|
+
error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
|
|
1173
|
+
else
|
|
1174
|
+
printLanguageKinds (language);
|
|
1175
|
+
}
|
|
1176
|
+
exit (0);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
static void processListMapsOption (
|
|
1180
|
+
const char *const __unused__ option,
|
|
1181
|
+
const char *const __unused__ parameter)
|
|
1182
|
+
{
|
|
1183
|
+
if (parameter [0] == '\0' || strcasecmp (parameter, "all") == 0)
|
|
1184
|
+
printLanguageMaps (LANG_AUTO);
|
|
1185
|
+
else
|
|
1186
|
+
{
|
|
1187
|
+
langType language = getNamedLanguage (parameter);
|
|
1188
|
+
if (language == LANG_IGNORE)
|
|
1189
|
+
error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
|
|
1190
|
+
else
|
|
1191
|
+
printLanguageMaps (language);
|
|
1192
|
+
}
|
|
1193
|
+
exit (0);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
static void processListLanguagesOption (
|
|
1197
|
+
const char *const option __unused__,
|
|
1198
|
+
const char *const parameter __unused__)
|
|
1199
|
+
{
|
|
1200
|
+
printLanguageList ();
|
|
1201
|
+
exit (0);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
static void processOptionFile (
|
|
1205
|
+
const char *const option, const char *const parameter)
|
|
1206
|
+
{
|
|
1207
|
+
if (parameter [0] == '\0')
|
|
1208
|
+
error (WARNING, "no option file supplied for \"%s\"", option);
|
|
1209
|
+
else if (! parseFileOptions (parameter))
|
|
1210
|
+
error (FATAL | PERROR, "cannot open option file \"%s\"", parameter);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
static void processSortOption (
|
|
1214
|
+
const char *const option, const char *const parameter)
|
|
1215
|
+
{
|
|
1216
|
+
if (isFalse (parameter))
|
|
1217
|
+
Option.sorted = SO_UNSORTED;
|
|
1218
|
+
else if (isTrue (parameter))
|
|
1219
|
+
Option.sorted = SO_SORTED;
|
|
1220
|
+
else if (strcasecmp (parameter, "f") == 0 ||
|
|
1221
|
+
strcasecmp (parameter, "fold") == 0 ||
|
|
1222
|
+
strcasecmp (parameter, "foldcase") == 0)
|
|
1223
|
+
Option.sorted = SO_FOLDSORTED;
|
|
1224
|
+
else
|
|
1225
|
+
error (FATAL, "Invalid value for \"%s\" option", option);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
static void installHeaderListDefaults (void)
|
|
1229
|
+
{
|
|
1230
|
+
Option.headerExt = stringListNewFromArgv (HeaderExtensions);
|
|
1231
|
+
if (Option.verbose)
|
|
1232
|
+
{
|
|
1233
|
+
printf (" Setting default header extensions: ");
|
|
1234
|
+
stringListPrint (Option.headerExt);
|
|
1235
|
+
putchar ('\n');
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
static void processHeaderListOption (const int option, const char *parameter)
|
|
1240
|
+
{
|
|
1241
|
+
/* Check to make sure that the user did not enter "ctags -h *.c"
|
|
1242
|
+
* by testing to see if the list is a filename that exists.
|
|
1243
|
+
*/
|
|
1244
|
+
if (doesFileExist (parameter))
|
|
1245
|
+
error (FATAL, "-%c: Invalid list", option);
|
|
1246
|
+
if (strcmp (parameter, "default") == 0)
|
|
1247
|
+
installHeaderListDefaults ();
|
|
1248
|
+
else
|
|
1249
|
+
{
|
|
1250
|
+
boolean clear = TRUE;
|
|
1251
|
+
|
|
1252
|
+
if (parameter [0] == '+')
|
|
1253
|
+
{
|
|
1254
|
+
++parameter;
|
|
1255
|
+
clear = FALSE;
|
|
1256
|
+
}
|
|
1257
|
+
if (Option.headerExt == NULL)
|
|
1258
|
+
Option.headerExt = stringListNew ();
|
|
1259
|
+
verbose (" Header Extensions:\n");
|
|
1260
|
+
addExtensionList (Option.headerExt, parameter, clear);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/*
|
|
1265
|
+
* Token ignore processing
|
|
1266
|
+
*/
|
|
1267
|
+
|
|
1268
|
+
/* Determines whether or not "name" should be ignored, per the ignore list.
|
|
1269
|
+
*/
|
|
1270
|
+
extern boolean isIgnoreToken (
|
|
1271
|
+
const char *const name, boolean *const pIgnoreParens,
|
|
1272
|
+
const char **const replacement)
|
|
1273
|
+
{
|
|
1274
|
+
boolean result = FALSE;
|
|
1275
|
+
|
|
1276
|
+
if (Option.ignore != NULL)
|
|
1277
|
+
{
|
|
1278
|
+
const size_t nameLen = strlen (name);
|
|
1279
|
+
unsigned int i;
|
|
1280
|
+
|
|
1281
|
+
if (pIgnoreParens != NULL)
|
|
1282
|
+
*pIgnoreParens = FALSE;
|
|
1283
|
+
|
|
1284
|
+
for (i = 0 ; i < stringListCount (Option.ignore) ; ++i)
|
|
1285
|
+
{
|
|
1286
|
+
vString *token = stringListItem (Option.ignore, i);
|
|
1287
|
+
|
|
1288
|
+
if (strncmp (vStringValue (token), name, nameLen) == 0)
|
|
1289
|
+
{
|
|
1290
|
+
const size_t tokenLen = vStringLength (token);
|
|
1291
|
+
|
|
1292
|
+
if (nameLen == tokenLen)
|
|
1293
|
+
{
|
|
1294
|
+
result = TRUE;
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
else if (tokenLen == nameLen + 1 &&
|
|
1298
|
+
vStringChar (token, tokenLen - 1) == '+')
|
|
1299
|
+
{
|
|
1300
|
+
result = TRUE;
|
|
1301
|
+
if (pIgnoreParens != NULL)
|
|
1302
|
+
*pIgnoreParens = TRUE;
|
|
1303
|
+
break;
|
|
1304
|
+
}
|
|
1305
|
+
else if (vStringChar (token, nameLen) == '=')
|
|
1306
|
+
{
|
|
1307
|
+
if (replacement != NULL)
|
|
1308
|
+
*replacement = vStringValue (token) + nameLen + 1;
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
return result;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
static void saveIgnoreToken (vString *const ignoreToken)
|
|
1318
|
+
{
|
|
1319
|
+
if (Option.ignore == NULL)
|
|
1320
|
+
Option.ignore = stringListNew ();
|
|
1321
|
+
stringListAdd (Option.ignore, ignoreToken);
|
|
1322
|
+
verbose (" ignore token: %s\n", vStringValue (ignoreToken));
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
static void readIgnoreList (const char *const list)
|
|
1326
|
+
{
|
|
1327
|
+
char* newList = stringCopy (list);
|
|
1328
|
+
const char *token = strtok (newList, IGNORE_SEPARATORS);
|
|
1329
|
+
|
|
1330
|
+
while (token != NULL)
|
|
1331
|
+
{
|
|
1332
|
+
vString *const entry = vStringNewInit (token);
|
|
1333
|
+
|
|
1334
|
+
saveIgnoreToken (entry);
|
|
1335
|
+
token = strtok (NULL, IGNORE_SEPARATORS);
|
|
1336
|
+
}
|
|
1337
|
+
eFree (newList);
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
static void addIgnoreListFromFile (const char *const fileName)
|
|
1341
|
+
{
|
|
1342
|
+
stringList* tokens = stringListNewFromFile (fileName);
|
|
1343
|
+
if (tokens == NULL)
|
|
1344
|
+
error (FATAL | PERROR, "cannot open \"%s\"", fileName);
|
|
1345
|
+
if (Option.ignore == NULL)
|
|
1346
|
+
Option.ignore = tokens;
|
|
1347
|
+
else
|
|
1348
|
+
stringListCombine (Option.ignore, tokens);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
static void processIgnoreOption (const char *const list)
|
|
1352
|
+
{
|
|
1353
|
+
if (strchr ("@./\\", list [0]) != NULL)
|
|
1354
|
+
{
|
|
1355
|
+
const char* fileName = (*list == '@') ? list + 1 : list;
|
|
1356
|
+
addIgnoreListFromFile (fileName);
|
|
1357
|
+
}
|
|
1358
|
+
#if defined (MSDOS) || defined (WIN32) || defined (OS2)
|
|
1359
|
+
else if (isalpha (list [0]) && list [1] == ':')
|
|
1360
|
+
addIgnoreListFromFile (list);
|
|
1361
|
+
#endif
|
|
1362
|
+
else if (strcmp (list, "-") == 0)
|
|
1363
|
+
{
|
|
1364
|
+
freeList (&Option.ignore);
|
|
1365
|
+
verbose (" clearing list\n");
|
|
1366
|
+
}
|
|
1367
|
+
else
|
|
1368
|
+
readIgnoreList (list);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
static void processVersionOption (
|
|
1372
|
+
const char *const option __unused__,
|
|
1373
|
+
const char *const parameter __unused__)
|
|
1374
|
+
{
|
|
1375
|
+
printProgramIdentification ();
|
|
1376
|
+
exit (0);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/*
|
|
1380
|
+
* Option tables
|
|
1381
|
+
*/
|
|
1382
|
+
|
|
1383
|
+
static parametricOption ParametricOptions [] = {
|
|
1384
|
+
{ "etags-include", processEtagsInclude, FALSE },
|
|
1385
|
+
{ "exclude", processExcludeOption, FALSE },
|
|
1386
|
+
{ "excmd", processExcmdOption, FALSE },
|
|
1387
|
+
{ "extra", processExtraTagsOption, FALSE },
|
|
1388
|
+
{ "fields", processFieldsOption, FALSE },
|
|
1389
|
+
{ "filter-terminator", processFilterTerminatorOption, TRUE },
|
|
1390
|
+
{ "format", processFormatOption, TRUE },
|
|
1391
|
+
{ "help", processHelpOption, TRUE },
|
|
1392
|
+
{ "lang", processLanguageForceOption, FALSE },
|
|
1393
|
+
{ "language", processLanguageForceOption, FALSE },
|
|
1394
|
+
{ "language-force", processLanguageForceOption, FALSE },
|
|
1395
|
+
{ "languages", processLanguagesOption, FALSE },
|
|
1396
|
+
{ "langdef", processLanguageDefineOption, FALSE },
|
|
1397
|
+
{ "langmap", processLanguageMapOption, FALSE },
|
|
1398
|
+
{ "license", processLicenseOption, TRUE },
|
|
1399
|
+
{ "list-kinds", processListKindsOption, TRUE },
|
|
1400
|
+
{ "list-maps", processListMapsOption, TRUE },
|
|
1401
|
+
{ "list-languages", processListLanguagesOption, TRUE },
|
|
1402
|
+
{ "options", processOptionFile, FALSE },
|
|
1403
|
+
{ "sort", processSortOption, TRUE },
|
|
1404
|
+
{ "version", processVersionOption, TRUE },
|
|
1405
|
+
{ "stdin-filename", processStdinFileName, FALSE }
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
static booleanOption BooleanOptions [] = {
|
|
1409
|
+
{ "append", &Option.append, TRUE },
|
|
1410
|
+
{ "file-scope", &Option.include.fileScope, FALSE },
|
|
1411
|
+
{ "file-tags", &Option.include.fileNames, FALSE },
|
|
1412
|
+
{ "filter", &Option.filter, TRUE },
|
|
1413
|
+
{ "if0", &Option.if0, FALSE },
|
|
1414
|
+
{ "kind-long", &Option.kindLong, TRUE },
|
|
1415
|
+
{ "line-directives",&Option.lineDirectives, FALSE },
|
|
1416
|
+
{ "links", &Option.followLinks, FALSE },
|
|
1417
|
+
#ifdef RECURSE_SUPPORTED
|
|
1418
|
+
{ "recurse", &Option.recurse, FALSE },
|
|
1419
|
+
#endif
|
|
1420
|
+
{ "tag-relative", &Option.tagRelative, TRUE },
|
|
1421
|
+
{ "totals", &Option.printTotals, TRUE },
|
|
1422
|
+
{ "verbose", &Option.verbose, FALSE },
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
/*
|
|
1426
|
+
* Generic option parsing
|
|
1427
|
+
*/
|
|
1428
|
+
|
|
1429
|
+
static void checkOptionOrder (const char* const option)
|
|
1430
|
+
{
|
|
1431
|
+
if (NonOptionEncountered)
|
|
1432
|
+
error (FATAL, "-%s option may not follow a file name", option);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
static boolean processParametricOption (
|
|
1436
|
+
const char *const option, const char *const parameter)
|
|
1437
|
+
{
|
|
1438
|
+
const int count = sizeof (ParametricOptions) / sizeof (parametricOption);
|
|
1439
|
+
boolean found = FALSE;
|
|
1440
|
+
int i;
|
|
1441
|
+
|
|
1442
|
+
for (i = 0 ; i < count && ! found ; ++i)
|
|
1443
|
+
{
|
|
1444
|
+
parametricOption* const entry = &ParametricOptions [i];
|
|
1445
|
+
if (strcmp (option, entry->name) == 0)
|
|
1446
|
+
{
|
|
1447
|
+
found = TRUE;
|
|
1448
|
+
if (entry->initOnly)
|
|
1449
|
+
checkOptionOrder (option);
|
|
1450
|
+
(entry->handler) (option, parameter);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
return found;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
static boolean getBooleanOption (
|
|
1457
|
+
const char *const option, const char *const parameter)
|
|
1458
|
+
{
|
|
1459
|
+
boolean selection = TRUE;
|
|
1460
|
+
|
|
1461
|
+
if (parameter [0] == '\0')
|
|
1462
|
+
selection = TRUE;
|
|
1463
|
+
else if (isFalse (parameter))
|
|
1464
|
+
selection = FALSE;
|
|
1465
|
+
else if (isTrue (parameter))
|
|
1466
|
+
selection = TRUE;
|
|
1467
|
+
else
|
|
1468
|
+
error (FATAL, "Invalid value for \"%s\" option", option);
|
|
1469
|
+
|
|
1470
|
+
return selection;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
static boolean processBooleanOption (
|
|
1474
|
+
const char *const option, const char *const parameter)
|
|
1475
|
+
{
|
|
1476
|
+
const int count = sizeof (BooleanOptions) / sizeof (booleanOption);
|
|
1477
|
+
boolean found = FALSE;
|
|
1478
|
+
int i;
|
|
1479
|
+
|
|
1480
|
+
for (i = 0 ; i < count && ! found ; ++i)
|
|
1481
|
+
{
|
|
1482
|
+
booleanOption* const entry = &BooleanOptions [i];
|
|
1483
|
+
if (strcmp (option, entry->name) == 0)
|
|
1484
|
+
{
|
|
1485
|
+
found = TRUE;
|
|
1486
|
+
if (entry->initOnly)
|
|
1487
|
+
checkOptionOrder (option);
|
|
1488
|
+
*entry->pValue = getBooleanOption (option, parameter);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return found;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
static void processLongOption (
|
|
1495
|
+
const char *const option, const char *const parameter)
|
|
1496
|
+
{
|
|
1497
|
+
Assert (parameter != NULL);
|
|
1498
|
+
if (parameter == NULL && parameter [0] == '\0')
|
|
1499
|
+
verbose (" Option: --%s\n", option);
|
|
1500
|
+
else
|
|
1501
|
+
verbose (" Option: --%s=%s\n", option, parameter);
|
|
1502
|
+
|
|
1503
|
+
if (processBooleanOption (option, parameter))
|
|
1504
|
+
;
|
|
1505
|
+
else if (processParametricOption (option, parameter))
|
|
1506
|
+
;
|
|
1507
|
+
else if (processKindOption (option, parameter))
|
|
1508
|
+
;
|
|
1509
|
+
else if (processRegexOption (option, parameter))
|
|
1510
|
+
;
|
|
1511
|
+
#ifndef RECURSE_SUPPORTED
|
|
1512
|
+
else if (strcmp (option, "recurse") == 0)
|
|
1513
|
+
error (WARNING, "%s option not supported on this host", option);
|
|
1514
|
+
#endif
|
|
1515
|
+
else
|
|
1516
|
+
error (FATAL, "Unknown option: --%s", option);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
static void processShortOption (
|
|
1520
|
+
const char *const option, const char *const parameter)
|
|
1521
|
+
{
|
|
1522
|
+
if (parameter == NULL || parameter [0] == '\0')
|
|
1523
|
+
verbose (" Option: -%s\n", option);
|
|
1524
|
+
else
|
|
1525
|
+
verbose (" Option: -%s %s\n", option, parameter);
|
|
1526
|
+
|
|
1527
|
+
if (isCompoundOption (*option) && (parameter == NULL || parameter [0] == '\0'))
|
|
1528
|
+
error (FATAL, "Missing parameter for \"%s\" option", option);
|
|
1529
|
+
else switch (*option)
|
|
1530
|
+
{
|
|
1531
|
+
case '?':
|
|
1532
|
+
processHelpOption ("?", NULL);
|
|
1533
|
+
exit (0);
|
|
1534
|
+
break;
|
|
1535
|
+
case 'a':
|
|
1536
|
+
checkOptionOrder (option);
|
|
1537
|
+
Option.append = TRUE;
|
|
1538
|
+
break;
|
|
1539
|
+
#ifdef DEBUG
|
|
1540
|
+
case 'b':
|
|
1541
|
+
if (atol (parameter) < 0)
|
|
1542
|
+
error (FATAL, "-%s: Invalid line number", option);
|
|
1543
|
+
Option.breakLine = atol (parameter);
|
|
1544
|
+
break;
|
|
1545
|
+
case 'D':
|
|
1546
|
+
Option.debugLevel = strtol (parameter, NULL, 0);
|
|
1547
|
+
if (debug (DEBUG_STATUS))
|
|
1548
|
+
Option.verbose = TRUE;
|
|
1549
|
+
break;
|
|
1550
|
+
#endif
|
|
1551
|
+
case 'B':
|
|
1552
|
+
Option.backward = TRUE;
|
|
1553
|
+
break;
|
|
1554
|
+
case 'e':
|
|
1555
|
+
checkOptionOrder (option);
|
|
1556
|
+
setEtagsMode ();
|
|
1557
|
+
break;
|
|
1558
|
+
case 'f':
|
|
1559
|
+
case 'o':
|
|
1560
|
+
checkOptionOrder (option);
|
|
1561
|
+
if (Option.tagFileName != NULL)
|
|
1562
|
+
{
|
|
1563
|
+
error (WARNING,
|
|
1564
|
+
"-%s option specified more than once, last value used",
|
|
1565
|
+
option);
|
|
1566
|
+
freeString (&Option.tagFileName);
|
|
1567
|
+
}
|
|
1568
|
+
else if (parameter [0] == '-' && parameter [1] != '\0')
|
|
1569
|
+
error (FATAL, "output file name may not begin with a '-'");
|
|
1570
|
+
Option.tagFileName = stringCopy (parameter);
|
|
1571
|
+
break;
|
|
1572
|
+
case 'F':
|
|
1573
|
+
Option.backward = FALSE;
|
|
1574
|
+
break;
|
|
1575
|
+
case 'h':
|
|
1576
|
+
processHeaderListOption (*option, parameter);
|
|
1577
|
+
break;
|
|
1578
|
+
case 'I':
|
|
1579
|
+
processIgnoreOption (parameter);
|
|
1580
|
+
break;
|
|
1581
|
+
case 'L':
|
|
1582
|
+
if (Option.fileList != NULL)
|
|
1583
|
+
{
|
|
1584
|
+
error (WARNING,
|
|
1585
|
+
"-%s option specified more than once, last value used",
|
|
1586
|
+
option);
|
|
1587
|
+
freeString (&Option.fileList);
|
|
1588
|
+
}
|
|
1589
|
+
Option.fileList = stringCopy (parameter);
|
|
1590
|
+
break;
|
|
1591
|
+
case 'n':
|
|
1592
|
+
Option.locate = EX_LINENUM;
|
|
1593
|
+
break;
|
|
1594
|
+
case 'N':
|
|
1595
|
+
Option.locate = EX_PATTERN;
|
|
1596
|
+
break;
|
|
1597
|
+
case 'R':
|
|
1598
|
+
#ifdef RECURSE_SUPPORTED
|
|
1599
|
+
Option.recurse = TRUE;
|
|
1600
|
+
#else
|
|
1601
|
+
error (WARNING, "-%s option not supported on this host", option);
|
|
1602
|
+
#endif
|
|
1603
|
+
break;
|
|
1604
|
+
case 'u':
|
|
1605
|
+
checkOptionOrder (option);
|
|
1606
|
+
Option.sorted = SO_UNSORTED;
|
|
1607
|
+
break;
|
|
1608
|
+
case 'V':
|
|
1609
|
+
Option.verbose = TRUE;
|
|
1610
|
+
break;
|
|
1611
|
+
case 'w':
|
|
1612
|
+
/* silently ignored */
|
|
1613
|
+
break;
|
|
1614
|
+
case 'x':
|
|
1615
|
+
checkOptionOrder (option);
|
|
1616
|
+
Option.xref = TRUE;
|
|
1617
|
+
break;
|
|
1618
|
+
default:
|
|
1619
|
+
error (FATAL, "Unknown option: -%s", option);
|
|
1620
|
+
break;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
extern void parseOption (cookedArgs* const args)
|
|
1625
|
+
{
|
|
1626
|
+
Assert (! cArgOff (args));
|
|
1627
|
+
if (args->isOption)
|
|
1628
|
+
{
|
|
1629
|
+
if (args->longOption)
|
|
1630
|
+
processLongOption (args->item, args->parameter);
|
|
1631
|
+
else
|
|
1632
|
+
{
|
|
1633
|
+
const char *parameter = args->parameter;
|
|
1634
|
+
while (*parameter == ' ')
|
|
1635
|
+
++parameter;
|
|
1636
|
+
processShortOption (args->item, parameter);
|
|
1637
|
+
}
|
|
1638
|
+
cArgForth (args);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
extern void parseOptions (cookedArgs* const args)
|
|
1643
|
+
{
|
|
1644
|
+
NonOptionEncountered = FALSE;
|
|
1645
|
+
while (! cArgOff (args) && cArgIsOption (args))
|
|
1646
|
+
parseOption (args);
|
|
1647
|
+
if (! cArgOff (args) && ! cArgIsOption (args))
|
|
1648
|
+
NonOptionEncountered = TRUE;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
static const char *CheckFile;
|
|
1652
|
+
static boolean checkSameFile (const char *const fileName)
|
|
1653
|
+
{
|
|
1654
|
+
return isSameFile (CheckFile, fileName);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
static boolean parseFileOptions (const char* const fileName)
|
|
1658
|
+
{
|
|
1659
|
+
boolean fileFound = FALSE;
|
|
1660
|
+
const char* const format = "Considering option file %s: %s\n";
|
|
1661
|
+
CheckFile = fileName;
|
|
1662
|
+
if (stringListHasTest (OptionFiles, checkSameFile))
|
|
1663
|
+
verbose (format, fileName, "already considered");
|
|
1664
|
+
else
|
|
1665
|
+
{
|
|
1666
|
+
FILE* const fp = fopen (fileName, "r");
|
|
1667
|
+
if (fp == NULL)
|
|
1668
|
+
verbose (format, fileName, "not found");
|
|
1669
|
+
else
|
|
1670
|
+
{
|
|
1671
|
+
cookedArgs* const args = cArgNewFromLineFile (fp);
|
|
1672
|
+
vString* file = vStringNewInit (fileName);
|
|
1673
|
+
stringListAdd (OptionFiles, file);
|
|
1674
|
+
verbose (format, fileName, "reading...");
|
|
1675
|
+
parseOptions (args);
|
|
1676
|
+
if (NonOptionEncountered)
|
|
1677
|
+
error (WARNING, "Ignoring non-option in %s\n", fileName);
|
|
1678
|
+
cArgDelete (args);
|
|
1679
|
+
fclose (fp);
|
|
1680
|
+
fileFound = TRUE;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
return fileFound;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
/* Actions to be taken before reading any other options */
|
|
1687
|
+
extern void previewFirstOption (cookedArgs* const args)
|
|
1688
|
+
{
|
|
1689
|
+
while (cArgIsOption (args))
|
|
1690
|
+
{
|
|
1691
|
+
if (strcmp (args->item, "V") == 0 || strcmp (args->item, "verbose") == 0)
|
|
1692
|
+
parseOption (args);
|
|
1693
|
+
else if (strcmp (args->item, "options") == 0 &&
|
|
1694
|
+
strcmp (args->parameter, "NONE") == 0)
|
|
1695
|
+
{
|
|
1696
|
+
fprintf (stderr, "No options will be read from files or environment\n");
|
|
1697
|
+
SkipConfiguration = TRUE;
|
|
1698
|
+
cArgForth (args);
|
|
1699
|
+
}
|
|
1700
|
+
else
|
|
1701
|
+
break;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
static void parseConfigurationFileOptionsInDirectoryWithLeafname (const char* directory, const char* leafname)
|
|
1706
|
+
{
|
|
1707
|
+
vString* const pathname = combinePathAndFile (directory, leafname);
|
|
1708
|
+
parseFileOptions (vStringValue (pathname));
|
|
1709
|
+
vStringDelete (pathname);
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
static void parseConfigurationFileOptionsInDirectory (const char* directory)
|
|
1713
|
+
{
|
|
1714
|
+
parseConfigurationFileOptionsInDirectoryWithLeafname (directory, ".ctags");
|
|
1715
|
+
#ifdef MSDOS_STYLE_PATH
|
|
1716
|
+
parseConfigurationFileOptionsInDirectoryWithLeafname (directory, "ctags.cnf");
|
|
1717
|
+
#endif
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
static void parseConfigurationFileOptions (void)
|
|
1721
|
+
{
|
|
1722
|
+
/* We parse .ctags on all systems, and additionally ctags.cnf on DOS. */
|
|
1723
|
+
const char* const home = getenv ("HOME");
|
|
1724
|
+
#ifdef CUSTOM_CONFIGURATION_FILE
|
|
1725
|
+
parseFileOptions (CUSTOM_CONFIGURATION_FILE);
|
|
1726
|
+
#endif
|
|
1727
|
+
#ifdef MSDOS_STYLE_PATH
|
|
1728
|
+
parseFileOptions ("/ctags.cnf");
|
|
1729
|
+
#endif
|
|
1730
|
+
parseFileOptions ("/etc/ctags.conf");
|
|
1731
|
+
parseFileOptions ("/usr/local/etc/ctags.conf");
|
|
1732
|
+
if (home != NULL)
|
|
1733
|
+
{
|
|
1734
|
+
parseConfigurationFileOptionsInDirectory (home);
|
|
1735
|
+
}
|
|
1736
|
+
else
|
|
1737
|
+
{
|
|
1738
|
+
#ifdef MSDOS_STYLE_PATH
|
|
1739
|
+
/*
|
|
1740
|
+
* Windows users don't usually set HOME.
|
|
1741
|
+
* The OS sets HOMEDRIVE and HOMEPATH for them.
|
|
1742
|
+
*/
|
|
1743
|
+
const char* homeDrive = getenv ("HOMEDRIVE");
|
|
1744
|
+
const char* homePath = getenv ("HOMEPATH");
|
|
1745
|
+
if (homeDrive != NULL && homePath != NULL)
|
|
1746
|
+
{
|
|
1747
|
+
vString* const windowsHome = vStringNew ();
|
|
1748
|
+
vStringCatS (windowsHome, homeDrive);
|
|
1749
|
+
vStringCatS (windowsHome, homePath);
|
|
1750
|
+
parseConfigurationFileOptionsInDirectory (vStringValue (windowsHome));
|
|
1751
|
+
vStringDelete (windowsHome);
|
|
1752
|
+
}
|
|
1753
|
+
#endif
|
|
1754
|
+
}
|
|
1755
|
+
parseConfigurationFileOptionsInDirectory (".");
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
static void parseEnvironmentOptions (void)
|
|
1759
|
+
{
|
|
1760
|
+
const char *envOptions = NULL;
|
|
1761
|
+
const char* var = NULL;
|
|
1762
|
+
|
|
1763
|
+
if (Option.etags)
|
|
1764
|
+
{
|
|
1765
|
+
var = ETAGS_ENVIRONMENT;
|
|
1766
|
+
envOptions = getenv (var);
|
|
1767
|
+
}
|
|
1768
|
+
if (envOptions == NULL)
|
|
1769
|
+
{
|
|
1770
|
+
var = CTAGS_ENVIRONMENT;
|
|
1771
|
+
envOptions = getenv (var);
|
|
1772
|
+
}
|
|
1773
|
+
if (envOptions != NULL && envOptions [0] != '\0')
|
|
1774
|
+
{
|
|
1775
|
+
cookedArgs* const args = cArgNewFromString (envOptions);
|
|
1776
|
+
verbose ("Reading options from $CTAGS\n");
|
|
1777
|
+
parseOptions (args);
|
|
1778
|
+
cArgDelete (args);
|
|
1779
|
+
if (NonOptionEncountered)
|
|
1780
|
+
error (WARNING, "Ignoring non-option in %s variable", var);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
extern void readOptionConfiguration (void)
|
|
1785
|
+
{
|
|
1786
|
+
if (! SkipConfiguration)
|
|
1787
|
+
{
|
|
1788
|
+
parseConfigurationFileOptions ();
|
|
1789
|
+
parseEnvironmentOptions ();
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/*
|
|
1794
|
+
* Option initialization
|
|
1795
|
+
*/
|
|
1796
|
+
|
|
1797
|
+
extern void initOptions (void)
|
|
1798
|
+
{
|
|
1799
|
+
OptionFiles = stringListNew ();
|
|
1800
|
+
verbose ("Setting option defaults\n");
|
|
1801
|
+
installHeaderListDefaults ();
|
|
1802
|
+
verbose (" Installing default language mappings:\n");
|
|
1803
|
+
installLanguageMapDefaults ();
|
|
1804
|
+
|
|
1805
|
+
/* always excluded by default */
|
|
1806
|
+
verbose (" Installing default exclude patterns:\n");
|
|
1807
|
+
processExcludeOption (NULL, "{arch}");
|
|
1808
|
+
processExcludeOption (NULL, ".arch-ids");
|
|
1809
|
+
processExcludeOption (NULL, ".arch-inventory");
|
|
1810
|
+
processExcludeOption (NULL, "autom4te.cache");
|
|
1811
|
+
processExcludeOption (NULL, "BitKeeper");
|
|
1812
|
+
processExcludeOption (NULL, ".bzr");
|
|
1813
|
+
processExcludeOption (NULL, ".bzrignore");
|
|
1814
|
+
processExcludeOption (NULL, "CVS");
|
|
1815
|
+
processExcludeOption (NULL, ".cvsignore");
|
|
1816
|
+
processExcludeOption (NULL, "_darcs");
|
|
1817
|
+
processExcludeOption (NULL, ".deps");
|
|
1818
|
+
processExcludeOption (NULL, "EIFGEN");
|
|
1819
|
+
processExcludeOption (NULL, ".git");
|
|
1820
|
+
processExcludeOption (NULL, ".hg");
|
|
1821
|
+
processExcludeOption (NULL, "PENDING");
|
|
1822
|
+
processExcludeOption (NULL, "RCS");
|
|
1823
|
+
processExcludeOption (NULL, "RESYNC");
|
|
1824
|
+
processExcludeOption (NULL, "SCCS");
|
|
1825
|
+
processExcludeOption (NULL, ".svn");
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
extern void freeOptionResources (void)
|
|
1829
|
+
{
|
|
1830
|
+
freeString (&Option.tagFileName);
|
|
1831
|
+
freeString (&Option.fileList);
|
|
1832
|
+
freeString (&Option.filterTerminator);
|
|
1833
|
+
freeString (&Option.stdinFileName);
|
|
1834
|
+
|
|
1835
|
+
freeList (&Excluded);
|
|
1836
|
+
freeList (&Option.ignore);
|
|
1837
|
+
freeList (&Option.headerExt);
|
|
1838
|
+
freeList (&Option.etagsInclude);
|
|
1839
|
+
freeList (&OptionFiles);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
/* vi:set tabstop=4 shiftwidth=4: */
|