ctags.rb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. data/Gemfile +2 -0
  2. data/Rakefile +23 -0
  3. data/ctags.rb.gemspec +23 -0
  4. data/ext/.gitignore +3 -0
  5. data/ext/extconf.rb +15 -0
  6. data/ext/vendor/exuberant-ctags/.gitignore +6 -0
  7. data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
  8. data/ext/vendor/exuberant-ctags/COPYING +340 -0
  9. data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
  10. data/ext/vendor/exuberant-ctags/FAQ +371 -0
  11. data/ext/vendor/exuberant-ctags/INSTALL +215 -0
  12. data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
  13. data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
  14. data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
  15. data/ext/vendor/exuberant-ctags/NEWS +871 -0
  16. data/ext/vendor/exuberant-ctags/README +73 -0
  17. data/ext/vendor/exuberant-ctags/ant.c +42 -0
  18. data/ext/vendor/exuberant-ctags/argproc.c +505 -0
  19. data/ext/vendor/exuberant-ctags/args.c +274 -0
  20. data/ext/vendor/exuberant-ctags/args.h +63 -0
  21. data/ext/vendor/exuberant-ctags/asm.c +387 -0
  22. data/ext/vendor/exuberant-ctags/asp.c +328 -0
  23. data/ext/vendor/exuberant-ctags/awk.c +81 -0
  24. data/ext/vendor/exuberant-ctags/basic.c +203 -0
  25. data/ext/vendor/exuberant-ctags/beta.c +321 -0
  26. data/ext/vendor/exuberant-ctags/c.c +2932 -0
  27. data/ext/vendor/exuberant-ctags/cobol.c +50 -0
  28. data/ext/vendor/exuberant-ctags/config.h.in +277 -0
  29. data/ext/vendor/exuberant-ctags/configure +7704 -0
  30. data/ext/vendor/exuberant-ctags/configure.ac +532 -0
  31. data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
  32. data/ext/vendor/exuberant-ctags/ctags.h +28 -0
  33. data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
  34. data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
  35. data/ext/vendor/exuberant-ctags/debug.c +113 -0
  36. data/ext/vendor/exuberant-ctags/debug.h +70 -0
  37. data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
  38. data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
  39. data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
  40. data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
  41. data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
  42. data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
  43. data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
  44. data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
  45. data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
  46. data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
  47. data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
  48. data/ext/vendor/exuberant-ctags/entry.c +847 -0
  49. data/ext/vendor/exuberant-ctags/entry.h +103 -0
  50. data/ext/vendor/exuberant-ctags/erlang.c +189 -0
  51. data/ext/vendor/exuberant-ctags/flex.c +2243 -0
  52. data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
  53. data/ext/vendor/exuberant-ctags/general.h +127 -0
  54. data/ext/vendor/exuberant-ctags/get.c +669 -0
  55. data/ext/vendor/exuberant-ctags/get.h +50 -0
  56. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
  57. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
  58. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
  59. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
  60. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
  61. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
  62. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
  63. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
  64. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
  65. data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
  66. data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
  67. data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
  68. data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
  69. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
  70. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
  71. data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
  72. data/ext/vendor/exuberant-ctags/html.c +49 -0
  73. data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
  74. data/ext/vendor/exuberant-ctags/keyword.c +258 -0
  75. data/ext/vendor/exuberant-ctags/keyword.h +34 -0
  76. data/ext/vendor/exuberant-ctags/lisp.c +139 -0
  77. data/ext/vendor/exuberant-ctags/lregex.c +704 -0
  78. data/ext/vendor/exuberant-ctags/lua.c +133 -0
  79. data/ext/vendor/exuberant-ctags/mac.c +273 -0
  80. data/ext/vendor/exuberant-ctags/magic.diff +21 -0
  81. data/ext/vendor/exuberant-ctags/main.c +584 -0
  82. data/ext/vendor/exuberant-ctags/main.h +32 -0
  83. data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
  84. data/ext/vendor/exuberant-ctags/make.c +217 -0
  85. data/ext/vendor/exuberant-ctags/matlab.c +44 -0
  86. data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
  87. data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
  88. data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
  89. data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
  90. data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
  91. data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
  92. data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
  93. data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
  94. data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
  95. data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
  96. data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
  97. data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
  98. data/ext/vendor/exuberant-ctags/options.c +1842 -0
  99. data/ext/vendor/exuberant-ctags/options.h +155 -0
  100. data/ext/vendor/exuberant-ctags/parse.c +677 -0
  101. data/ext/vendor/exuberant-ctags/parse.h +129 -0
  102. data/ext/vendor/exuberant-ctags/parsers.h +63 -0
  103. data/ext/vendor/exuberant-ctags/pascal.c +267 -0
  104. data/ext/vendor/exuberant-ctags/perl.c +382 -0
  105. data/ext/vendor/exuberant-ctags/php.c +237 -0
  106. data/ext/vendor/exuberant-ctags/python.c +771 -0
  107. data/ext/vendor/exuberant-ctags/qdos.c +106 -0
  108. data/ext/vendor/exuberant-ctags/read.c +569 -0
  109. data/ext/vendor/exuberant-ctags/read.h +116 -0
  110. data/ext/vendor/exuberant-ctags/readtags.c +959 -0
  111. data/ext/vendor/exuberant-ctags/readtags.h +252 -0
  112. data/ext/vendor/exuberant-ctags/rexx.c +39 -0
  113. data/ext/vendor/exuberant-ctags/routines.c +891 -0
  114. data/ext/vendor/exuberant-ctags/routines.h +134 -0
  115. data/ext/vendor/exuberant-ctags/ruby.c +408 -0
  116. data/ext/vendor/exuberant-ctags/scheme.c +111 -0
  117. data/ext/vendor/exuberant-ctags/sh.c +115 -0
  118. data/ext/vendor/exuberant-ctags/slang.c +41 -0
  119. data/ext/vendor/exuberant-ctags/sml.c +212 -0
  120. data/ext/vendor/exuberant-ctags/sort.c +230 -0
  121. data/ext/vendor/exuberant-ctags/sort.h +32 -0
  122. data/ext/vendor/exuberant-ctags/source.mak +122 -0
  123. data/ext/vendor/exuberant-ctags/sql.c +2112 -0
  124. data/ext/vendor/exuberant-ctags/strlist.c +281 -0
  125. data/ext/vendor/exuberant-ctags/strlist.h +54 -0
  126. data/ext/vendor/exuberant-ctags/tcl.c +116 -0
  127. data/ext/vendor/exuberant-ctags/tex.c +524 -0
  128. data/ext/vendor/exuberant-ctags/verilog.c +340 -0
  129. data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
  130. data/ext/vendor/exuberant-ctags/vim.c +636 -0
  131. data/ext/vendor/exuberant-ctags/vstring.c +232 -0
  132. data/ext/vendor/exuberant-ctags/vstring.h +85 -0
  133. data/ext/vendor/exuberant-ctags/yacc.c +40 -0
  134. data/lib/ctags/exuberant.rb +45 -0
  135. data/lib/ctags/version.rb +3 -0
  136. data/lib/ctags.rb +6 -0
  137. data/test/test_ctags.rb +24 -0
  138. 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: */