xref: /Universal-ctags/main/options.c (revision c62e6612b9bde9529f58f8a1710a383ab2a224e4)
1d4c6f1e6SMasatake YAMATO /*
2d4c6f1e6SMasatake YAMATO *   Copyright (c) 1996-2003, Darren Hiebert
3d4c6f1e6SMasatake YAMATO *
4d4c6f1e6SMasatake YAMATO *   This source code is released for free distribution under the terms of the
50ce38835Sviccuad *   GNU General Public License version 2 or (at your option) any later version.
6d4c6f1e6SMasatake YAMATO *
7d4c6f1e6SMasatake YAMATO *   This module contains functions to process command line options.
8d4c6f1e6SMasatake YAMATO */
9d4c6f1e6SMasatake YAMATO 
10d4c6f1e6SMasatake YAMATO /*
11d4c6f1e6SMasatake YAMATO *   INCLUDE FILES
12d4c6f1e6SMasatake YAMATO */
13d4c6f1e6SMasatake YAMATO #include "general.h"  /* must always come first */
14d4c6f1e6SMasatake YAMATO 
1521996d92SMasatake YAMATO #define OPTION_WRITE
1621996d92SMasatake YAMATO #include "options_p.h"
1721996d92SMasatake YAMATO 
1879d17f85SJiří Techet #ifndef _GNU_SOURCE
19d4c6f1e6SMasatake YAMATO # define _GNU_SOURCE   /* for asprintf */
2079d17f85SJiří Techet #endif
21d4c6f1e6SMasatake YAMATO #include <stdlib.h>
22d4c6f1e6SMasatake YAMATO #include <string.h>
23d4c6f1e6SMasatake YAMATO #include <stdio.h>
24d4c6f1e6SMasatake YAMATO #include <ctype.h>  /* to declare isspace () */
25d4c6f1e6SMasatake YAMATO 
26d4c6f1e6SMasatake YAMATO #include "ctags.h"
27d4c6f1e6SMasatake YAMATO #include "debug.h"
2839da75bcSMasatake YAMATO #include "entry_p.h"
29c08c70d0SMasatake YAMATO #include "field_p.h"
3041a2d6beSMasatake YAMATO #include "gvars.h"
31aa9c3392SMasatake YAMATO #include "keyword_p.h"
320d502ef0SMasatake YAMATO #include "parse_p.h"
330d81da14SMasatake YAMATO #include "ptag_p.h"
3429e40fb6SMasatake YAMATO #include "routines_p.h"
35e2a3289bSMasatake YAMATO #include "xtag_p.h"
3699ac24f8SMasatake YAMATO #include "param_p.h"
377e412a04SMasatake YAMATO #include "error_p.h"
3821996d92SMasatake YAMATO #include "interactive_p.h"
39285b4dfeSMasatake YAMATO #include "writer_p.h"
40782707aeSMasatake YAMATO #include "trace.h"
41d4c6f1e6SMasatake YAMATO 
42ecff6b07SMasatake YAMATO #ifdef HAVE_JANSSON
43ecff6b07SMasatake YAMATO #include <jansson.h>
44ecff6b07SMasatake YAMATO #endif
45ecff6b07SMasatake YAMATO 
46d4c6f1e6SMasatake YAMATO /*
47d4c6f1e6SMasatake YAMATO *   MACROS
48d4c6f1e6SMasatake YAMATO */
49d4c6f1e6SMasatake YAMATO #define INVOCATION  "Usage: %s [options] [file(s)]\n"
50d4c6f1e6SMasatake YAMATO 
51d4c6f1e6SMasatake YAMATO #define CTAGS_ENVIRONMENT  "CTAGS"
52d4c6f1e6SMasatake YAMATO #define ETAGS_ENVIRONMENT  "ETAGS"
53d4c6f1e6SMasatake YAMATO 
54d4c6f1e6SMasatake YAMATO #ifndef ETAGS
55d4c6f1e6SMasatake YAMATO # define ETAGS	"etags"  /* name which causes default use of to -e */
56d4c6f1e6SMasatake YAMATO #endif
57d4c6f1e6SMasatake YAMATO 
58d4c6f1e6SMasatake YAMATO /*  The following separators are permitted for list options.
59d4c6f1e6SMasatake YAMATO  */
60d4c6f1e6SMasatake YAMATO #define EXTENSION_SEPARATOR '.'
61d4c6f1e6SMasatake YAMATO #define PATTERN_START '('
62d4c6f1e6SMasatake YAMATO #define PATTERN_STOP  ')'
63d4c6f1e6SMasatake YAMATO #define IGNORE_SEPARATORS   ", \t\n"
64d4c6f1e6SMasatake YAMATO 
65d4c6f1e6SMasatake YAMATO #ifndef DEFAULT_FILE_FORMAT
66039bc97fSMasatake YAMATO # define DEFAULT_FILE_FORMAT  2
67d4c6f1e6SMasatake YAMATO #endif
68d4c6f1e6SMasatake YAMATO 
6982b817f7SK.Takata #if defined (HAVE_OPENDIR) || defined (HAVE__FINDFIRST)
70d4c6f1e6SMasatake YAMATO # define RECURSE_SUPPORTED
71d4c6f1e6SMasatake YAMATO #endif
72d4c6f1e6SMasatake YAMATO 
73eaa89a10SMasatake YAMATO #define isCompoundOption(c)  (bool) (strchr ("fohiILpdDb", (c)) != NULL)
74d4c6f1e6SMasatake YAMATO 
756684eba6SMasatake YAMATO #define ENTER(STAGE) do {												\
766684eba6SMasatake YAMATO 		Assert (Stage <= OptionLoadingStage##STAGE);					\
7779eec5deSMasatake YAMATO 		if (Stage != OptionLoadingStage##STAGE)							\
7879eec5deSMasatake YAMATO 		{																\
796684eba6SMasatake YAMATO 			Stage = OptionLoadingStage##STAGE;							\
8079eec5deSMasatake YAMATO 			verbose ("Entering configuration stage: loading %s\n", StageDescription[Stage]); \
8179eec5deSMasatake YAMATO 		}																\
826684eba6SMasatake YAMATO 	} while (0)
836684eba6SMasatake YAMATO 
84d4c6f1e6SMasatake YAMATO /*
85d4c6f1e6SMasatake YAMATO *   Data declarations
86d4c6f1e6SMasatake YAMATO */
87d4c6f1e6SMasatake YAMATO 
88d4c6f1e6SMasatake YAMATO enum eOptionLimits {
89d4c6f1e6SMasatake YAMATO 	MaxHeaderExtensions	= 100,  /* maximum number of extensions in -h option */
90039bc97fSMasatake YAMATO 	MaxSupportedTagFormat = 2
91d4c6f1e6SMasatake YAMATO };
92d4c6f1e6SMasatake YAMATO 
93d4c6f1e6SMasatake YAMATO typedef struct sOptionDescription {
94d4c6f1e6SMasatake YAMATO 	int usedByEtags;
95d3f55251SHiroo HAYASHI 	int experimentalOption;
96d4c6f1e6SMasatake YAMATO 	const char *description;
97d4c6f1e6SMasatake YAMATO } optionDescription;
98d4c6f1e6SMasatake YAMATO 
99d4c6f1e6SMasatake YAMATO typedef void (*parametricOptionHandler) (const char *const option, const char *const parameter);
100d4c6f1e6SMasatake YAMATO 
101d4c6f1e6SMasatake YAMATO typedef const struct {
102d4c6f1e6SMasatake YAMATO 	const char* name;   /* name of option as specified by user */
103d4c6f1e6SMasatake YAMATO 	parametricOptionHandler handler;  /* routine to handle option */
104ce990805SThomas Braun 	bool initOnly;   /* option must be specified before any files */
1058da2e646SMasatake YAMATO 	unsigned long acceptableStages;
106d4c6f1e6SMasatake YAMATO } parametricOption;
107d4c6f1e6SMasatake YAMATO 
10835c59e96SMasatake YAMATO typedef const struct sBooleanOption {
109d4c6f1e6SMasatake YAMATO 	const char* name;   /* name of option as specified by user */
110ce990805SThomas Braun 	bool* pValue;    /* pointer to option value */
111ce990805SThomas Braun 	bool initOnly;   /* option must be specified before any files */
1128da2e646SMasatake YAMATO 	unsigned long acceptableStages;
1134f8ad53fSMasatake YAMATO 	void (* set) (const struct sBooleanOption *const option, bool value);
114d4c6f1e6SMasatake YAMATO } booleanOption;
115d4c6f1e6SMasatake YAMATO 
116d4c6f1e6SMasatake YAMATO /*
117d4c6f1e6SMasatake YAMATO *   DATA DEFINITIONS
118d4c6f1e6SMasatake YAMATO */
119d4c6f1e6SMasatake YAMATO 
120ce990805SThomas Braun static bool NonOptionEncountered = false;
121d4c6f1e6SMasatake YAMATO static stringList *OptionFiles;
122d4c6f1e6SMasatake YAMATO 
123d4c6f1e6SMasatake YAMATO typedef stringList searchPathList;
124d4c6f1e6SMasatake YAMATO static searchPathList *OptlibPathList;
125d4c6f1e6SMasatake YAMATO 
126ff29abd0SMasatake YAMATO static stringList *Excluded, *ExcludedException;
127ce990805SThomas Braun static bool FilesRequired = true;
128ce990805SThomas Braun static bool SkipConfiguration;
129d4c6f1e6SMasatake YAMATO 
130d4c6f1e6SMasatake YAMATO static const char *const HeaderExtensions [] = {
131d4c6f1e6SMasatake YAMATO 	"h", "H", "hh", "hpp", "hxx", "h++", "inc", "def", NULL
132d4c6f1e6SMasatake YAMATO };
133d4c6f1e6SMasatake YAMATO 
13441a2d6beSMasatake YAMATO long ctags_debugLevel = 0L;
13541a2d6beSMasatake YAMATO bool ctags_verbose = false;
13641a2d6beSMasatake YAMATO 
137d4c6f1e6SMasatake YAMATO optionValues Option = {
138ee1d9e40SMasatake YAMATO 	.append = false,
139ee1d9e40SMasatake YAMATO 	.backward = false,
140ee1d9e40SMasatake YAMATO 	.etags = false,
141ee1d9e40SMasatake YAMATO 	.locate =
142d4c6f1e6SMasatake YAMATO #ifdef MACROS_USE_PATTERNS
143ee1d9e40SMasatake YAMATO 	EX_PATTERN
144d4c6f1e6SMasatake YAMATO #else
145ee1d9e40SMasatake YAMATO 	EX_MIX
146d4c6f1e6SMasatake YAMATO #endif
147ee1d9e40SMasatake YAMATO 	,
148ee1d9e40SMasatake YAMATO 	.recurse = false,
149ee1d9e40SMasatake YAMATO 	.sorted = SO_SORTED,
150ee1d9e40SMasatake YAMATO 	.xref = false,
1514a63fecaSMasatake YAMATO 	.customXfmt = NULL,
152ee1d9e40SMasatake YAMATO 	.fileList = NULL,
153ee1d9e40SMasatake YAMATO 	.tagFileName = NULL,
154ee1d9e40SMasatake YAMATO 	.headerExt = NULL,
155ee1d9e40SMasatake YAMATO 	.etagsInclude = NULL,
156ee1d9e40SMasatake YAMATO 	.tagFileFormat = DEFAULT_FILE_FORMAT,
1572acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
158ee1d9e40SMasatake YAMATO 	.inputEncoding= NULL,
159ee1d9e40SMasatake YAMATO 	.outputEncoding = NULL,
1602acdcfa1SYasuhiro Matsumoto #endif
161ee1d9e40SMasatake YAMATO 	.language = LANG_AUTO,
162ee1d9e40SMasatake YAMATO 	.followLinks = true,
163ee1d9e40SMasatake YAMATO 	.filter = false,
164ee1d9e40SMasatake YAMATO 	.filterTerminator = NULL,
16500277dc9SMasatake YAMATO 	.tagRelative = TREL_NO,
166a9c91f4dSMasatake YAMATO 	.printTotals = 0,
167ee1d9e40SMasatake YAMATO 	.lineDirectives = false,
168ee1d9e40SMasatake YAMATO 	.printLanguage =false,
169ee1d9e40SMasatake YAMATO 	.guessLanguageEagerly = false,
170ee1d9e40SMasatake YAMATO 	.quiet = false,
171ee1d9e40SMasatake YAMATO 	.fatalWarnings = false,
1727b47ff23SMasatake YAMATO 	.patternLengthLimit = 96,
173ce990805SThomas Braun 	.putFieldPrefix = false,
174078b8008SSzymon Tomasz Stefanek 	.maxRecursionDepth = 0xffffffff,
175ee1d9e40SMasatake YAMATO 	.interactive = false,
176c0421c5eSMasatake YAMATO 	.fieldsReset = false,
177f4904b13SMasatake YAMATO #ifdef WIN32
178f4904b13SMasatake YAMATO 	.useSlashAsFilenameSeparator = FILENAME_SEP_UNSET,
179f4904b13SMasatake YAMATO #endif
180d4c6f1e6SMasatake YAMATO #ifdef DEBUG
181ee1d9e40SMasatake YAMATO 	.breakLine = 0,
182d4c6f1e6SMasatake YAMATO #endif
183d4c6f1e6SMasatake YAMATO };
184d4c6f1e6SMasatake YAMATO 
185a2dce47aSMasatake YAMATO struct localOptionValues {
186a2dce47aSMasatake YAMATO 	bool machinable;			/* --machinable */
187a2dce47aSMasatake YAMATO 	bool withListHeader;		/* --with-list-header */
188a2dce47aSMasatake YAMATO } localOption = {
189a2dce47aSMasatake YAMATO 	.machinable = false,
190a2dce47aSMasatake YAMATO 	.withListHeader = true,
191a2dce47aSMasatake YAMATO };
192a2dce47aSMasatake YAMATO 
193b36d91c3SMasatake YAMATO typedef enum eOptionLoadingStage {
194b36d91c3SMasatake YAMATO 	OptionLoadingStageNone,
195b36d91c3SMasatake YAMATO 	OptionLoadingStageCustom,
196b36d91c3SMasatake YAMATO 	OptionLoadingStageXdg,
197b36d91c3SMasatake YAMATO 	OptionLoadingStageHomeRecursive,
198b36d91c3SMasatake YAMATO 	OptionLoadingStageCurrentRecursive,
199b36d91c3SMasatake YAMATO 	OptionLoadingStageEnvVar,
200b36d91c3SMasatake YAMATO 	OptionLoadingStageCmdline,
201b36d91c3SMasatake YAMATO } OptionLoadingStage;
202b36d91c3SMasatake YAMATO 
2036684eba6SMasatake YAMATO static OptionLoadingStage Stage = OptionLoadingStageNone;
2048da2e646SMasatake YAMATO #define STAGE_ANY ~0UL
2056684eba6SMasatake YAMATO 
206d4c6f1e6SMasatake YAMATO /*
207d4c6f1e6SMasatake YAMATO -   Locally used only
208d4c6f1e6SMasatake YAMATO */
209d4c6f1e6SMasatake YAMATO 
210d4c6f1e6SMasatake YAMATO static optionDescription LongOptionDescription [] = {
2111bdc5d33SHiroo HAYASHI  {1,0,"Input/Output Options"},
212d3f55251SHiroo HAYASHI  {1,0,"  --exclude=<pattern>"},
213d3f55251SHiroo HAYASHI  {1,0,"       Exclude files and directories matching <pattern>."},
214d3f55251SHiroo HAYASHI  {1,0,"       See also --exclude-exception option."},
215d3f55251SHiroo HAYASHI  {1,0,"  --exclude-exception=<pattern>"},
216d3f55251SHiroo HAYASHI  {1,0,"      Don't exclude files and directories matching <pattern> even if"},
217d3f55251SHiroo HAYASHI  {1,0,"      they match the pattern specified with --exclude option."},
2181bdc5d33SHiroo HAYASHI  {1,0,"  --filter[=(yes|no)]"},
2191bdc5d33SHiroo HAYASHI  {1,0,"       Behave as a filter, reading file names from standard input and"},
2201bdc5d33SHiroo HAYASHI  {1,0,"       writing tags to standard output [no]."},
2211bdc5d33SHiroo HAYASHI  {1,0,"  --filter-terminator=<string>"},
2221bdc5d33SHiroo HAYASHI  {1,0,"       Specify <string> to print to stdout following the tags for each file"},
2231bdc5d33SHiroo HAYASHI  {1,0,"       parsed when --filter is enabled."},
2241bdc5d33SHiroo HAYASHI  {1,0,"  --links[=(yes|no)]"},
2251bdc5d33SHiroo HAYASHI  {1,0,"       Indicate whether symbolic links should be followed [yes]."},
2261bdc5d33SHiroo HAYASHI  {1,0,"  --maxdepth=<N>"},
2271bdc5d33SHiroo HAYASHI #ifdef RECURSE_SUPPORTED
2281bdc5d33SHiroo HAYASHI  {1,0,"       Specify maximum recursion depth."},
2291bdc5d33SHiroo HAYASHI #else
2301bdc5d33SHiroo HAYASHI  {1,0,"       Not supported on this platform."},
2311bdc5d33SHiroo HAYASHI #endif
2321bdc5d33SHiroo HAYASHI  {1,0,"  --recurse[=(yes|no)]"},
2331bdc5d33SHiroo HAYASHI #ifdef RECURSE_SUPPORTED
2341bdc5d33SHiroo HAYASHI  {1,0,"       Recurse into directories supplied on command line [no]."},
2351bdc5d33SHiroo HAYASHI  {1,0,"  -R   Equivalent to --recurse."},
2361bdc5d33SHiroo HAYASHI #else
2371bdc5d33SHiroo HAYASHI  {1,0,"       Not supported on this platform."},
2381bdc5d33SHiroo HAYASHI  {1,0,"  -R   Not supported on this platform."},
2391bdc5d33SHiroo HAYASHI #endif
2401bdc5d33SHiroo HAYASHI  {1,0,"  -L <file>"},
2411bdc5d33SHiroo HAYASHI  {1,0,"       A list of input file names is read from the specified <file>."},
2421bdc5d33SHiroo HAYASHI  {1,0,"       If specified as \"-\", then standard input is read."},
2431bdc5d33SHiroo HAYASHI  {1,0,"  --append[=(yes|no)]"},
2441bdc5d33SHiroo HAYASHI  {1,0,"       Should tags should be appended to existing tag file [no]?"},
2451bdc5d33SHiroo HAYASHI  {1,0,"  -a   Append the tags to an existing tag file."},
2461bdc5d33SHiroo HAYASHI  {1,0,"  -f <tagfile>"},
2471bdc5d33SHiroo HAYASHI  {1,0,"       Write tags to specified <tagfile>. Value of \"-\" writes tags to stdout"},
2481bdc5d33SHiroo HAYASHI  {1,0,"       [\"tags\"; or \"TAGS\" when -e supplied]."},
2491bdc5d33SHiroo HAYASHI  {1,0,"  -o   Alternative for -f."},
2501bdc5d33SHiroo HAYASHI  {1,0,""},
2511bdc5d33SHiroo HAYASHI  {1,0,"Output Format Options"},
2521bdc5d33SHiroo HAYASHI  {0,0,"  --format=(1|2)"},
2531bdc5d33SHiroo HAYASHI #if DEFAULT_FILE_FORMAT == 1
2541bdc5d33SHiroo HAYASHI  {0,0,"       Force output of specified tag file format [1]."},
2551bdc5d33SHiroo HAYASHI #else
2561bdc5d33SHiroo HAYASHI  {0,0,"       Force output of specified tag file format [2]."},
2571bdc5d33SHiroo HAYASHI #endif
2581bdc5d33SHiroo HAYASHI #ifdef HAVE_JANSSON
2591bdc5d33SHiroo HAYASHI  {0,0,"  --output-format=(u-ctags|e-ctags|etags|xref|json)"},
2601bdc5d33SHiroo HAYASHI #else
2611bdc5d33SHiroo HAYASHI  {0,0,"  --output-format=(u-ctags|e-ctags|etags|xref)"},
2621bdc5d33SHiroo HAYASHI #endif
2631bdc5d33SHiroo HAYASHI  {0,0,"      Specify the output format. [u-ctags]"},
2641bdc5d33SHiroo HAYASHI  {0,0,"  -e   Output tag file for use with Emacs."},
2651bdc5d33SHiroo HAYASHI  {1,0,"  -x   Print a tabular cross reference file to standard output."},
2661bdc5d33SHiroo HAYASHI  {0,0,"  --sort=(yes|no|foldcase)"},
2671bdc5d33SHiroo HAYASHI  {0,0,"       Should tags be sorted (optionally ignoring case) [yes]?"},
2681bdc5d33SHiroo HAYASHI  {0,0,"  -u   Equivalent to --sort=no."},
2691bdc5d33SHiroo HAYASHI  {1,0,"  --etags-include=<file>"},
2701bdc5d33SHiroo HAYASHI  {1,0,"       Include reference to <file> in Emacs-style tag file (requires -e)."},
2711bdc5d33SHiroo HAYASHI #ifdef HAVE_ICONV
2721bdc5d33SHiroo HAYASHI  {1,0,"  --input-encoding=<encoding>"},
2731bdc5d33SHiroo HAYASHI  {1,0,"       Specify <encoding> of all input files."},
2741bdc5d33SHiroo HAYASHI  {1,0,"  --input-encoding-<LANG>=<encoding>"},
2751bdc5d33SHiroo HAYASHI  {1,0,"       Specify <encoding> of the <LANG> input files."},
2761bdc5d33SHiroo HAYASHI  {1,0,"  --output-encoding=<encoding>"},
2771bdc5d33SHiroo HAYASHI  {1,0,"       The <encoding> to write the tag file in. Defaults to UTF-8 if --input-encoding"},
2781bdc5d33SHiroo HAYASHI  {1,0,"       is specified, otherwise no conversion is performed."},
2791bdc5d33SHiroo HAYASHI #endif
2801bdc5d33SHiroo HAYASHI  {1,1,"  --_xformat=<field_format>"},
2811bdc5d33SHiroo HAYASHI  {1,1,"       Specify custom format for tabular cross reference (-x)."},
2821bdc5d33SHiroo HAYASHI  {1,1,"       Fields can be specified with letter listed in --list-fields."},
2831bdc5d33SHiroo HAYASHI  {1,1,"       e.g. --_xformat=%10N %10l:%K @ %-20F:%-20n"},
2841bdc5d33SHiroo HAYASHI  {1,0,""},
2851bdc5d33SHiroo HAYASHI  {1,0,"Language Selection and Mapping Options"},
2861bdc5d33SHiroo HAYASHI  {1,0,"  --language-force=(<language>|auto)"},
2871bdc5d33SHiroo HAYASHI  {1,0,"       Force all files to be interpreted using specified <language>."},
2881bdc5d33SHiroo HAYASHI  {1,0,"  --languages=[+|-](<list>|all)"},
2891bdc5d33SHiroo HAYASHI  {1,0,"       Restrict files scanned for tags to those mapped to languages"},
2901bdc5d33SHiroo HAYASHI  {1,0,"       specified in the comma-separated <list>. The list can contain any"},
2911bdc5d33SHiroo HAYASHI  {1,0,"       built-in or user-defined language [all]."},
2921bdc5d33SHiroo HAYASHI  {1,0,"  --alias-<LANG>=[+|-](<pattern>|default)"},
2931bdc5d33SHiroo HAYASHI  {1,0,"       Add a <pattern> detecting a name, can be used as an alternative name"},
2941bdc5d33SHiroo HAYASHI  {1,0,"       for <LANG>."},
2951bdc5d33SHiroo HAYASHI  {1,0,"  --guess-language-eagerly"},
2961bdc5d33SHiroo HAYASHI  {1,0,"       Guess the language of input file more eagerly"},
2971bdc5d33SHiroo HAYASHI  {1,0,"       (but taking longer time for guessing):"},
2981bdc5d33SHiroo HAYASHI  {1,0,"       o shebang, even if the input file is not executable,"},
2991bdc5d33SHiroo HAYASHI  {1,0,"       o emacs mode specification at the beginning and end of input file, and"},
3001bdc5d33SHiroo HAYASHI  {1,0,"       o vim syntax specification at the end of input file."},
3011bdc5d33SHiroo HAYASHI  {1,0,"  -G   Equivalent to --guess-language-eagerly."},
3021bdc5d33SHiroo HAYASHI  {1,0,"  --langmap=<map>[,<map>[...]]"},
3031bdc5d33SHiroo HAYASHI  {1,0,"       Override default mapping of language to input file extension."},
3041bdc5d33SHiroo HAYASHI  {1,0,"       e.g. --langmap=c:.c.x,java:+.j,make:([Mm]akefile).mak"},
3051bdc5d33SHiroo HAYASHI  {1,0,"  --map-<LANG>=[+|-]<extension>|<pattern>"},
3061bdc5d33SHiroo HAYASHI  {1,0,"       Set, add(+) or remove(-) the map for <LANG>."},
3071bdc5d33SHiroo HAYASHI  {1,0,"       Unlike --langmap, this doesn't take a list; only one file name <pattern>"},
3081bdc5d33SHiroo HAYASHI  {1,0,"       or one file <extension> can be specified at once."},
3091bdc5d33SHiroo HAYASHI  {1,0,"       Unlike --langmap the change with this option affects mapping of <LANG> only."},
3101bdc5d33SHiroo HAYASHI  {1,0,""},
3111bdc5d33SHiroo HAYASHI  {1,0,"Tags File Contents Options"},
312d3f55251SHiroo HAYASHI  {0,0,"  --excmd=(number|pattern|mix|combine)"},
313d4c6f1e6SMasatake YAMATO #ifdef MACROS_USE_PATTERNS
314d3f55251SHiroo HAYASHI  {0,0,"       Uses the specified type of EX command to locate tags [pattern]."},
315d4c6f1e6SMasatake YAMATO #else
316d3f55251SHiroo HAYASHI  {0,0,"       Uses the specified type of EX command to locate tags [mix]."},
317d4c6f1e6SMasatake YAMATO #endif
3181bdc5d33SHiroo HAYASHI  {0,0,"  -n   Equivalent to --excmd=number."},
3191bdc5d33SHiroo HAYASHI  {0,0,"  -N   Equivalent to --excmd=pattern."},
320d3f55251SHiroo HAYASHI  {1,0,"  --extras=[+|-][<flags>|*]"},
321d3f55251SHiroo HAYASHI  {1,0,"       Include extra tag entries for selected information (<flags>: \"fFgpqrs\") [F]."},
322d3f55251SHiroo HAYASHI  {1,0,"  --extras-(<LANG>|all)=[+|-][<flags>|*]"},
323d3f55251SHiroo HAYASHI  {1,0,"       Include <LANG> own extra tag entries for selected information"},
324d3f55251SHiroo HAYASHI  {1,0,"       (<flags>: see the output of --list-extras=<LANG> option)."},
325d3f55251SHiroo HAYASHI  {1,0,"  --fields=[+|-][<flags>|*]"},
326d3f55251SHiroo HAYASHI  {1,0,"       Include selected extension fields (<flags>: \"aCeEfFikKlmnNpPrRsStxzZ\") [fks]."},
327d3f55251SHiroo HAYASHI  {1,0,"  --fields-(<LANG>|all)=[+|-][<flags>|*]"},
328d3f55251SHiroo HAYASHI  {1,0,"       Include selected <LANG> own extension fields"},
329d3f55251SHiroo HAYASHI  {1,0,"       (<flags>: see the output of --list-fields=<LANG> option)."},
330d3f55251SHiroo HAYASHI  {1,0,"  --kinds-(<LANG>|all)=[+|-](<kinds>|*)"},
331d3f55251SHiroo HAYASHI  {1,0,"       Enable/disable tag <kinds> for language <LANG>."},
3321bdc5d33SHiroo HAYASHI  {0,0,"  --pattern-length-limit=<N>"},
3331bdc5d33SHiroo HAYASHI  {0,0,"      Cutoff patterns of tag entries after <N> characters. Disable by setting to 0. [96]"},
3341bdc5d33SHiroo HAYASHI  {0,0,"  --pseudo-tags=[+|-](<pseudo-tag>|*)"},
3351bdc5d33SHiroo HAYASHI  {0,0,"       Enable/disable emitting pseudo tag named <pseudo-tag>."},
3361bdc5d33SHiroo HAYASHI  {0,0,"       if '*' is given, enable emitting all pseudo tags."},
3371bdc5d33SHiroo HAYASHI  {0,0,"  --put-field-prefix"},
3381bdc5d33SHiroo HAYASHI  {0,0,"       Put \"" CTAGS_FIELD_PREFIX "\" as prefix for the name of fields newly introduced in"},
3391bdc5d33SHiroo HAYASHI  {0,0,"       universal-ctags."},
340*899c9f48SMasatake YAMATO  {1,0,"  --roles-(<LANG>|all).(<kind>|*)=[+|-][<roles>|*]"},
3411bdc5d33SHiroo HAYASHI  {1,0,"       Enable/disable tag roles for kinds of language <LANG>."},
3421bdc5d33SHiroo HAYASHI  {0,0,"  --tag-relative=(yes|no|always|never)"},
3431bdc5d33SHiroo HAYASHI  {0,0,"       Should paths be relative to location of tag file [no; yes when -e]?"},
3441bdc5d33SHiroo HAYASHI  {0,0,"       always: be relative even if input files are passed in with absolute paths" },
3451bdc5d33SHiroo HAYASHI  {0,0,"       never:  be absolute even if input files are passed in with relative paths" },
3461bdc5d33SHiroo HAYASHI #ifdef WIN32
3471bdc5d33SHiroo HAYASHI  {1,0,"  --use-slash-as-filename-separator[=(yes|no)]"},
3481bdc5d33SHiroo HAYASHI  {1,0,"       Use slash as filename separator [yes] for u-ctags output format."},
3491bdc5d33SHiroo HAYASHI #endif
3501bdc5d33SHiroo HAYASHI  {0,0,"  -B   Use backward searching patterns (?...?)."},
3511bdc5d33SHiroo HAYASHI  {0,0,"  -F   Use forward searching patterns (/.../; default)."},
3521bdc5d33SHiroo HAYASHI  {1,0,""},
3531bdc5d33SHiroo HAYASHI  {1,0,"Option File Options"},
3541bdc5d33SHiroo HAYASHI  {1,0,"  --options=<pathname>"},
3551bdc5d33SHiroo HAYASHI  {1,0,"       Specify file (or directory) <pathname> from which command line options should be read."},
3561bdc5d33SHiroo HAYASHI  {1,0,"  --options-maybe=<pathname>"},
3571bdc5d33SHiroo HAYASHI  {1,0,"       Do the same as --options but this doesn't make an error for non-existing file."},
3581bdc5d33SHiroo HAYASHI  {1,0,"  --optlib-dir=[+]<directory>"},
3591bdc5d33SHiroo HAYASHI  {1,0,"       Add or set <directory> to optlib search path."},
3601bdc5d33SHiroo HAYASHI  {1,1,"  --_echo=<msg>"},
3611bdc5d33SHiroo HAYASHI  {1,1,"       Echo <msg> to standard error. Useful to debug the chain"},
3621bdc5d33SHiroo HAYASHI  {1,1,"       of loading option files."},
3631bdc5d33SHiroo HAYASHI  {1,1,"  --_force-quit[=<num>]"},
3641bdc5d33SHiroo HAYASHI  {1,1,"       Quit when loading the option files is processed."},
3651bdc5d33SHiroo HAYASHI  {1,1,"       Useful to debug the chain of loading option files."},
3661bdc5d33SHiroo HAYASHI  {1,0,""},
3671bdc5d33SHiroo HAYASHI  {1,0,"optlib Options"},
3681bdc5d33SHiroo HAYASHI  {1,0,"  --kinddef-<LANG>=<letter>,<name>,<description>"},
3691bdc5d33SHiroo HAYASHI  {1,0,"       Define new kind for <LANG>."},
370d3f55251SHiroo HAYASHI  {1,0,"  --langdef=<name>"},
371d3f55251SHiroo HAYASHI  {1,0,"       Define a new language to be parsed with regular expressions."},
3721bdc5d33SHiroo HAYASHI  {1,0,"  --mline-regex-<LANG>=/<line_pattern>/<name_pattern>/<kind-spec>/[<flags>]"},
3731bdc5d33SHiroo HAYASHI  {1,0,"       Define multiline regular expression for locating tags in specific language."},
3741bdc5d33SHiroo HAYASHI  {1,0,"  --regex-<LANG>=/<line_pattern>/<name_pattern>/<kind-spec>/[<flags>]"},
3751bdc5d33SHiroo HAYASHI  {1,0,"       Define single-line regular expression for locating tags in specific language."},
3761bdc5d33SHiroo HAYASHI  {1,1,"  --_extradef-<LANG>=<name>,<description>"},
3771bdc5d33SHiroo HAYASHI  {1,1,"       Define new extra for <LANG>. --extras-<LANG>=+{name} enables it."},
3781bdc5d33SHiroo HAYASHI  {1,1,"  --_fielddef-<LANG>=<name>,<description>"},
3791bdc5d33SHiroo HAYASHI  {1,1,"       Define new field for <LANG>."},
3801bdc5d33SHiroo HAYASHI  {1,1,"  --_mtable-extend-<LANG>=disttable+srctable."},
3811bdc5d33SHiroo HAYASHI  {1,1,"       Copy patterns of a regex table to another regex table."},
3821bdc5d33SHiroo HAYASHI  {1,1,"  --_mtable-regex-<LANG>=<table>/<line_pattern>/<name_pattern>/[<flags>]"},
3831bdc5d33SHiroo HAYASHI  {1,1,"       Define multitable regular expression for locating tags in specific language."},
3845c872341SMasatake YAMATO  {1,1,"  --_prelude-<LANG>={{ optscript-code }}"},
3855c872341SMasatake YAMATO  {1,1,"       Specify code run before parsing with <LANG> parser."},
3861bdc5d33SHiroo HAYASHI  {1,1,"  --_pretend-<NEWLANG>=<OLDLANG>"},
3871bdc5d33SHiroo HAYASHI  {1,1,"       Make NEWLANG parser pretend OLDLANG parser in lang: field."},
3881bdc5d33SHiroo HAYASHI  {1,1,"  --_roledef-<LANG>.<kind>=<name>,<description>"},
3891bdc5d33SHiroo HAYASHI  {1,1,"       Define new role for the kind in <LANG>."},
3901bdc5d33SHiroo HAYASHI  {1,1,"  --_scopesep-<LANG>=[<parent_kind_letter>|*]/(<child_kind_letter>|*):<separator>"},
3911bdc5d33SHiroo HAYASHI  {1,1,"       Specify scope separator between <PARENT_KIND> and <KIND>."},
3921409a195SMasatake YAMATO  {1,1,"  --_sequel-<LANG>={{ optscript-code }}"},
3931409a195SMasatake YAMATO  {1,1,"       Specify code run after parsing with <LANG> parser."},
3941bdc5d33SHiroo HAYASHI  {1,1,"  --_tabledef-<LANG>=<name>"},
3951bdc5d33SHiroo HAYASHI  {1,1,"       Define new regex table for <LANG>."},
3961bdc5d33SHiroo HAYASHI  {1,0,""},
3971bdc5d33SHiroo HAYASHI  {1,0,"Language Specific Options"},
3981bdc5d33SHiroo HAYASHI  {1,0,"  --if0[=(yes|no)]"},
3991bdc5d33SHiroo HAYASHI  {1,0,"       Should code within #if 0 conditional branches be parsed [no]?"},
400d3f55251SHiroo HAYASHI  {0,0,"  --line-directives[=(yes|no)]"},
401d3f55251SHiroo HAYASHI  {0,0,"       Should '#line' directives be processed [no]?"},
4021bdc5d33SHiroo HAYASHI  {1,0,"  -D <macro>=<definition>"},
4031bdc5d33SHiroo HAYASHI  {1,0,"       (CPreProcessor) Give <definition> for <macro>."},
4041bdc5d33SHiroo HAYASHI  {1,0,"  -h (<list>|default)"},
4051bdc5d33SHiroo HAYASHI  {1,0,"       Specify a <list> of file extensions to be treated as include files"},
4061bdc5d33SHiroo HAYASHI  {1,0,"       [\".h.H.hh.hpp.hxx.h++.inc.def\"]."},
4071bdc5d33SHiroo HAYASHI  {1,0,"  -I [+|-]<list>|@<file>"},
4081bdc5d33SHiroo HAYASHI  {1,0,"       A <list> of tokens to be specially handled is read from either the"},
4091bdc5d33SHiroo HAYASHI  {1,0,"       command line or the specified <file>."},
4108a87cfffSMasatake YAMATO  {1,0,"  --param-<LANG>.<name>=<argument>"},
4111bdc5d33SHiroo HAYASHI  {1,0,"       Set <LANG> specific parameter. Available parameters can be listed with --list-params."},
4121bdc5d33SHiroo HAYASHI  {1,0,""},
4131bdc5d33SHiroo HAYASHI  {1,0,"Listing Options"},
414d3f55251SHiroo HAYASHI  {1,0,"  --list-aliases[=(<language>|all)]"},
415d3f55251SHiroo HAYASHI  {1,0,"       Output list of alias patterns."},
416d3f55251SHiroo HAYASHI  {1,0,"  --list-excludes"},
417d3f55251SHiroo HAYASHI  {1,0,"       Output list of exclude patterns for excluding files/directories."},
418d3f55251SHiroo HAYASHI  {1,0,"  --list-extras[=(<language>|all)]"},
419d3f55251SHiroo HAYASHI  {1,0,"       Output list of extra tag flags."},
420d3f55251SHiroo HAYASHI  {1,0,"  --list-features"},
421d3f55251SHiroo HAYASHI  {1,0,"       Output list of compiled features."},
422d3f55251SHiroo HAYASHI  {1,0,"  --list-fields[=(<language>|all)]"},
423d3f55251SHiroo HAYASHI  {1,0,"       Output list of fields."},
424d3f55251SHiroo HAYASHI  {1,0,"  --list-kinds[=(<language>|all)]"},
425d3f55251SHiroo HAYASHI  {1,0,"       Output a list of all tag kinds for specified <language> or all."},
426d3f55251SHiroo HAYASHI  {1,0,"  --list-kinds-full[=(<language>|all)]"},
427d3f55251SHiroo HAYASHI  {1,0,"       List the details of all tag kinds for specified <language> or all"},
428d3f55251SHiroo HAYASHI  {1,0,"       For each line, associated language name is printed when \"all\" is"},
429d3f55251SHiroo HAYASHI  {1,0,"       specified as language."},
430d3f55251SHiroo HAYASHI  {1,0,"  --list-languages"},
431d3f55251SHiroo HAYASHI  {1,0,"       Output list of supported languages."},
432d3f55251SHiroo HAYASHI  {1,0,"  --list-map-extensions[=(<language>|all)]"},
433d3f55251SHiroo HAYASHI  {1,0,"       Output list of language extensions in mapping."},
434d3f55251SHiroo HAYASHI  {1,0,"  --list-map-patterns[=(<language>|all)]"},
435d3f55251SHiroo HAYASHI  {1,0,"       Output list of language patterns in mapping."},
436d3f55251SHiroo HAYASHI  {1,0,"  --list-maps[=(<language>|all)]"},
437d3f55251SHiroo HAYASHI  {1,0,"       Output list of language mappings (both extensions and patterns)."},
438d3f55251SHiroo HAYASHI  {1,0,"  --list-mline-regex-flags"},
439d3f55251SHiroo HAYASHI  {1,0,"       Output list of flags which can be used in a multiline regex parser definition."},
440d3f55251SHiroo HAYASHI  {1,0,"  --list-params[=(<language>|all)]"},
441d3f55251SHiroo HAYASHI  {1,0,"       Output list of language parameters. This works with --machinable."},
442d3f55251SHiroo HAYASHI  {0,0,"  --list-pseudo-tags"},
443d3f55251SHiroo HAYASHI  {0,0,"       Output list of pseudo tags."},
444d3f55251SHiroo HAYASHI  {1,0,"  --list-regex-flags"},
445d3f55251SHiroo HAYASHI  {1,0,"       Output list of flags which can be used in a regex parser definition."},
446d3f55251SHiroo HAYASHI  {1,0,"  --list-roles[=(<language>|all)[.(<kindspecs>|*)]]"},
447d3f55251SHiroo HAYASHI  {1,0,"       Output list of all roles of tag kind(s) specified for <language>."},
448d3f55251SHiroo HAYASHI  {1,0,"       Both letters and names can be used in <kindspecs>."},
449d3f55251SHiroo HAYASHI  {1,0,"       e.g. --list-roles=C.{header}d"},
450d3f55251SHiroo HAYASHI  {1,0,"  --list-subparsers[=(<baselang>|all)]"},
451d3f55251SHiroo HAYASHI  {1,0,"       Output list of subparsers for the base language."},
452d3f55251SHiroo HAYASHI  {1,0,"  --machinable[=(yes|no)]"},
453d3f55251SHiroo HAYASHI  {1,0,"       Use tab separated representation in --list-* option output. [no]"},
454d3f55251SHiroo HAYASHI  {1,0,"       --list-{aliases,extras,features,fields,kind-full,langdef-flags,params," },
455d3f55251SHiroo HAYASHI  {1,0,"       pseudo-tags,regex-flags,roles,subparsers} support this option."},
456d3f55251SHiroo HAYASHI  {1,0,"       Suitable for scripting. Specify before --list-* option."},
457d3f55251SHiroo HAYASHI  {1,0,"  --with-list-header[=(yes|no)]"},
458d3f55251SHiroo HAYASHI  {1,0,"       Prepend the column descriptions in --list- output. [yes]"},
459d3f55251SHiroo HAYASHI  {1,0,"       --list-{aliases,extras,features,fields,kind-full,langdef-flags,params," },
460d3f55251SHiroo HAYASHI  {1,0,"       pseudo-tags,regex-flags,roles,subparsers} support this option."},
461d3f55251SHiroo HAYASHI  {1,0,"       Specify before --list-* option."},
4621bdc5d33SHiroo HAYASHI  {1,1,"  --_list-kinddef-flags"},
4631bdc5d33SHiroo HAYASHI  {1,1,"       Output list of flags which can be used with --kinddef option."},
4641bdc5d33SHiroo HAYASHI  {1,1,"  --_list-langdef-flags"},
4651bdc5d33SHiroo HAYASHI  {1,1,"       Output list of flags which can be used with --langdef option."},
4661bdc5d33SHiroo HAYASHI  {1,1,"  --_list-mtable-regex-flags"},
4671bdc5d33SHiroo HAYASHI  {1,1,"       Output list of flags which can be used in a multitable regex parser definition."},
468965b7025SMasatake YAMATO  {1,1,"  --_list-operators"},
469965b7025SMasatake YAMATO  {1,1,"       Output list of optscript operators."},
4701bdc5d33SHiroo HAYASHI  {1,0,""},
4711bdc5d33SHiroo HAYASHI  {1,0,"Miscellaneous Options"},
4721bdc5d33SHiroo HAYASHI  {1,0,"  --help"},
4731bdc5d33SHiroo HAYASHI  {1,0,"       Print this option summary."},
4741bdc5d33SHiroo HAYASHI  {1,0,"  -?   Print this option summary."},
4751bdc5d33SHiroo HAYASHI  {1,0,"  --help-full"},
4761bdc5d33SHiroo HAYASHI  {1,0,"       Print this option summary including experimental features."},
4771bdc5d33SHiroo HAYASHI  {1,0,"  --license"},
4781bdc5d33SHiroo HAYASHI  {1,0,"       Print details of software license."},
4791bdc5d33SHiroo HAYASHI  {0,0,"  --print-language"},
4801bdc5d33SHiroo HAYASHI  {0,0,"       Don't make tags file but just print the guessed language name for"},
4811bdc5d33SHiroo HAYASHI  {0,0,"       input file."},
4821bdc5d33SHiroo HAYASHI  {1,0,"  --quiet[=(yes|no)]"},
4831bdc5d33SHiroo HAYASHI  {0,0,"       Don't print NOTICE class messages [no]."},
4841bdc5d33SHiroo HAYASHI  {1,0,"  --totals[=(yes|no|extra)]"},
4851bdc5d33SHiroo HAYASHI  {1,0,"       Print statistics about input and tag files [no]."},
4861bdc5d33SHiroo HAYASHI  {1,0,"  --verbose[=(yes|no)]"},
4871bdc5d33SHiroo HAYASHI  {1,0,"       Enable verbose messages describing actions on each input file."},
4881bdc5d33SHiroo HAYASHI  {1,0,"  --version"},
4891bdc5d33SHiroo HAYASHI  {1,0,"       Print version identifier to standard output."},
4901bdc5d33SHiroo HAYASHI  {1,0,"  -V   Equivalent to --verbose."},
4911bdc5d33SHiroo HAYASHI #ifdef DEBUG
4921bdc5d33SHiroo HAYASHI  {1,0,"  -b <line>"},
4931bdc5d33SHiroo HAYASHI  {1,0,"       Set break line. (for DEBUG)"},
4941bdc5d33SHiroo HAYASHI  {1,0,"  -d <level>"},
4951bdc5d33SHiroo HAYASHI  {1,0,"       Set debug level. (for DEBUG)"},
4961bdc5d33SHiroo HAYASHI #endif
49707b943caSMasatake YAMATO 
498d3f55251SHiroo HAYASHI  {1,1,"  --_anonhash=<fname>"},
499d3f55251SHiroo HAYASHI  {1,1,"       Used in u-ctags test harness"},
500d3f55251SHiroo HAYASHI  {1,1,"  --_dump-keywords"},
501d3f55251SHiroo HAYASHI  {1,1,"       Dump keywords of initialized parser(s)."},
502d3f55251SHiroo HAYASHI  {1,1,"  --_dump-options"},
503d3f55251SHiroo HAYASHI  {1,1,"       Dump options."},
50433f24afcSMasatake YAMATO  {1,1,"  --_dump-prelude"},
50533f24afcSMasatake YAMATO  {1,1,"       Dump contents of optscript prelude."},
506d3f55251SHiroo HAYASHI  {1,1,"  --_fatal-warnings"},
507d3f55251SHiroo HAYASHI  {1,1,"       Make all warnings fatal."},
508d3f55251SHiroo HAYASHI  {1,1,"  --_force-initializing"},
509d3f55251SHiroo HAYASHI  {1,1,"       Initialize all parsers in early stage"},
5102050d074SAman Gupta #ifdef HAVE_JANSSON
511d3f55251SHiroo HAYASHI  {0,1,"  --_interactive"
512e7ed5190SHan-Wen Nienhuys #ifdef HAVE_SECCOMP
51390fd43d1SHiroo HAYASHI   "[=(default|sandbox)]"
514c59f2a21SMasatake YAMATO #endif
515c59f2a21SMasatake YAMATO  },
516d3f55251SHiroo HAYASHI  {0,1,"       Enter interactive mode (JSON over stdio)."},
517c59f2a21SMasatake YAMATO #ifdef HAVE_SECCOMP
518d3f55251SHiroo HAYASHI  {0,1,"       Enter file I/O limited interactive mode if sandbox is specified. [default]"},
519c59f2a21SMasatake YAMATO #endif
520e7ed5190SHan-Wen Nienhuys #endif
521782707aeSMasatake YAMATO #ifdef DO_TRACING
522d3f55251SHiroo HAYASHI  {1,1,"  --_trace=<list>"},
523d3f55251SHiroo HAYASHI  {1,1,"       Trace parsers for the languages."},
524782707aeSMasatake YAMATO #endif
525d3f55251SHiroo HAYASHI  {1,1, NULL}
526d4c6f1e6SMasatake YAMATO };
527d4c6f1e6SMasatake YAMATO 
528d4c6f1e6SMasatake YAMATO static const char* const License1 =
529d4c6f1e6SMasatake YAMATO "This program is free software; you can redistribute it and/or\n"
530d4c6f1e6SMasatake YAMATO "modify it under the terms of the GNU General Public License\n"
531ab9f33f6Sviccuad "as published by the Free Software Foundation; either version 2"
532d4c6f1e6SMasatake YAMATO "of the License, or (at your option) any later version.\n"
533d4c6f1e6SMasatake YAMATO "\n";
534d4c6f1e6SMasatake YAMATO static const char* const License2 =
535d4c6f1e6SMasatake YAMATO "This program is distributed in the hope that it will be useful,\n"
536d4c6f1e6SMasatake YAMATO "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
537d4c6f1e6SMasatake YAMATO "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
538d4c6f1e6SMasatake YAMATO "GNU General Public License for more details.\n"
539d4c6f1e6SMasatake YAMATO "\n"
540d4c6f1e6SMasatake YAMATO "You should have received a copy of the GNU General Public License\n"
541d4c6f1e6SMasatake YAMATO "along with this program; if not, write to the Free Software\n"
542d4c6f1e6SMasatake YAMATO "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n";
543d4c6f1e6SMasatake YAMATO 
544d4c6f1e6SMasatake YAMATO /*  Contains a set of strings describing the set of "features" compiled into
545d4c6f1e6SMasatake YAMATO  *  the code.
546d4c6f1e6SMasatake YAMATO  */
5475352f0a5SMasatake YAMATO static struct Feature {
5485352f0a5SMasatake YAMATO 	const char *name;
5495352f0a5SMasatake YAMATO 	const char *description;
5505352f0a5SMasatake YAMATO } Features [] = {
551d4c6f1e6SMasatake YAMATO #ifdef WIN32
5525352f0a5SMasatake YAMATO 	{"win32", "TO BE WRITTEN"},
553d4c6f1e6SMasatake YAMATO #endif
5545352f0a5SMasatake YAMATO 	/* Following two features are always available on universal ctags */
5555352f0a5SMasatake YAMATO 	{"wildcards", "can use glob matching"},
5565352f0a5SMasatake YAMATO 	{"regex", "can use regular expression based pattern matching"},
55736fa0e22SHiroo HAYASHI #ifdef USE_GNULIB_FNMATCH
55836fa0e22SHiroo HAYASHI 	{"gnulib_fnmatch", "linked with the Gnulib fnmatch library"},
55936fa0e22SHiroo HAYASHI #endif
560cc51f65dSHiroo HAYASHI /* https://lists.gnu.org/archive/html/bug-gnulib/2011-07/msg00435.html */
561cc51f65dSHiroo HAYASHI #ifdef _REGEX_INCLUDE_LIMITS_H
562cc51f65dSHiroo HAYASHI 	{"gnulib_regex", "linked with the Gnulib regular expression library"},
563cc51f65dSHiroo HAYASHI #endif
564d4c6f1e6SMasatake YAMATO #ifndef EXTERNAL_SORT
5655352f0a5SMasatake YAMATO 	{"internal-sort", "uses internal sort routine instead of invoking sort command"},
566d4c6f1e6SMasatake YAMATO #endif
567d4c6f1e6SMasatake YAMATO #ifdef CUSTOM_CONFIGURATION_FILE
5685352f0a5SMasatake YAMATO 	{"custom-conf", "read \"" CUSTOM_CONFIGURATION_FILE "\" as config file"},
569d4c6f1e6SMasatake YAMATO #endif
5707e4bfca4SMasatake YAMATO #if defined (WIN32)
5715352f0a5SMasatake YAMATO 	{"unix-path-separator", "can use '/' as file name separator"},
572d4c6f1e6SMasatake YAMATO #endif
5732acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
5749d021942SMasatake YAMATO 	{"iconv", "can convert input/output encodings"},
5752acdcfa1SYasuhiro Matsumoto #endif
576d4c6f1e6SMasatake YAMATO #ifdef DEBUG
5775352f0a5SMasatake YAMATO 	{"debug", "TO BE WRITTEN"},
578d4c6f1e6SMasatake YAMATO #endif
579e225a827SJiří Techet #if defined (HAVE_DIRENT_H) || defined (_MSC_VER)
5805352f0a5SMasatake YAMATO 	{"option-directory", "TO BE WRITTEN"},
581d4c6f1e6SMasatake YAMATO #endif
582a086aff1SMasatake YAMATO #ifdef HAVE_LIBXML
5835352f0a5SMasatake YAMATO 	{"xpath", "linked with library for parsing xml input"},
584a086aff1SMasatake YAMATO #endif
5859b88981cSAman Gupta #ifdef HAVE_JANSSON
5865352f0a5SMasatake YAMATO 	{"json", "supports json format output"},
5875352f0a5SMasatake YAMATO 	{"interactive", "accepts source code from stdin"},
5889b88981cSAman Gupta #endif
589e7ed5190SHan-Wen Nienhuys #ifdef HAVE_SECCOMP
5905352f0a5SMasatake YAMATO 	{"sandbox", "linked with code for system call level sandbox"},
591e7ed5190SHan-Wen Nienhuys #endif
592288cd67dSMasatake YAMATO #ifdef HAVE_LIBYAML
5935352f0a5SMasatake YAMATO 	{"yaml", "linked with library for parsing yaml input"},
594288cd67dSMasatake YAMATO #endif
5955c0fd3eaSMasatake YAMATO #ifdef CASE_INSENSITIVE_FILENAMES
5965352f0a5SMasatake YAMATO 	{"case-insensitive-filenames", "TO BE WRITTEN"},
5975c0fd3eaSMasatake YAMATO #endif
5987da252f3SMasatake YAMATO #ifdef ENABLE_GCOV
5995352f0a5SMasatake YAMATO 	{"gcov", "linked with code for coverage analysis"},
6007da252f3SMasatake YAMATO #endif
601ad91e260SMasatake YAMATO #ifdef HAVE_PACKCC
602ad91e260SMasatake YAMATO 	/* The test harnesses use this as hints for skipping test cases */
603ad91e260SMasatake YAMATO 	{"packcc", "has peg based parser(s)"},
604ad91e260SMasatake YAMATO #endif
605e8386a4eSMasatake YAMATO 	{"optscript", "can use the interpreter"},
6066a8d5b70SMasatake YAMATO #ifdef HAVE_PCRE2
6076a8d5b70SMasatake YAMATO 	{"pcre2", "has pcre2 regex engine"},
6086a8d5b70SMasatake YAMATO #endif
6095352f0a5SMasatake YAMATO 	{NULL,}
610d4c6f1e6SMasatake YAMATO };
611d4c6f1e6SMasatake YAMATO 
6128da2e646SMasatake YAMATO static const char *const StageDescription [] = {
6138da2e646SMasatake YAMATO 	[OptionLoadingStageNone]   = "not initialized",
6148da2e646SMasatake YAMATO 	[OptionLoadingStageCustom] = "custom file",
615f2416dcaSitchyny 	[OptionLoadingStageXdg] = "file(s) under $XDG_CONFIG_HOME and $HOME/.config",
616573ad0aaSMasatake YAMATO 	[OptionLoadingStageHomeRecursive] = "file(s) under $HOME",
6178da2e646SMasatake YAMATO 	[OptionLoadingStageCurrentRecursive] = "file(s) under the current directory",
6188da2e646SMasatake YAMATO 	[OptionLoadingStageCmdline] = "command line",
6198da2e646SMasatake YAMATO };
6208da2e646SMasatake YAMATO 
621d4c6f1e6SMasatake YAMATO /*
622d4c6f1e6SMasatake YAMATO *   FUNCTION PROTOTYPES
623d4c6f1e6SMasatake YAMATO */
624ce990805SThomas Braun static bool parseFileOptions (const char *const fileName);
625ce990805SThomas Braun static bool parseAllConfigurationFilesOptionsInDirectory (const char *const fileName,
626d4c6f1e6SMasatake YAMATO 							     stringList* const already_loaded_files);
627bdd29018SMasatake YAMATO static bool getBooleanOption (const char *const option, const char *const parameter);
628d4c6f1e6SMasatake YAMATO 
629d4c6f1e6SMasatake YAMATO /*
630d4c6f1e6SMasatake YAMATO *   FUNCTION DEFINITIONS
631d4c6f1e6SMasatake YAMATO */
632d4c6f1e6SMasatake YAMATO 
6332a0a0d8dSFabian Groffen #ifndef HAVE_ASPRINTF
634d4c6f1e6SMasatake YAMATO 
635d4c6f1e6SMasatake YAMATO /* Some versions of MinGW are missing _vscprintf's declaration, although they
636d4c6f1e6SMasatake YAMATO  * still provide the symbol in the import library.
637d4c6f1e6SMasatake YAMATO  */
638d4c6f1e6SMasatake YAMATO #ifdef __MINGW32__
639d4c6f1e6SMasatake YAMATO _CRTIMP int _vscprintf(const char *format, va_list argptr);
640d4c6f1e6SMasatake YAMATO #endif
641d4c6f1e6SMasatake YAMATO 
642d4c6f1e6SMasatake YAMATO #ifndef va_copy
643d4c6f1e6SMasatake YAMATO #define va_copy(dest, src) (dest = src)
644d4c6f1e6SMasatake YAMATO #endif
645d4c6f1e6SMasatake YAMATO 
asprintf(char ** strp,const char * fmt,...)646d4c6f1e6SMasatake YAMATO int asprintf(char **strp, const char *fmt, ...)
647d4c6f1e6SMasatake YAMATO {
648d4c6f1e6SMasatake YAMATO 	va_list args;
649d4c6f1e6SMasatake YAMATO 	va_list args_copy;
650d4c6f1e6SMasatake YAMATO 	int length;
651d4c6f1e6SMasatake YAMATO 	size_t size;
652d4c6f1e6SMasatake YAMATO 
653d4c6f1e6SMasatake YAMATO 	va_start(args, fmt);
654d4c6f1e6SMasatake YAMATO 
655d4c6f1e6SMasatake YAMATO 	va_copy(args_copy, args);
656d4c6f1e6SMasatake YAMATO 
657d4c6f1e6SMasatake YAMATO #ifdef _WIN32
658de4e0619SK.Takata 	/* We need to use _vscprintf to calculate the length as vsnprintf returns -1
659d4c6f1e6SMasatake YAMATO 	 * if the number of characters to write is greater than count.
660d4c6f1e6SMasatake YAMATO 	 */
661d4c6f1e6SMasatake YAMATO 	length = _vscprintf(fmt, args_copy);
662d4c6f1e6SMasatake YAMATO #else
663d4c6f1e6SMasatake YAMATO 	char dummy;
664d4c6f1e6SMasatake YAMATO 	length = vsnprintf(&dummy, sizeof dummy, fmt, args_copy);
665d4c6f1e6SMasatake YAMATO #endif
666d4c6f1e6SMasatake YAMATO 
667d4c6f1e6SMasatake YAMATO 	va_end(args_copy);
668d4c6f1e6SMasatake YAMATO 
669d4c6f1e6SMasatake YAMATO 	Assert(length >= 0);
670d4c6f1e6SMasatake YAMATO 	size = length + 1;
671d4c6f1e6SMasatake YAMATO 
672d4c6f1e6SMasatake YAMATO 	*strp = malloc(size);
673d4c6f1e6SMasatake YAMATO 	if (!*strp) {
674d4c6f1e6SMasatake YAMATO 		return -1;
675d4c6f1e6SMasatake YAMATO 	}
676d4c6f1e6SMasatake YAMATO 
677d4c6f1e6SMasatake YAMATO 	va_start(args, fmt);
678d4c6f1e6SMasatake YAMATO 	vsnprintf(*strp, size, fmt, args);
679d4c6f1e6SMasatake YAMATO 	va_end(args);
680d4c6f1e6SMasatake YAMATO 
681d4c6f1e6SMasatake YAMATO 	return length;
682d4c6f1e6SMasatake YAMATO }
683d4c6f1e6SMasatake YAMATO #endif
684d4c6f1e6SMasatake YAMATO 
verbose(const char * const format,...)685d4c6f1e6SMasatake YAMATO extern void verbose (const char *const format, ...)
686d4c6f1e6SMasatake YAMATO {
68741a2d6beSMasatake YAMATO 	if (ctags_verbose)
688d4c6f1e6SMasatake YAMATO 	{
689d4c6f1e6SMasatake YAMATO 		va_list ap;
690d4c6f1e6SMasatake YAMATO 		va_start (ap, format);
6912bcfb879SMasatake YAMATO 		vfprintf (stderr, format, ap);
692d4c6f1e6SMasatake YAMATO 		va_end (ap);
693d4c6f1e6SMasatake YAMATO 	}
694d4c6f1e6SMasatake YAMATO }
695d4c6f1e6SMasatake YAMATO 
stringCopy(const char * const string)696d4c6f1e6SMasatake YAMATO static char *stringCopy (const char *const string)
697d4c6f1e6SMasatake YAMATO {
698d4c6f1e6SMasatake YAMATO 	char* result = NULL;
699d4c6f1e6SMasatake YAMATO 	if (string != NULL)
700d4c6f1e6SMasatake YAMATO 		result = eStrdup (string);
701d4c6f1e6SMasatake YAMATO 	return result;
702d4c6f1e6SMasatake YAMATO }
703d4c6f1e6SMasatake YAMATO 
freeString(char ** const pString)704d4c6f1e6SMasatake YAMATO static void freeString (char **const pString)
705d4c6f1e6SMasatake YAMATO {
706d4c6f1e6SMasatake YAMATO 	if (*pString != NULL)
707d4c6f1e6SMasatake YAMATO 	{
708d4c6f1e6SMasatake YAMATO 		eFree (*pString);
709d4c6f1e6SMasatake YAMATO 		*pString = NULL;
710d4c6f1e6SMasatake YAMATO 	}
711d4c6f1e6SMasatake YAMATO }
712d4c6f1e6SMasatake YAMATO 
freeList(stringList ** const pList)713d4c6f1e6SMasatake YAMATO extern void freeList (stringList** const pList)
714d4c6f1e6SMasatake YAMATO {
715d4c6f1e6SMasatake YAMATO 	if (*pList != NULL)
716d4c6f1e6SMasatake YAMATO 	{
717d4c6f1e6SMasatake YAMATO 		stringListDelete (*pList);
718d4c6f1e6SMasatake YAMATO 		*pList = NULL;
719d4c6f1e6SMasatake YAMATO 	}
720d4c6f1e6SMasatake YAMATO }
721d4c6f1e6SMasatake YAMATO 
setDefaultTagFileName(void)722d4c6f1e6SMasatake YAMATO extern void setDefaultTagFileName (void)
723d4c6f1e6SMasatake YAMATO {
7244b7a1543SMasatake YAMATO 	if (Option.filter || Option.interactive)
7254b7a1543SMasatake YAMATO 		return;
7264b7a1543SMasatake YAMATO 
7274b7a1543SMasatake YAMATO 	if (Option.tagFileName == NULL)
7284b7a1543SMasatake YAMATO 	{
7294b7a1543SMasatake YAMATO 		const char *tmp = outputDefaultFileName ();
7304b7a1543SMasatake YAMATO 
7314b7a1543SMasatake YAMATO 		if (tmp == NULL)
7324b7a1543SMasatake YAMATO 			tmp = "-";
7334b7a1543SMasatake YAMATO 
7344b7a1543SMasatake YAMATO 		Option.tagFileName = stringCopy (tmp);
7354b7a1543SMasatake YAMATO 	}
736d4c6f1e6SMasatake YAMATO }
737d4c6f1e6SMasatake YAMATO 
filesRequired(void)738ce990805SThomas Braun extern bool filesRequired (void)
739d4c6f1e6SMasatake YAMATO {
740ce990805SThomas Braun 	bool result = FilesRequired;
741d4c6f1e6SMasatake YAMATO 	if (Option.recurse)
742ce990805SThomas Braun 		result = false;
743d4c6f1e6SMasatake YAMATO 	return result;
744d4c6f1e6SMasatake YAMATO }
745d4c6f1e6SMasatake YAMATO 
checkOptions(void)746d4c6f1e6SMasatake YAMATO extern void checkOptions (void)
747d4c6f1e6SMasatake YAMATO {
748d4c6f1e6SMasatake YAMATO 	const char* notice;
749214c1853SMasatake YAMATO 	if (Option.xref && (Option.customXfmt == NULL))
750d4c6f1e6SMasatake YAMATO 	{
751d4c6f1e6SMasatake YAMATO 		notice = "xref output";
752bf0d47e3SMasatake YAMATO 		if (isXtagEnabled(XTAG_FILE_NAMES))
753d4c6f1e6SMasatake YAMATO 		{
754d4c6f1e6SMasatake YAMATO 			error (WARNING, "%s disables file name tags", notice);
755ce990805SThomas Braun 			enableXtag (XTAG_FILE_NAMES, false);
756d4c6f1e6SMasatake YAMATO 		}
757d4c6f1e6SMasatake YAMATO 	}
758d4c6f1e6SMasatake YAMATO 	if (Option.append)
759d4c6f1e6SMasatake YAMATO 	{
760d4c6f1e6SMasatake YAMATO 		notice = "append mode is not compatible with";
761d4c6f1e6SMasatake YAMATO 		if (isDestinationStdout ())
762d4c6f1e6SMasatake YAMATO 			error (FATAL, "%s tags to stdout", notice);
763d4c6f1e6SMasatake YAMATO 	}
764d4c6f1e6SMasatake YAMATO 	if (Option.filter)
765d4c6f1e6SMasatake YAMATO 	{
766d4c6f1e6SMasatake YAMATO 		notice = "filter mode";
767d4c6f1e6SMasatake YAMATO 		if (Option.printTotals)
768d4c6f1e6SMasatake YAMATO 		{
769d4c6f1e6SMasatake YAMATO 			error (WARNING, "%s disables totals", notice);
770a9c91f4dSMasatake YAMATO 			Option.printTotals = 0;
771d4c6f1e6SMasatake YAMATO 		}
772d4c6f1e6SMasatake YAMATO 		if (Option.tagFileName != NULL)
773d4c6f1e6SMasatake YAMATO 			error (WARNING, "%s ignores output tag file name", notice);
774d4c6f1e6SMasatake YAMATO 	}
775c0421c5eSMasatake YAMATO 	writerCheckOptions (Option.fieldsReset);
776d4c6f1e6SMasatake YAMATO }
777d4c6f1e6SMasatake YAMATO 
getLanguageComponentInOptionFull(const char * const option,const char * const prefix,bool noPretending)778f02166dcSMasatake YAMATO extern langType getLanguageComponentInOptionFull (const char *const option,
779f02166dcSMasatake YAMATO 												  const char *const prefix,
780f02166dcSMasatake YAMATO 												  bool noPretending)
781d4ee22f1SMasatake YAMATO {
78228d0ff03SMasatake YAMATO 	size_t prefix_len;
783d4ee22f1SMasatake YAMATO 	langType language;
784d4ee22f1SMasatake YAMATO 	const char *lang;
78597d2a121SMasatake YAMATO 	char *sep = NULL;
78628d0ff03SMasatake YAMATO 	size_t lang_len = 0;
787d4ee22f1SMasatake YAMATO 
788d4ee22f1SMasatake YAMATO 	Assert (prefix && prefix[0]);
789a486300fSMasatake YAMATO 	Assert (option);
790d4ee22f1SMasatake YAMATO 
79128d0ff03SMasatake YAMATO 	prefix_len = strlen (prefix);
79228d0ff03SMasatake YAMATO 	if (strncmp (option, prefix, prefix_len) != 0)
793d4ee22f1SMasatake YAMATO 		return LANG_IGNORE;
794d4ee22f1SMasatake YAMATO 	else
795d4ee22f1SMasatake YAMATO 	{
79628d0ff03SMasatake YAMATO 		lang = option + prefix_len;
797d4ee22f1SMasatake YAMATO 		if (lang [0] == '\0')
798d4ee22f1SMasatake YAMATO 			return LANG_IGNORE;
799d4ee22f1SMasatake YAMATO 	}
800d4ee22f1SMasatake YAMATO 
80197d2a121SMasatake YAMATO 	/* Extract <LANG> from
8028a87cfffSMasatake YAMATO 	 * --param-<LANG>.<PARAM>=..., and
80397d2a121SMasatake YAMATO 	 * --_roledef-<LANG>.<KIND>=... */
8048a87cfffSMasatake YAMATO 
8058a87cfffSMasatake YAMATO 	/*  `:' is only for keeping self compatibility. */
80697d2a121SMasatake YAMATO 	sep = strpbrk (lang, ":.");
80797d2a121SMasatake YAMATO 	if (sep)
8088a87cfffSMasatake YAMATO 	{
8098a87cfffSMasatake YAMATO 		if (*sep == ':')
8108a87cfffSMasatake YAMATO 			error (WARNING, "using `:' as a separator is obsolete; use `.' instead: --%s", option);
81197d2a121SMasatake YAMATO 		lang_len = sep - lang;
8128a87cfffSMasatake YAMATO 	}
8139a391711SMasatake YAMATO 	language = getNamedLanguageFull (lang, lang_len, noPretending, false);
814d4ee22f1SMasatake YAMATO 	if (language == LANG_IGNORE)
8157cec90a7SMasatake YAMATO 	{
8167cec90a7SMasatake YAMATO 		const char *langName = (lang_len == 0)? lang: eStrndup (lang, lang_len);
8177cec90a7SMasatake YAMATO 		error (FATAL, "Unknown language \"%s\" in \"%s\" option", langName, option);
8187cec90a7SMasatake YAMATO 	}
819d4ee22f1SMasatake YAMATO 
820d4ee22f1SMasatake YAMATO 	return language;
821d4ee22f1SMasatake YAMATO }
822d4ee22f1SMasatake YAMATO 
getLanguageComponentInOption(const char * const option,const char * const prefix)823f02166dcSMasatake YAMATO extern langType getLanguageComponentInOption (const char *const option,
824f02166dcSMasatake YAMATO 											  const char *const prefix)
825f02166dcSMasatake YAMATO {
826f02166dcSMasatake YAMATO 	return getLanguageComponentInOptionFull (option, prefix, false);
827f02166dcSMasatake YAMATO }
828f02166dcSMasatake YAMATO 
setEtagsMode(void)829d4c6f1e6SMasatake YAMATO static void setEtagsMode (void)
830d4c6f1e6SMasatake YAMATO {
831ce990805SThomas Braun 	Option.etags = true;
832d4c6f1e6SMasatake YAMATO 	Option.sorted = SO_UNSORTED;
833ce990805SThomas Braun 	Option.lineDirectives = false;
83478478818SMasatake YAMATO 	Option.tagRelative = TREL_YES;
83582791c20SMasatake YAMATO 	enableLanguage (LANG_FALLBACK, true);
836d7738cbeSMasatake YAMATO 	setTagWriter (WRITER_ETAGS, NULL);
837d4c6f1e6SMasatake YAMATO }
838d4c6f1e6SMasatake YAMATO 
testEtagsInvocation(void)839d4c6f1e6SMasatake YAMATO extern void testEtagsInvocation (void)
840d4c6f1e6SMasatake YAMATO {
841d4c6f1e6SMasatake YAMATO 	char* const execName = eStrdup (getExecutableName ());
842d4c6f1e6SMasatake YAMATO 	char* const etags = eStrdup (ETAGS);
843d4c6f1e6SMasatake YAMATO #ifdef CASE_INSENSITIVE_FILENAMES
844d4c6f1e6SMasatake YAMATO 	toLowerString (execName);
845d4c6f1e6SMasatake YAMATO 	toLowerString (etags);
846d4c6f1e6SMasatake YAMATO #endif
847d4c6f1e6SMasatake YAMATO 	if (strstr (execName, etags) != NULL)
848d4c6f1e6SMasatake YAMATO 	{
849d4c6f1e6SMasatake YAMATO 		verbose ("Running in etags mode\n");
850d4c6f1e6SMasatake YAMATO 		setEtagsMode ();
851d4c6f1e6SMasatake YAMATO 	}
852d4c6f1e6SMasatake YAMATO 	eFree (execName);
853d4c6f1e6SMasatake YAMATO 	eFree (etags);
854d4c6f1e6SMasatake YAMATO }
855d4c6f1e6SMasatake YAMATO 
setXrefMode(void)856ee022af7SMasatake YAMATO static void setXrefMode (void)
857ee022af7SMasatake YAMATO {
858ce990805SThomas Braun 	Option.xref = true;
859d7738cbeSMasatake YAMATO 	setTagWriter (WRITER_XREF, NULL);
860ee022af7SMasatake YAMATO }
861ee022af7SMasatake YAMATO 
86237e5978bSMasatake YAMATO #ifdef HAVE_JANSSON
setJsonMode(void)8639b88981cSAman Gupta static void setJsonMode (void)
8649b88981cSAman Gupta {
865ce990805SThomas Braun 	enablePtag (PTAG_JSON_OUTPUT_VERSION, true);
866039bc97fSMasatake YAMATO 	enablePtag (PTAG_OUTPUT_MODE, false);
867ca3471feSMasatake YAMATO 	enablePtag (PTAG_FILE_FORMAT, false);
868d7738cbeSMasatake YAMATO 	setTagWriter (WRITER_JSON, NULL);
8699b88981cSAman Gupta }
87037e5978bSMasatake YAMATO #endif
8719b88981cSAman Gupta 
872d4c6f1e6SMasatake YAMATO /*
873d4c6f1e6SMasatake YAMATO  *  Cooked argument parsing
874d4c6f1e6SMasatake YAMATO  */
875d4c6f1e6SMasatake YAMATO 
parseShortOption(cookedArgs * const args)876d4c6f1e6SMasatake YAMATO static void parseShortOption (cookedArgs *const args)
877d4c6f1e6SMasatake YAMATO {
878d4c6f1e6SMasatake YAMATO 	args->simple [0] = *args->shortOptions++;
879d4c6f1e6SMasatake YAMATO 	args->simple [1] = '\0';
880950f8bafSVitor Antunes 	args->item = eStrdup (args->simple);
881d4c6f1e6SMasatake YAMATO 	if (! isCompoundOption (*args->simple))
882d4c6f1e6SMasatake YAMATO 		args->parameter = "";
883d4c6f1e6SMasatake YAMATO 	else if (*args->shortOptions == '\0')
884d4c6f1e6SMasatake YAMATO 	{
885d4c6f1e6SMasatake YAMATO 		argForth (args->args);
886d4c6f1e6SMasatake YAMATO 		if (argOff (args->args))
887d4c6f1e6SMasatake YAMATO 			args->parameter = NULL;
888d4c6f1e6SMasatake YAMATO 		else
889d4c6f1e6SMasatake YAMATO 			args->parameter = argItem (args->args);
890d4c6f1e6SMasatake YAMATO 		args->shortOptions = NULL;
891d4c6f1e6SMasatake YAMATO 	}
892d4c6f1e6SMasatake YAMATO 	else
893d4c6f1e6SMasatake YAMATO 	{
894d4c6f1e6SMasatake YAMATO 		args->parameter = args->shortOptions;
895d4c6f1e6SMasatake YAMATO 		args->shortOptions = NULL;
896d4c6f1e6SMasatake YAMATO 	}
897d4c6f1e6SMasatake YAMATO }
898d4c6f1e6SMasatake YAMATO 
parseLongOption(cookedArgs * const args,const char * item)899d4c6f1e6SMasatake YAMATO static void parseLongOption (cookedArgs *const args, const char *item)
900d4c6f1e6SMasatake YAMATO {
901d4c6f1e6SMasatake YAMATO 	const char* const equal = strchr (item, '=');
902d4c6f1e6SMasatake YAMATO 	if (equal == NULL)
903d4c6f1e6SMasatake YAMATO 	{
904d4c6f1e6SMasatake YAMATO 		args->item = eStrdup (item);
905d4c6f1e6SMasatake YAMATO 		args->parameter = "";
906d4c6f1e6SMasatake YAMATO 	}
907d4c6f1e6SMasatake YAMATO 	else
908d4c6f1e6SMasatake YAMATO 	{
9096efe027cSMasatake YAMATO 		args->item = eStrndup (item, equal - item);
910d4c6f1e6SMasatake YAMATO 		args->parameter = equal + 1;
911d4c6f1e6SMasatake YAMATO 	}
912d4c6f1e6SMasatake YAMATO 	Assert (args->item != NULL);
913d4c6f1e6SMasatake YAMATO 	Assert (args->parameter != NULL);
914d4c6f1e6SMasatake YAMATO }
915d4c6f1e6SMasatake YAMATO 
cArgRead(cookedArgs * const current)916d4c6f1e6SMasatake YAMATO static void cArgRead (cookedArgs *const current)
917d4c6f1e6SMasatake YAMATO {
918d4c6f1e6SMasatake YAMATO 	char* item;
919d4c6f1e6SMasatake YAMATO 
920d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
921d4c6f1e6SMasatake YAMATO 	if (! argOff (current->args))
922d4c6f1e6SMasatake YAMATO 	{
923d4c6f1e6SMasatake YAMATO 		item = argItem (current->args);
924d4c6f1e6SMasatake YAMATO 		current->shortOptions = NULL;
925d4c6f1e6SMasatake YAMATO 		Assert (item != NULL);
926d4c6f1e6SMasatake YAMATO 		if (strncmp (item, "--", (size_t) 2) == 0)
927d4c6f1e6SMasatake YAMATO 		{
928ce990805SThomas Braun 			current->isOption = true;
929ce990805SThomas Braun 			current->longOption = true;
930d4c6f1e6SMasatake YAMATO 			parseLongOption (current, item + 2);
931d4c6f1e6SMasatake YAMATO 			Assert (current->item != NULL);
932d4c6f1e6SMasatake YAMATO 			Assert (current->parameter != NULL);
933d4c6f1e6SMasatake YAMATO 		}
934d4c6f1e6SMasatake YAMATO 		else if (*item == '-')
935d4c6f1e6SMasatake YAMATO 		{
936ce990805SThomas Braun 			current->isOption = true;
937ce990805SThomas Braun 			current->longOption = false;
938d4c6f1e6SMasatake YAMATO 			current->shortOptions = item + 1;
939d4c6f1e6SMasatake YAMATO 			parseShortOption (current);
940d4c6f1e6SMasatake YAMATO 		}
941d4c6f1e6SMasatake YAMATO 		else
942d4c6f1e6SMasatake YAMATO 		{
943ce990805SThomas Braun 			current->isOption = false;
944ce990805SThomas Braun 			current->longOption = false;
945950f8bafSVitor Antunes 			current->item = eStrdup (item);
946d4c6f1e6SMasatake YAMATO 			current->parameter = NULL;
947d4c6f1e6SMasatake YAMATO 		}
948d4c6f1e6SMasatake YAMATO 	}
949d4c6f1e6SMasatake YAMATO }
950d4c6f1e6SMasatake YAMATO 
cArgNewFromString(const char * string)951d4c6f1e6SMasatake YAMATO extern cookedArgs* cArgNewFromString (const char* string)
952d4c6f1e6SMasatake YAMATO {
953d4c6f1e6SMasatake YAMATO 	cookedArgs* const result = xMalloc (1, cookedArgs);
954d4c6f1e6SMasatake YAMATO 	memset (result, 0, sizeof (cookedArgs));
955d4c6f1e6SMasatake YAMATO 	result->args = argNewFromString (string);
956d4c6f1e6SMasatake YAMATO 	cArgRead (result);
957d4c6f1e6SMasatake YAMATO 	return result;
958d4c6f1e6SMasatake YAMATO }
959d4c6f1e6SMasatake YAMATO 
cArgNewFromArgv(char * const * const argv)960d4c6f1e6SMasatake YAMATO extern cookedArgs* cArgNewFromArgv (char* const* const argv)
961d4c6f1e6SMasatake YAMATO {
962d4c6f1e6SMasatake YAMATO 	cookedArgs* const result = xMalloc (1, cookedArgs);
963d4c6f1e6SMasatake YAMATO 	memset (result, 0, sizeof (cookedArgs));
964d4c6f1e6SMasatake YAMATO 	result->args = argNewFromArgv (argv);
965d4c6f1e6SMasatake YAMATO 	cArgRead (result);
966d4c6f1e6SMasatake YAMATO 	return result;
967d4c6f1e6SMasatake YAMATO }
968d4c6f1e6SMasatake YAMATO 
cArgNewFromFile(FILE * const fp)969d4c6f1e6SMasatake YAMATO extern cookedArgs* cArgNewFromFile (FILE* const fp)
970d4c6f1e6SMasatake YAMATO {
971d4c6f1e6SMasatake YAMATO 	cookedArgs* const result = xMalloc (1, cookedArgs);
972d4c6f1e6SMasatake YAMATO 	memset (result, 0, sizeof (cookedArgs));
973d4c6f1e6SMasatake YAMATO 	result->args = argNewFromFile (fp);
974d4c6f1e6SMasatake YAMATO 	cArgRead (result);
975d4c6f1e6SMasatake YAMATO 	return result;
976d4c6f1e6SMasatake YAMATO }
977d4c6f1e6SMasatake YAMATO 
cArgNewFromLineFile(FILE * const fp)978d4c6f1e6SMasatake YAMATO extern cookedArgs* cArgNewFromLineFile (FILE* const fp)
979d4c6f1e6SMasatake YAMATO {
980d4c6f1e6SMasatake YAMATO 	cookedArgs* const result = xMalloc (1, cookedArgs);
981d4c6f1e6SMasatake YAMATO 	memset (result, 0, sizeof (cookedArgs));
982d4c6f1e6SMasatake YAMATO 	result->args = argNewFromLineFile (fp);
983d4c6f1e6SMasatake YAMATO 	cArgRead (result);
984d4c6f1e6SMasatake YAMATO 	return result;
985d4c6f1e6SMasatake YAMATO }
986d4c6f1e6SMasatake YAMATO 
cArgDelete(cookedArgs * const current)987d4c6f1e6SMasatake YAMATO extern void cArgDelete (cookedArgs* const current)
988d4c6f1e6SMasatake YAMATO {
989d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
990d4c6f1e6SMasatake YAMATO 	argDelete (current->args);
991950f8bafSVitor Antunes 	if (current->item != NULL)
992950f8bafSVitor Antunes 		eFree (current->item);
993d4c6f1e6SMasatake YAMATO 	memset (current, 0, sizeof (cookedArgs));
994d4c6f1e6SMasatake YAMATO 	eFree (current);
995d4c6f1e6SMasatake YAMATO }
996d4c6f1e6SMasatake YAMATO 
cArgOptionPending(cookedArgs * const current)997ce990805SThomas Braun static bool cArgOptionPending (cookedArgs* const current)
998d4c6f1e6SMasatake YAMATO {
999ce990805SThomas Braun 	bool result = false;
1000d4c6f1e6SMasatake YAMATO 	if (current->shortOptions != NULL)
1001d4c6f1e6SMasatake YAMATO 		if (*current->shortOptions != '\0')
1002ce990805SThomas Braun 			result = true;
1003d4c6f1e6SMasatake YAMATO 	return result;
1004d4c6f1e6SMasatake YAMATO }
1005d4c6f1e6SMasatake YAMATO 
cArgOff(cookedArgs * const current)1006ce990805SThomas Braun extern bool cArgOff (cookedArgs* const current)
1007d4c6f1e6SMasatake YAMATO {
1008d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
1009ce990805SThomas Braun 	return (bool) (argOff (current->args) && ! cArgOptionPending (current));
1010d4c6f1e6SMasatake YAMATO }
1011d4c6f1e6SMasatake YAMATO 
cArgIsOption(cookedArgs * const current)1012ce990805SThomas Braun extern bool cArgIsOption (cookedArgs* const current)
1013d4c6f1e6SMasatake YAMATO {
1014d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
1015d4c6f1e6SMasatake YAMATO 	return current->isOption;
1016d4c6f1e6SMasatake YAMATO }
1017d4c6f1e6SMasatake YAMATO 
cArgItem(cookedArgs * const current)1018d4c6f1e6SMasatake YAMATO extern const char* cArgItem (cookedArgs* const current)
1019d4c6f1e6SMasatake YAMATO {
1020d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
1021d4c6f1e6SMasatake YAMATO 	return current->item;
1022d4c6f1e6SMasatake YAMATO }
1023d4c6f1e6SMasatake YAMATO 
cArgForth(cookedArgs * const current)1024d4c6f1e6SMasatake YAMATO extern void cArgForth (cookedArgs* const current)
1025d4c6f1e6SMasatake YAMATO {
1026d4c6f1e6SMasatake YAMATO 	Assert (current != NULL);
1027d4c6f1e6SMasatake YAMATO 	Assert (! cArgOff (current));
1028950f8bafSVitor Antunes 	if (current->item != NULL)
1029950f8bafSVitor Antunes 		eFree (current->item);
1030d4c6f1e6SMasatake YAMATO 	if (cArgOptionPending (current))
1031d4c6f1e6SMasatake YAMATO 		parseShortOption (current);
1032d4c6f1e6SMasatake YAMATO 	else
1033d4c6f1e6SMasatake YAMATO 	{
1034d4c6f1e6SMasatake YAMATO 		Assert (! argOff (current->args));
1035d4c6f1e6SMasatake YAMATO 		argForth (current->args);
1036d4c6f1e6SMasatake YAMATO 		if (! argOff (current->args))
1037d4c6f1e6SMasatake YAMATO 			cArgRead (current);
1038d4c6f1e6SMasatake YAMATO 		else
1039d4c6f1e6SMasatake YAMATO 		{
1040ce990805SThomas Braun 			current->isOption = false;
1041ce990805SThomas Braun 			current->longOption = false;
1042d4c6f1e6SMasatake YAMATO 			current->shortOptions = NULL;
1043d4c6f1e6SMasatake YAMATO 			current->item = NULL;
1044d4c6f1e6SMasatake YAMATO 			current->parameter = NULL;
1045d4c6f1e6SMasatake YAMATO 		}
1046d4c6f1e6SMasatake YAMATO 	}
1047d4c6f1e6SMasatake YAMATO }
1048d4c6f1e6SMasatake YAMATO 
1049d4c6f1e6SMasatake YAMATO /*
1050d4c6f1e6SMasatake YAMATO  *  File extension and language mapping
1051d4c6f1e6SMasatake YAMATO  */
1052d4c6f1e6SMasatake YAMATO 
addExtensionList(stringList * const slist,const char * const elist,const bool clear)1053d4c6f1e6SMasatake YAMATO static void addExtensionList (
1054ce990805SThomas Braun 		stringList *const slist, const char *const elist, const bool clear)
1055d4c6f1e6SMasatake YAMATO {
1056d4c6f1e6SMasatake YAMATO 	char *const extensionList = eStrdup (elist);
1057d4c6f1e6SMasatake YAMATO 	const char *extension = NULL;
1058ce990805SThomas Braun 	bool first = true;
1059d4c6f1e6SMasatake YAMATO 
1060d4c6f1e6SMasatake YAMATO 	if (clear)
1061d4c6f1e6SMasatake YAMATO 	{
1062d4c6f1e6SMasatake YAMATO 		verbose ("      clearing\n");
1063d4c6f1e6SMasatake YAMATO 		stringListClear (slist);
1064d4c6f1e6SMasatake YAMATO 	}
1065d4c6f1e6SMasatake YAMATO 	verbose ("      adding: ");
1066d4c6f1e6SMasatake YAMATO 	if (elist != NULL  &&  *elist != '\0')
1067d4c6f1e6SMasatake YAMATO 	{
1068d4c6f1e6SMasatake YAMATO 		extension = extensionList;
1069d4c6f1e6SMasatake YAMATO 		if (elist [0] == EXTENSION_SEPARATOR)
1070d4c6f1e6SMasatake YAMATO 			++extension;
1071d4c6f1e6SMasatake YAMATO 	}
1072d4c6f1e6SMasatake YAMATO 	while (extension != NULL)
1073d4c6f1e6SMasatake YAMATO 	{
1074d4c6f1e6SMasatake YAMATO 		char *separator = strchr (extension, EXTENSION_SEPARATOR);
1075d4c6f1e6SMasatake YAMATO 		if (separator != NULL)
1076d4c6f1e6SMasatake YAMATO 			*separator = '\0';
1077d4c6f1e6SMasatake YAMATO 		verbose ("%s%s", first ? "" : ", ",
1078d4c6f1e6SMasatake YAMATO 				*extension == '\0' ? "(NONE)" : extension);
1079d4c6f1e6SMasatake YAMATO 		stringListAdd (slist, vStringNewInit (extension));
1080ce990805SThomas Braun 		first = false;
1081d4c6f1e6SMasatake YAMATO 		if (separator == NULL)
1082d4c6f1e6SMasatake YAMATO 			extension = NULL;
1083d4c6f1e6SMasatake YAMATO 		else
1084d4c6f1e6SMasatake YAMATO 			extension = separator + 1;
1085d4c6f1e6SMasatake YAMATO 	}
1086d4c6f1e6SMasatake YAMATO 	BEGIN_VERBOSE(vfp);
1087d4c6f1e6SMasatake YAMATO 	{
1088d4c6f1e6SMasatake YAMATO 		fprintf (vfp, "\n      now: ");
1089d4c6f1e6SMasatake YAMATO 		stringListPrint (slist, vfp);
1090d4c6f1e6SMasatake YAMATO 		putc ('\n', vfp);
1091d4c6f1e6SMasatake YAMATO 	}
1092d4c6f1e6SMasatake YAMATO 	END_VERBOSE();
1093d4c6f1e6SMasatake YAMATO }
1094d4c6f1e6SMasatake YAMATO 
isFalse(const char * parameter)1095ce990805SThomas Braun static bool isFalse (const char *parameter)
1096d4c6f1e6SMasatake YAMATO {
1097ce990805SThomas Braun 	return (bool) (
1098d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "0"  ) == 0  ||
1099d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "n"  ) == 0  ||
1100d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "no" ) == 0  ||
1101d8654acfSMasatake YAMATO 		strcasecmp (parameter, "off") == 0  ||
1102d8654acfSMasatake YAMATO 		strcasecmp (parameter, "false") == 0 );
1103d4c6f1e6SMasatake YAMATO }
1104d4c6f1e6SMasatake YAMATO 
isTrue(const char * parameter)1105ce990805SThomas Braun static bool isTrue (const char *parameter)
1106d4c6f1e6SMasatake YAMATO {
1107ce990805SThomas Braun 	return (bool) (
1108d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "1"  ) == 0  ||
1109d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "y"  ) == 0  ||
1110d4c6f1e6SMasatake YAMATO 		strcasecmp (parameter, "yes") == 0  ||
1111d8654acfSMasatake YAMATO 		strcasecmp (parameter, "on" ) == 0  ||
1112d8654acfSMasatake YAMATO 		strcasecmp (parameter, "true" ) == 0);
1113d4c6f1e6SMasatake YAMATO }
1114d4c6f1e6SMasatake YAMATO 
paramParserBool(const char * value,bool fallback,const char * errWhat,const char * errCategory)1115c92cfeefSMasatake YAMATO extern bool paramParserBool (const char *value, bool fallback,
1116c92cfeefSMasatake YAMATO 							 const char *errWhat, const char *errCategory)
1117c92cfeefSMasatake YAMATO {
1118c92cfeefSMasatake YAMATO 	bool r = fallback;
1119c92cfeefSMasatake YAMATO 
1120c92cfeefSMasatake YAMATO 	if (value [0] == '\0')
1121c92cfeefSMasatake YAMATO 		r = true;
1122c92cfeefSMasatake YAMATO 	else if (isFalse (value))
1123c92cfeefSMasatake YAMATO 		r = false;
1124c92cfeefSMasatake YAMATO 	else if (isTrue (value))
1125c92cfeefSMasatake YAMATO 		r = true;
1126c92cfeefSMasatake YAMATO 	else
1127c92cfeefSMasatake YAMATO 		error (FATAL, "Invalid value for \"%s\" %s", errWhat, errCategory);
1128c92cfeefSMasatake YAMATO 
1129c92cfeefSMasatake YAMATO 	return r;
1130c92cfeefSMasatake YAMATO }
1131c92cfeefSMasatake YAMATO 
1132d4c6f1e6SMasatake YAMATO /*  Determines whether the specified file name is considered to be a header
1133d4c6f1e6SMasatake YAMATO  *  file for the purposes of determining whether enclosed tags are global or
1134d4c6f1e6SMasatake YAMATO  *  static.
1135d4c6f1e6SMasatake YAMATO  */
isIncludeFile(const char * const fileName)1136ce990805SThomas Braun extern bool isIncludeFile (const char *const fileName)
1137d4c6f1e6SMasatake YAMATO {
1138ce990805SThomas Braun 	bool result = false;
1139d4c6f1e6SMasatake YAMATO 	const char *const extension = fileExtension (fileName);
1140d4c6f1e6SMasatake YAMATO 	if (Option.headerExt != NULL)
1141d4c6f1e6SMasatake YAMATO 		result = stringListExtensionMatched (Option.headerExt, extension);
1142d4c6f1e6SMasatake YAMATO 	return result;
1143d4c6f1e6SMasatake YAMATO }
1144d4c6f1e6SMasatake YAMATO 
1145d4c6f1e6SMasatake YAMATO /*
1146d4c6f1e6SMasatake YAMATO  *  Specific option processing
1147d4c6f1e6SMasatake YAMATO  */
1148d4c6f1e6SMasatake YAMATO 
processEtagsInclude(const char * const option,const char * const parameter)1149d4c6f1e6SMasatake YAMATO static void processEtagsInclude (
1150d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1151d4c6f1e6SMasatake YAMATO {
1152d4c6f1e6SMasatake YAMATO 	if (! Option.etags)
1153d4c6f1e6SMasatake YAMATO 		error (FATAL, "Etags must be enabled to use \"%s\" option", option);
1154d4c6f1e6SMasatake YAMATO 	else
1155d4c6f1e6SMasatake YAMATO 	{
1156d4c6f1e6SMasatake YAMATO 		vString *const file = vStringNewInit (parameter);
1157d4c6f1e6SMasatake YAMATO 		if (Option.etagsInclude == NULL)
1158d4c6f1e6SMasatake YAMATO 			Option.etagsInclude = stringListNew ();
1159d4c6f1e6SMasatake YAMATO 		stringListAdd (Option.etagsInclude, file);
1160ce990805SThomas Braun 		FilesRequired = false;
1161d4c6f1e6SMasatake YAMATO 	}
1162d4c6f1e6SMasatake YAMATO }
1163d4c6f1e6SMasatake YAMATO 
processExcludeOptionCommon(stringList ** list,const char * const optname,const char * const parameter)1164ff29abd0SMasatake YAMATO static void processExcludeOptionCommon (
1165ff29abd0SMasatake YAMATO 	stringList** list, const char *const optname, const char *const parameter)
1166d4c6f1e6SMasatake YAMATO {
1167d4c6f1e6SMasatake YAMATO 	const char *const fileName = parameter + 1;
1168d4c6f1e6SMasatake YAMATO 	if (parameter [0] == '\0')
1169ff29abd0SMasatake YAMATO 		freeList (list);
1170d4c6f1e6SMasatake YAMATO 	else if (parameter [0] == '@')
1171d4c6f1e6SMasatake YAMATO 	{
1172d4c6f1e6SMasatake YAMATO 		stringList* const sl = stringListNewFromFile (fileName);
1173d4c6f1e6SMasatake YAMATO 		if (sl == NULL)
1174d4c6f1e6SMasatake YAMATO 			error (FATAL | PERROR, "cannot open \"%s\"", fileName);
1175ff29abd0SMasatake YAMATO 		if (*list == NULL)
1176ff29abd0SMasatake YAMATO 			*list = sl;
1177d4c6f1e6SMasatake YAMATO 		else
1178ff29abd0SMasatake YAMATO 			stringListCombine (*list, sl);
1179ff29abd0SMasatake YAMATO 		verbose ("    adding %s patterns from %s\n", optname, fileName);
1180d4c6f1e6SMasatake YAMATO 	}
1181d4c6f1e6SMasatake YAMATO 	else
1182d4c6f1e6SMasatake YAMATO 	{
1183d4c6f1e6SMasatake YAMATO 		vString *const item = vStringNewInit (parameter);
118440bf0941SMasatake YAMATO #if defined (WIN32)
118542a65786SMasatake YAMATO 		vStringTranslate(item, PATH_SEPARATOR, OUTPUT_PATH_SEPARATOR);
118640bf0941SMasatake YAMATO #endif
1187ff29abd0SMasatake YAMATO 		if (*list == NULL)
1188ff29abd0SMasatake YAMATO 			*list = stringListNew ();
1189ff29abd0SMasatake YAMATO 		stringListAdd (*list, item);
1190ff29abd0SMasatake YAMATO 		verbose ("    adding %s pattern: %s\n", optname, parameter);
1191d4c6f1e6SMasatake YAMATO 	}
1192d4c6f1e6SMasatake YAMATO }
1193d4c6f1e6SMasatake YAMATO 
processExcludeOption(const char * const option,const char * const parameter)1194ff29abd0SMasatake YAMATO static void processExcludeOption (
1195ff29abd0SMasatake YAMATO 		const char *const option, const char *const parameter)
1196ff29abd0SMasatake YAMATO {
1197ff29abd0SMasatake YAMATO 	processExcludeOptionCommon (&Excluded, option, parameter);
1198ff29abd0SMasatake YAMATO }
1199ff29abd0SMasatake YAMATO 
processExcludeExceptionOption(const char * const option,const char * const parameter)1200ff29abd0SMasatake YAMATO static void processExcludeExceptionOption (
1201ff29abd0SMasatake YAMATO 		const char *const option, const char *const parameter)
1202ff29abd0SMasatake YAMATO {
1203ff29abd0SMasatake YAMATO 	processExcludeOptionCommon (&ExcludedException, option, parameter);
1204ff29abd0SMasatake YAMATO }
1205ff29abd0SMasatake YAMATO 
isExcludedFile(const char * const name,bool falseIfExceptionsAreDefeind)1206ff29abd0SMasatake YAMATO extern bool isExcludedFile (const char* const name,
1207ff29abd0SMasatake YAMATO 							bool falseIfExceptionsAreDefeind)
1208d4c6f1e6SMasatake YAMATO {
1209d4c6f1e6SMasatake YAMATO 	const char* base = baseFilename (name);
1210ce990805SThomas Braun 	bool result = false;
1211ff29abd0SMasatake YAMATO 
1212ff29abd0SMasatake YAMATO 	if (falseIfExceptionsAreDefeind
1213ff29abd0SMasatake YAMATO 		&& ExcludedException != NULL
1214ff29abd0SMasatake YAMATO 		&& stringListCount (ExcludedException) > 0)
1215ff29abd0SMasatake YAMATO 		return false;
1216ff29abd0SMasatake YAMATO 
1217d4c6f1e6SMasatake YAMATO 	if (Excluded != NULL)
1218d4c6f1e6SMasatake YAMATO 	{
1219d4c6f1e6SMasatake YAMATO 		result = stringListFileMatched (Excluded, base);
1220d4c6f1e6SMasatake YAMATO 		if (! result  &&  name != base)
1221d4c6f1e6SMasatake YAMATO 			result = stringListFileMatched (Excluded, name);
1222d4c6f1e6SMasatake YAMATO 	}
1223ff29abd0SMasatake YAMATO 
1224ff29abd0SMasatake YAMATO 	if (result && ExcludedException != NULL)
1225ff29abd0SMasatake YAMATO 	{
1226ff29abd0SMasatake YAMATO 		bool result_exception;
1227ff29abd0SMasatake YAMATO 
1228ff29abd0SMasatake YAMATO 		result_exception = stringListFileMatched (ExcludedException, base);
1229ff29abd0SMasatake YAMATO 		if (! result_exception && name != base)
1230ff29abd0SMasatake YAMATO 			result_exception = stringListFileMatched (ExcludedException, name);
1231ff29abd0SMasatake YAMATO 
1232ff29abd0SMasatake YAMATO 		if (result_exception)
1233ff29abd0SMasatake YAMATO 			result = false;
1234ff29abd0SMasatake YAMATO 	}
1235d4c6f1e6SMasatake YAMATO 	return result;
1236d4c6f1e6SMasatake YAMATO }
1237d4c6f1e6SMasatake YAMATO 
processExcmdOption(const char * const option,const char * const parameter)1238d4c6f1e6SMasatake YAMATO static void processExcmdOption (
1239d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1240d4c6f1e6SMasatake YAMATO {
1241d4c6f1e6SMasatake YAMATO 	switch (*parameter)
1242d4c6f1e6SMasatake YAMATO 	{
1243d4c6f1e6SMasatake YAMATO 		case 'm': Option.locate = EX_MIX;     break;
1244d4c6f1e6SMasatake YAMATO 		case 'n': Option.locate = EX_LINENUM; break;
1245d4c6f1e6SMasatake YAMATO 		case 'p': Option.locate = EX_PATTERN; break;
1246d4c6f1e6SMasatake YAMATO 		default:
1247d62cebebSMasatake YAMATO 			if (strcmp(parameter, "combine") == 0)
1248d62cebebSMasatake YAMATO 				Option.locate = EX_COMBINE;
1249d62cebebSMasatake YAMATO 			else
12502eb35e90SMasatake YAMATO 				error (FATAL, "Invalid value for \"%s\" option: %s", option, parameter);
1251d4c6f1e6SMasatake YAMATO 			break;
1252d4c6f1e6SMasatake YAMATO 	}
1253d4c6f1e6SMasatake YAMATO }
1254d4c6f1e6SMasatake YAMATO 
resetXtags(langType lang,bool mode)12558643c5b5SMasatake YAMATO static void resetXtags (langType lang, bool mode)
12568eccc874SMasatake YAMATO {
12578eccc874SMasatake YAMATO 	int i;
12588643c5b5SMasatake YAMATO 	for (i = 0; i < countXtags (); i++)
12598643c5b5SMasatake YAMATO 		if ((lang == LANG_AUTO) || (lang == getXtagOwner (i)))
12608eccc874SMasatake YAMATO 			enableXtag (i, mode);
12618eccc874SMasatake YAMATO }
12628eccc874SMasatake YAMATO 
processExtraTagsOption(const char * const option,const char * const parameter)1263d4c6f1e6SMasatake YAMATO static void processExtraTagsOption (
1264d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1265d4c6f1e6SMasatake YAMATO {
126635c59e96SMasatake YAMATO 	xtagType t;
1267d4c6f1e6SMasatake YAMATO 	const char *p = parameter;
1268ce990805SThomas Braun 	bool mode = true;
1269d4c6f1e6SMasatake YAMATO 	int c;
12700d1270c9SMasatake YAMATO 	static vString *longName;
1271ce990805SThomas Braun 	bool inLongName = false;
12720d1270c9SMasatake YAMATO 	const char *x;
1273d4c6f1e6SMasatake YAMATO 
1274d76bc950SMasatake YAMATO 	if (strcmp (option, "extra") == 0)
1275d76bc950SMasatake YAMATO 		error(WARNING, "--extra option is obsolete; use --extras instead");
1276d76bc950SMasatake YAMATO 
12770d1270c9SMasatake YAMATO 	if (*p == '*')
1278d4c6f1e6SMasatake YAMATO 	{
12798643c5b5SMasatake YAMATO 		resetXtags (LANG_IGNORE, true);
12800d1270c9SMasatake YAMATO 		p++;
1281d4c6f1e6SMasatake YAMATO 	}
12820d1270c9SMasatake YAMATO 	else if (*p != '+'  &&  *p != '-')
12838643c5b5SMasatake YAMATO 		resetXtags (LANG_IGNORE, false);
12840d1270c9SMasatake YAMATO 
128556065e52SMasatake YAMATO 	longName = vStringNewOrClearWithAutoRelease (longName);
12860d1270c9SMasatake YAMATO 
12870d1270c9SMasatake YAMATO 	while ((c = *p++) != '\0')
1288d4c6f1e6SMasatake YAMATO 	{
12890d1270c9SMasatake YAMATO 		switch (c)
12900d1270c9SMasatake YAMATO 		{
12910d1270c9SMasatake YAMATO 		case '+':
12920d1270c9SMasatake YAMATO 			if (inLongName)
12930d1270c9SMasatake YAMATO 				vStringPut (longName, c);
12940d1270c9SMasatake YAMATO 			else
1295ce990805SThomas Braun 				mode = true;
12960d1270c9SMasatake YAMATO 			break;
12970d1270c9SMasatake YAMATO 		case '-':
12980d1270c9SMasatake YAMATO 			if (inLongName)
12990d1270c9SMasatake YAMATO 				vStringPut (longName, c);
13000d1270c9SMasatake YAMATO 			else
1301ce990805SThomas Braun 				mode = false;
13020d1270c9SMasatake YAMATO 			break;
13030d1270c9SMasatake YAMATO 		case '{':
13040d1270c9SMasatake YAMATO 			if (inLongName)
13050d1270c9SMasatake YAMATO 				error(FATAL,
13060d1270c9SMasatake YAMATO 				      "unexpected character in extra specification: \'%c\'",
13070d1270c9SMasatake YAMATO 				      c);
1308ce990805SThomas Braun 			inLongName = true;
13090d1270c9SMasatake YAMATO 			break;
13100d1270c9SMasatake YAMATO 		case '}':
13110d1270c9SMasatake YAMATO 			if (!inLongName)
13120d1270c9SMasatake YAMATO 				error(FATAL,
13130d1270c9SMasatake YAMATO 				      "unexpected character in extra specification: \'%c\'",
13140d1270c9SMasatake YAMATO 				      c);
13150d1270c9SMasatake YAMATO 			x = vStringValue (longName);
13168643c5b5SMasatake YAMATO 			t = getXtagTypeForNameAndLanguage (x, LANG_IGNORE);
13170d1270c9SMasatake YAMATO 
13180d1270c9SMasatake YAMATO 			if (t == XTAG_UNKNOWN)
13190d1270c9SMasatake YAMATO 				error(WARNING, "Unsupported parameter '{%s}' for \"%s\" option",
13200d1270c9SMasatake YAMATO 				      x, option);
13210d1270c9SMasatake YAMATO 			else
13220d1270c9SMasatake YAMATO 				enableXtag (t, mode);
13230d1270c9SMasatake YAMATO 
1324ce990805SThomas Braun 			inLongName = false;
13250d1270c9SMasatake YAMATO 			vStringClear (longName);
1326309af5d6SMasatake YAMATO 			break;
132735c59e96SMasatake YAMATO 		default:
13280d1270c9SMasatake YAMATO 			if (inLongName)
13290d1270c9SMasatake YAMATO 				vStringPut (longName, c);
13300d1270c9SMasatake YAMATO 			else
13310d1270c9SMasatake YAMATO 			{
13320d1270c9SMasatake YAMATO 				t = getXtagTypeForLetter (c);
133335c59e96SMasatake YAMATO 				if (t == XTAG_UNKNOWN)
133435c59e96SMasatake YAMATO 					error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
1335d4c6f1e6SMasatake YAMATO 					      c, option);
133635c59e96SMasatake YAMATO 				else
133735c59e96SMasatake YAMATO 					enableXtag (t, mode);
13380d1270c9SMasatake YAMATO 			}
1339d4c6f1e6SMasatake YAMATO 			break;
1340d4c6f1e6SMasatake YAMATO 		}
1341d4c6f1e6SMasatake YAMATO 	}
13420d1270c9SMasatake YAMATO }
1343d4c6f1e6SMasatake YAMATO 
resetFieldsOption(langType lang,bool mode)1344ce990805SThomas Braun static void resetFieldsOption (langType lang, bool mode)
1345d4c6f1e6SMasatake YAMATO {
1346028a8808SMasatake YAMATO 	int i;
134722f33d7aSMasatake YAMATO 
134822f33d7aSMasatake YAMATO 	for (i = 0; i < countFields (); ++i)
13499135e21dSMasatake YAMATO 		if ((lang == LANG_AUTO) || (lang == getFieldOwner (i)))
1350c0421c5eSMasatake YAMATO 			enableField (i, mode);
1351c0421c5eSMasatake YAMATO 
1352c0421c5eSMasatake YAMATO 	if ((lang == LANG_AUTO || lang == LANG_IGNORE)&& !mode)
1353c0421c5eSMasatake YAMATO 		Option.fieldsReset = true;
1354d4c6f1e6SMasatake YAMATO }
1355d4c6f1e6SMasatake YAMATO 
processFieldsOption(const char * const option,const char * const parameter)1356d4c6f1e6SMasatake YAMATO static void processFieldsOption (
1357d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1358d4c6f1e6SMasatake YAMATO {
1359d4c6f1e6SMasatake YAMATO 	const char *p = parameter;
1360ce990805SThomas Braun 	bool mode = true;
1361d4c6f1e6SMasatake YAMATO 	int c;
13622894800fSMasatake YAMATO 	fieldType t;
1363ad1a3891SMasatake YAMATO 
1364a696f376SMasatake YAMATO 	static vString * longName;
1365ce990805SThomas Braun 	bool inLongName = false;
1366a696f376SMasatake YAMATO 
136756065e52SMasatake YAMATO 	longName = vStringNewOrClearWithAutoRelease (longName);
1368d4c6f1e6SMasatake YAMATO 
1369d4c6f1e6SMasatake YAMATO 	if (*p == '*')
1370d4c6f1e6SMasatake YAMATO 	{
1371ce990805SThomas Braun 		resetFieldsOption (LANG_IGNORE, true);
1372d4c6f1e6SMasatake YAMATO 		p++;
1373d4c6f1e6SMasatake YAMATO 	}
1374d4c6f1e6SMasatake YAMATO 	else if (*p != '+'  &&  *p != '-')
1375ce990805SThomas Braun 		resetFieldsOption (LANG_IGNORE, false);
1376d4c6f1e6SMasatake YAMATO 
1377d4c6f1e6SMasatake YAMATO 	while ((c = *p++) != '\0') switch (c)
1378d4c6f1e6SMasatake YAMATO 	{
1379a696f376SMasatake YAMATO 		case '+':
1380a696f376SMasatake YAMATO 			if (inLongName)
1381a696f376SMasatake YAMATO 				vStringPut (longName, c);
1382a696f376SMasatake YAMATO 			else
1383ce990805SThomas Braun 				mode = true;
1384a696f376SMasatake YAMATO 			break;
1385a696f376SMasatake YAMATO 		case '-':
1386a696f376SMasatake YAMATO 			if (inLongName)
1387a696f376SMasatake YAMATO 				vStringPut (longName, c);
1388a696f376SMasatake YAMATO 			else
1389ce990805SThomas Braun 				mode = false;
1390a696f376SMasatake YAMATO 			break;
1391a696f376SMasatake YAMATO 		case '{':
1392a696f376SMasatake YAMATO 			if (inLongName)
1393a696f376SMasatake YAMATO 				error(FATAL,
1394a696f376SMasatake YAMATO 				      "unexpected character in field specification: \'%c\'",
1395a696f376SMasatake YAMATO 				      c);
1396ce990805SThomas Braun 			inLongName = true;
1397a696f376SMasatake YAMATO 			break;
1398a696f376SMasatake YAMATO 		case '}':
1399a696f376SMasatake YAMATO 			if (!inLongName)
1400a696f376SMasatake YAMATO 				error(FATAL,
1401a696f376SMasatake YAMATO 				      "unexpected character in field specification: \'%c\'",
1402a696f376SMasatake YAMATO 				      c);
1403a696f376SMasatake YAMATO 
14048f2569d8SMasatake YAMATO 			{
14059135e21dSMasatake YAMATO 				const char *f = vStringValue (longName);
14069135e21dSMasatake YAMATO 				t = getFieldTypeForNameAndLanguage (f, LANG_IGNORE);
14078f2569d8SMasatake YAMATO 			}
14088f2569d8SMasatake YAMATO 
1409a696f376SMasatake YAMATO 			if (t == FIELD_UNKNOWN)
14108f2569d8SMasatake YAMATO 				error(FATAL, "no such field: \'%s\'", vStringValue (longName));
1411a696f376SMasatake YAMATO 
1412c0421c5eSMasatake YAMATO 			enableField (t, mode);
14138f2569d8SMasatake YAMATO 
1414ce990805SThomas Braun 			inLongName = false;
1415a696f376SMasatake YAMATO 			vStringClear (longName);
1416a696f376SMasatake YAMATO 			break;
1417a696f376SMasatake YAMATO 		default :
1418a696f376SMasatake YAMATO 			if (inLongName)
1419a696f376SMasatake YAMATO 				vStringPut (longName, c);
1420a696f376SMasatake YAMATO 			else
1421a696f376SMasatake YAMATO 			{
1422a696f376SMasatake YAMATO 				t = getFieldTypeForOption (c);
14232894800fSMasatake YAMATO 				if (t == FIELD_UNKNOWN)
14242894800fSMasatake YAMATO 					error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
1425d4c6f1e6SMasatake YAMATO 					      c, option);
14265f95b209SMasatake YAMATO 				else
1427c0421c5eSMasatake YAMATO 					enableField (t, mode);
1428a696f376SMasatake YAMATO 			}
1429d4c6f1e6SMasatake YAMATO 			break;
1430d4c6f1e6SMasatake YAMATO 	}
1431d4c6f1e6SMasatake YAMATO }
1432d4c6f1e6SMasatake YAMATO 
processFilterTerminatorOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)1433d4c6f1e6SMasatake YAMATO static void processFilterTerminatorOption (
14348ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED, const char *const parameter)
1435d4c6f1e6SMasatake YAMATO {
1436d4c6f1e6SMasatake YAMATO 	freeString (&Option.filterTerminator);
1437d4c6f1e6SMasatake YAMATO 	Option.filterTerminator = stringCopy (parameter);
1438d4c6f1e6SMasatake YAMATO }
1439d4c6f1e6SMasatake YAMATO 
processFormatOption(const char * const option,const char * const parameter)1440d4c6f1e6SMasatake YAMATO static void processFormatOption (
1441d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1442d4c6f1e6SMasatake YAMATO {
1443d4c6f1e6SMasatake YAMATO 	unsigned int format;
1444d4c6f1e6SMasatake YAMATO 
1445d4c6f1e6SMasatake YAMATO 	if (sscanf (parameter, "%u", &format) < 1)
1446d4c6f1e6SMasatake YAMATO 		error (FATAL, "Invalid value for \"%s\" option",option);
1447d4c6f1e6SMasatake YAMATO 	else if (format <= (unsigned int) MaxSupportedTagFormat)
1448d4c6f1e6SMasatake YAMATO 		Option.tagFileFormat = format;
1449d4c6f1e6SMasatake YAMATO 	else
1450d4c6f1e6SMasatake YAMATO 		error (FATAL, "Unsupported value for \"%s\" option", option);
1451d4c6f1e6SMasatake YAMATO }
1452d4c6f1e6SMasatake YAMATO 
14532acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
processInputEncodingOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)1454e4d16241SMasatake YAMATO static void processInputEncodingOption(const char *const option CTAGS_ATTR_UNUSED,
14552acdcfa1SYasuhiro Matsumoto 				const char *const parameter)
14562acdcfa1SYasuhiro Matsumoto {
14572acdcfa1SYasuhiro Matsumoto 	if (Option.inputEncoding)
14582acdcfa1SYasuhiro Matsumoto 		eFree (Option.inputEncoding);
14592acdcfa1SYasuhiro Matsumoto 	else
14602acdcfa1SYasuhiro Matsumoto 	{
14612acdcfa1SYasuhiro Matsumoto 		if (!Option.outputEncoding)
14622acdcfa1SYasuhiro Matsumoto 			Option.outputEncoding = eStrdup("UTF-8");
14632acdcfa1SYasuhiro Matsumoto 	}
14642acdcfa1SYasuhiro Matsumoto 	Option.inputEncoding = eStrdup(parameter);
14652acdcfa1SYasuhiro Matsumoto }
14662acdcfa1SYasuhiro Matsumoto 
processOutputEncodingOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)1467e4d16241SMasatake YAMATO static void processOutputEncodingOption(const char *const option CTAGS_ATTR_UNUSED,
14682acdcfa1SYasuhiro Matsumoto 				const char *const parameter)
14692acdcfa1SYasuhiro Matsumoto {
14702acdcfa1SYasuhiro Matsumoto 	if (Option.outputEncoding)
14712acdcfa1SYasuhiro Matsumoto 		eFree (Option.outputEncoding);
14722acdcfa1SYasuhiro Matsumoto 	Option.outputEncoding = eStrdup(parameter);
14732acdcfa1SYasuhiro Matsumoto }
14742acdcfa1SYasuhiro Matsumoto #endif
14752acdcfa1SYasuhiro Matsumoto 
printInvocationDescription(void)1476d4c6f1e6SMasatake YAMATO static void printInvocationDescription (void)
1477d4c6f1e6SMasatake YAMATO {
1478d4c6f1e6SMasatake YAMATO 	printf (INVOCATION, getExecutableName ());
1479d4c6f1e6SMasatake YAMATO }
1480d4c6f1e6SMasatake YAMATO 
excludesCompare(struct colprintLine * a,struct colprintLine * b)1481199c84cdSHadriel Kaplan static int excludesCompare (struct colprintLine *a, struct colprintLine *b)
1482199c84cdSHadriel Kaplan {
1483199c84cdSHadriel Kaplan 	return strcmp (colprintLineGetColumn (a, 0), colprintLineGetColumn (b, 0));
1484199c84cdSHadriel Kaplan }
1485199c84cdSHadriel Kaplan 
processListExcludesOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)1486199c84cdSHadriel Kaplan static void processListExcludesOption(const char *const option CTAGS_ATTR_UNUSED,
1487199c84cdSHadriel Kaplan 				      const char *const parameter CTAGS_ATTR_UNUSED)
1488199c84cdSHadriel Kaplan {
1489199c84cdSHadriel Kaplan 	int i;
1490199c84cdSHadriel Kaplan 	struct colprintTable *table = colprintTableNew ("L:NAME", NULL);
1491199c84cdSHadriel Kaplan 
1492199c84cdSHadriel Kaplan 	const int max = Excluded ? stringListCount (Excluded) : 0;
1493199c84cdSHadriel Kaplan 
1494199c84cdSHadriel Kaplan 	for (i = 0; i < max; ++i)
1495199c84cdSHadriel Kaplan 	{
1496199c84cdSHadriel Kaplan 		struct colprintLine * line = colprintTableGetNewLine (table);
1497199c84cdSHadriel Kaplan 		colprintLineAppendColumnVString (line, stringListItem (Excluded, i));
1498199c84cdSHadriel Kaplan 	}
1499199c84cdSHadriel Kaplan 
1500199c84cdSHadriel Kaplan 	colprintTableSort (table, excludesCompare);
1501199c84cdSHadriel Kaplan 	colprintTablePrint (table, 0, localOption.withListHeader, localOption.machinable, stdout);
1502199c84cdSHadriel Kaplan 	colprintTableDelete (table);
1503199c84cdSHadriel Kaplan 
1504199c84cdSHadriel Kaplan 	if (i == 0)
1505199c84cdSHadriel Kaplan 		putchar ('\n');
1506199c84cdSHadriel Kaplan 
1507199c84cdSHadriel Kaplan 	exit (0);
1508199c84cdSHadriel Kaplan }
1509199c84cdSHadriel Kaplan 
1510199c84cdSHadriel Kaplan 
printFeatureList(void)1511d4c6f1e6SMasatake YAMATO static void printFeatureList (void)
1512d4c6f1e6SMasatake YAMATO {
1513d4c6f1e6SMasatake YAMATO 	int i;
1514d4c6f1e6SMasatake YAMATO 
15155352f0a5SMasatake YAMATO 	for (i = 0 ; Features [i].name != NULL ; ++i)
1516d4c6f1e6SMasatake YAMATO 	{
1517d4c6f1e6SMasatake YAMATO 		if (i == 0)
1518d4c6f1e6SMasatake YAMATO 			printf ("  Optional compiled features: ");
15195352f0a5SMasatake YAMATO 		if (strcmp (Features [i].name, "regex") != 0 || checkRegex ())
15205352f0a5SMasatake YAMATO 			printf ("%s+%s", (i>0 ? ", " : ""), Features [i].name);
1521d4c6f1e6SMasatake YAMATO #ifdef CUSTOM_CONFIGURATION_FILE
15225352f0a5SMasatake YAMATO 		if (strcmp (Features [i].name, "custom-conf") == 0)
1523d4c6f1e6SMasatake YAMATO 			printf ("=%s", CUSTOM_CONFIGURATION_FILE);
1524d4c6f1e6SMasatake YAMATO #endif
1525d4c6f1e6SMasatake YAMATO 	}
1526d4c6f1e6SMasatake YAMATO 	if (i > 0)
1527d4c6f1e6SMasatake YAMATO 		putchar ('\n');
1528d4c6f1e6SMasatake YAMATO }
1529d4c6f1e6SMasatake YAMATO 
1530d4c6f1e6SMasatake YAMATO 
featureCompare(struct colprintLine * a,struct colprintLine * b)1531f9dca6f9SMasatake YAMATO static int featureCompare (struct colprintLine *a, struct colprintLine *b)
1532f9dca6f9SMasatake YAMATO {
1533f9dca6f9SMasatake YAMATO 	return strcmp (colprintLineGetColumn (a, 0),
1534f9dca6f9SMasatake YAMATO 				   colprintLineGetColumn (b, 0));
1535f9dca6f9SMasatake YAMATO }
1536f9dca6f9SMasatake YAMATO 
processListFeaturesOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)15378ccb7ee9SJiří Techet static void processListFeaturesOption(const char *const option CTAGS_ATTR_UNUSED,
15388ccb7ee9SJiří Techet 				      const char *const parameter CTAGS_ATTR_UNUSED)
1539d4c6f1e6SMasatake YAMATO {
1540d4c6f1e6SMasatake YAMATO 	int i;
1541d4c6f1e6SMasatake YAMATO 
15425352f0a5SMasatake YAMATO 	struct colprintTable *table = colprintTableNew ("L:NAME", "L:DESCRIPTION", NULL);
1543f9dca6f9SMasatake YAMATO 
15445352f0a5SMasatake YAMATO 	for (i = 0 ; Features [i].name != NULL ; ++i)
1545f9dca6f9SMasatake YAMATO 	{
1546f9dca6f9SMasatake YAMATO 		struct colprintLine * line = colprintTableGetNewLine (table);
15475352f0a5SMasatake YAMATO 		if (strcmp (Features [i].name, "regex") != 0 || checkRegex ())
15485352f0a5SMasatake YAMATO 		{
15495352f0a5SMasatake YAMATO 			colprintLineAppendColumnCString (line, Features [i].name);
15505352f0a5SMasatake YAMATO 			colprintLineAppendColumnCString (line, Features [i].description);
15515352f0a5SMasatake YAMATO 		}
1552f9dca6f9SMasatake YAMATO 
1553f9dca6f9SMasatake YAMATO 	}
1554f9dca6f9SMasatake YAMATO 
1555f9dca6f9SMasatake YAMATO 	colprintTableSort (table, featureCompare);
1556a2dce47aSMasatake YAMATO 	colprintTablePrint (table, 0, localOption.withListHeader, localOption.machinable, stdout);
1557f9dca6f9SMasatake YAMATO 	colprintTableDelete (table);
1558f9dca6f9SMasatake YAMATO 
1559d4c6f1e6SMasatake YAMATO 	if (i == 0)
1560d4c6f1e6SMasatake YAMATO 		putchar ('\n');
1561d4c6f1e6SMasatake YAMATO 	exit (0);
1562d4c6f1e6SMasatake YAMATO }
1563d4c6f1e6SMasatake YAMATO 
processListFieldsOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)15648ccb7ee9SJiří Techet static void processListFieldsOption(const char *const option CTAGS_ATTR_UNUSED,
156500b5a923SMasatake YAMATO 				    const char *const parameter)
15662894800fSMasatake YAMATO {
1567267776cbSMasatake YAMATO 	/* Before listing, adjust states of enabled/disabled for fixed fields. */
1568267776cbSMasatake YAMATO 	writerCheckOptions (Option.fieldsReset);
1569267776cbSMasatake YAMATO 
1570aa9256e3SMasatake YAMATO 	struct colprintTable * table = fieldColprintTableNew ();
1571aa9256e3SMasatake YAMATO 
1572484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
157300b5a923SMasatake YAMATO 	{
1574aa9256e3SMasatake YAMATO 		fieldColprintAddCommonLines (table);
1575aa9256e3SMasatake YAMATO 
15765a26e8b2SMasatake YAMATO 		initializeParser (LANG_AUTO);
1577aa9256e3SMasatake YAMATO 		for (unsigned int i = 0; i < countParsers (); i++)
1578aa9256e3SMasatake YAMATO 		{
1579aa9256e3SMasatake YAMATO 			if (isLanguageVisible(i))
1580aa9256e3SMasatake YAMATO 				fieldColprintAddLanguageLines (table, i);
1581aa9256e3SMasatake YAMATO 		}
158200b5a923SMasatake YAMATO 	}
158300b5a923SMasatake YAMATO 	else
158400b5a923SMasatake YAMATO 	{
158500b5a923SMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
158600b5a923SMasatake YAMATO 		if (language == LANG_IGNORE)
158700b5a923SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
1588aa9256e3SMasatake YAMATO 
158900b5a923SMasatake YAMATO 		initializeParser (language);
1590aa9256e3SMasatake YAMATO 		fieldColprintAddLanguageLines (table, language);
159100b5a923SMasatake YAMATO 	}
159200b5a923SMasatake YAMATO 
1593a2dce47aSMasatake YAMATO 	fieldColprintTablePrint (table, localOption.withListHeader, localOption.machinable, stdout);
1594aa9256e3SMasatake YAMATO 	colprintTableDelete (table);
15952894800fSMasatake YAMATO 	exit (0);
15962894800fSMasatake YAMATO }
15972894800fSMasatake YAMATO 
printProgramIdentification(void)1598d4c6f1e6SMasatake YAMATO static void printProgramIdentification (void)
1599d4c6f1e6SMasatake YAMATO {
16004490475dSMasatake YAMATO 	if ((ctags_repoinfo == NULL)
16014490475dSMasatake YAMATO 	    || (strcmp (ctags_repoinfo, PROGRAM_VERSION) == 0))
1602c409ec94SMasatake YAMATO 		printf ("%s %s, %s %s\n",
1603d4c6f1e6SMasatake YAMATO 			PROGRAM_NAME, PROGRAM_VERSION,
1604d4c6f1e6SMasatake YAMATO 			PROGRAM_COPYRIGHT, AUTHOR_NAME);
16054490475dSMasatake YAMATO 	else
16064490475dSMasatake YAMATO 		printf ("%s %s(%s), %s %s\n",
16074490475dSMasatake YAMATO 			PROGRAM_NAME, PROGRAM_VERSION, ctags_repoinfo,
16084490475dSMasatake YAMATO 			PROGRAM_COPYRIGHT, AUTHOR_NAME);
16096eacff97SMasatake YAMATO 	printf ("Universal Ctags is derived from Exuberant Ctags.\n");
16106eacff97SMasatake YAMATO 	printf ("Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert\n");
16116eacff97SMasatake YAMATO 
1612d4c6f1e6SMasatake YAMATO 	printf ("  Compiled: %s, %s\n", __DATE__, __TIME__);
16136eacff97SMasatake YAMATO 	printf ("  URL: %s\n", PROGRAM_URL);
16146eacff97SMasatake YAMATO 
1615d4c6f1e6SMasatake YAMATO 	printFeatureList ();
1616d4c6f1e6SMasatake YAMATO }
1617d4c6f1e6SMasatake YAMATO 
processHelpOptionCommon(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED,bool includingExperimentalOptions)161807b943caSMasatake YAMATO static void processHelpOptionCommon (
16198ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
162007b943caSMasatake YAMATO 		const char *const parameter CTAGS_ATTR_UNUSED,
162107b943caSMasatake YAMATO 		bool includingExperimentalOptions)
1622d4c6f1e6SMasatake YAMATO {
1623d4c6f1e6SMasatake YAMATO 	printProgramIdentification ();
1624d4c6f1e6SMasatake YAMATO 	putchar ('\n');
1625d4c6f1e6SMasatake YAMATO 	printInvocationDescription ();
1626d4c6f1e6SMasatake YAMATO 	putchar ('\n');
162724dce10bSHiroo HAYASHI 
162824dce10bSHiroo HAYASHI 	int i;
162924dce10bSHiroo HAYASHI 	for (i = 0 ; LongOptionDescription [i].description != NULL ; ++i)
163024dce10bSHiroo HAYASHI 	{
163124dce10bSHiroo HAYASHI 		if ((! Option.etags || LongOptionDescription [i].usedByEtags)
163224dce10bSHiroo HAYASHI 			&& (! LongOptionDescription [i].experimentalOption || includingExperimentalOptions))
163324dce10bSHiroo HAYASHI 			puts (LongOptionDescription [i].description);
163424dce10bSHiroo HAYASHI 	}
163507b943caSMasatake YAMATO }
163607b943caSMasatake YAMATO 
processHelpOption(const char * const option,const char * const parameter)163707b943caSMasatake YAMATO static void processHelpOption (
163807b943caSMasatake YAMATO 		const char *const option,
163907b943caSMasatake YAMATO 		const char *const parameter)
164007b943caSMasatake YAMATO {
164107b943caSMasatake YAMATO 	processHelpOptionCommon (option, parameter, false);
164207b943caSMasatake YAMATO 	exit (0);
164307b943caSMasatake YAMATO }
164407b943caSMasatake YAMATO 
processHelpFullOption(const char * const option,const char * const parameter)164507b943caSMasatake YAMATO static void processHelpFullOption (
164607b943caSMasatake YAMATO 		const char *const option,
164707b943caSMasatake YAMATO 		const char *const parameter)
164807b943caSMasatake YAMATO {
164907b943caSMasatake YAMATO 	processHelpOptionCommon (option, parameter, true);
1650d4c6f1e6SMasatake YAMATO 	exit (0);
1651d4c6f1e6SMasatake YAMATO }
1652d4c6f1e6SMasatake YAMATO 
16532050d074SAman Gupta #ifdef HAVE_JANSSON
processInteractiveOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)16542050d074SAman Gupta static void processInteractiveOption (
16552050d074SAman Gupta 		const char *const option CTAGS_ATTR_UNUSED,
1656c59f2a21SMasatake YAMATO 		const char *const parameter)
16572050d074SAman Gupta {
1658c59f2a21SMasatake YAMATO 	static struct interactiveModeArgs args;
1659c59f2a21SMasatake YAMATO 
1660c59f2a21SMasatake YAMATO 
1661c59f2a21SMasatake YAMATO 	if (parameter && (strcmp (parameter, "sandbox") == 0))
1662201e5e77SMasatake YAMATO 	{
1663201e5e77SMasatake YAMATO 		Option.interactive = INTERACTIVE_SANDBOX;
1664c59f2a21SMasatake YAMATO 		args.sandbox = true;
1665201e5e77SMasatake YAMATO 	}
1666c59f2a21SMasatake YAMATO 	else if (parameter && (strcmp (parameter, "default") == 0))
1667201e5e77SMasatake YAMATO 	{
1668201e5e77SMasatake YAMATO 		Option.interactive = INTERACTIVE_DEFAULT;
1669c59f2a21SMasatake YAMATO 		args.sandbox = false;
1670201e5e77SMasatake YAMATO 	}
1671c59f2a21SMasatake YAMATO 	else if ((!parameter) || *parameter == '\0')
1672201e5e77SMasatake YAMATO 	{
1673201e5e77SMasatake YAMATO 		Option.interactive = INTERACTIVE_DEFAULT;
1674c59f2a21SMasatake YAMATO 		args.sandbox = false;
1675201e5e77SMasatake YAMATO 	}
1676c59f2a21SMasatake YAMATO 	else
1677c59f2a21SMasatake YAMATO 		error (FATAL, "Unknown option argument \"%s\" for --%s option",
1678c59f2a21SMasatake YAMATO 			   parameter, option);
1679c59f2a21SMasatake YAMATO 
1680a4600366SMasatake YAMATO #ifndef HAVE_SECCOMP
1681a4600366SMasatake YAMATO 	if (args.sandbox)
1682a4600366SMasatake YAMATO 		error (FATAL, "sandbox submode is not supported on this platform");
1683a4600366SMasatake YAMATO #endif
1684a4600366SMasatake YAMATO 
1685a4600366SMasatake YAMATO #ifdef ENABLE_GCOV
1686a4600366SMasatake YAMATO 	if (args.sandbox)
1687a4600366SMasatake YAMATO 		error (FATAL, "sandbox submode does not work if gcov is instrumented");
1688a4600366SMasatake YAMATO #endif
1689a4600366SMasatake YAMATO 
16902050d074SAman Gupta 	Option.sorted = SO_UNSORTED;
1691c59f2a21SMasatake YAMATO 	setMainLoop (interactiveLoop, &args);
16922050d074SAman Gupta 	setErrorPrinter (jsonErrorPrinter, NULL);
1693d7738cbeSMasatake YAMATO 	setTagWriter (WRITER_JSON, NULL);
16942050d074SAman Gupta 	enablePtag (PTAG_JSON_OUTPUT_VERSION, true);
1695ecff6b07SMasatake YAMATO 
1696ecff6b07SMasatake YAMATO 	json_set_alloc_funcs (eMalloc, eFree);
16972050d074SAman Gupta }
16982050d074SAman Gupta #endif
16992050d074SAman Gupta 
processIf0Option(const char * const option,const char * const parameter)1700bdd29018SMasatake YAMATO static void processIf0Option (const char *const option,
1701bdd29018SMasatake YAMATO 							  const char *const parameter)
1702bdd29018SMasatake YAMATO {
1703bdd29018SMasatake YAMATO 	bool if0 = getBooleanOption (option, parameter);
1704bdd29018SMasatake YAMATO 	langType lang = getNamedLanguage ("CPreProcessor", 0);
1705bdd29018SMasatake YAMATO 	const char *arg = if0? "true": "false";
1706bdd29018SMasatake YAMATO 
1707bdd29018SMasatake YAMATO 	applyParameter (lang, "if0", arg);
1708bdd29018SMasatake YAMATO }
1709bdd29018SMasatake YAMATO 
processLanguageForceOption(const char * const option,const char * const parameter)1710d4c6f1e6SMasatake YAMATO static void processLanguageForceOption (
1711d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1712d4c6f1e6SMasatake YAMATO {
1713d4c6f1e6SMasatake YAMATO 	langType language;
1714484c7531SMasatake YAMATO 	if (strcasecmp (parameter, RSV_LANG_AUTO) == 0)
1715d4c6f1e6SMasatake YAMATO 		language = LANG_AUTO;
1716d4c6f1e6SMasatake YAMATO 	else
17175a55f03bSMasatake YAMATO 		language = getNamedLanguage (parameter, 0);
1718d4c6f1e6SMasatake YAMATO 
1719d4c6f1e6SMasatake YAMATO 	if (strcmp (option, "lang") == 0  ||  strcmp (option, "language") == 0)
1720d4c6f1e6SMasatake YAMATO 		error (WARNING,
1721d4c6f1e6SMasatake YAMATO 			   "\"--%s\" option is obsolete; use \"--language-force\" instead",
1722d4c6f1e6SMasatake YAMATO 			   option);
1723d4c6f1e6SMasatake YAMATO 	if (language == LANG_IGNORE)
1724d4c6f1e6SMasatake YAMATO 		error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
1725d4c6f1e6SMasatake YAMATO 	else
1726d4c6f1e6SMasatake YAMATO 		Option.language = language;
1727d4c6f1e6SMasatake YAMATO }
skipPastMap(char * p)1728d4c6f1e6SMasatake YAMATO static char* skipPastMap (char* p)
1729d4c6f1e6SMasatake YAMATO {
1730d4c6f1e6SMasatake YAMATO 	while (*p != EXTENSION_SEPARATOR  &&
1731d4c6f1e6SMasatake YAMATO 			*p != PATTERN_START  &&  *p != ','  &&  *p != '\0')
1732d4c6f1e6SMasatake YAMATO 		++p;
1733d4c6f1e6SMasatake YAMATO 	return p;
1734d4c6f1e6SMasatake YAMATO }
1735d4c6f1e6SMasatake YAMATO 
1736d4c6f1e6SMasatake YAMATO /* Parses the mapping beginning at `map', adds it to the language map, and
1737d4c6f1e6SMasatake YAMATO  * returns first character past the map.
1738d4c6f1e6SMasatake YAMATO  */
extractMapFromParameter(const langType language,char * parameter,char ** tail,bool * pattern_p,char * (* skip)(char *))1739d4c6f1e6SMasatake YAMATO static char* extractMapFromParameter (const langType language,
1740d4c6f1e6SMasatake YAMATO 				      char* parameter,
1741d4c6f1e6SMasatake YAMATO 				      char** tail,
1742ce990805SThomas Braun 				      bool* pattern_p,
1743d4c6f1e6SMasatake YAMATO 				      char* (* skip) (char *))
1744d4c6f1e6SMasatake YAMATO {
1745d4c6f1e6SMasatake YAMATO 	char* p = NULL;
1746d4c6f1e6SMasatake YAMATO 	const char first = *parameter;
1747d4c6f1e6SMasatake YAMATO 	char  tmp;
1748d4c6f1e6SMasatake YAMATO 	char* result;
1749d4c6f1e6SMasatake YAMATO 
1750d4c6f1e6SMasatake YAMATO 	if (first == EXTENSION_SEPARATOR)  /* extension map */
1751d4c6f1e6SMasatake YAMATO 	{
1752ce990805SThomas Braun 		*pattern_p = false;
1753d4c6f1e6SMasatake YAMATO 
1754d4c6f1e6SMasatake YAMATO 		++parameter;
1755d4c6f1e6SMasatake YAMATO 		p = (* skip) (parameter);
1756d4c6f1e6SMasatake YAMATO 		if (*p == '\0')
1757d4c6f1e6SMasatake YAMATO 		{
1758d4c6f1e6SMasatake YAMATO 			result = eStrdup (parameter);
1759d4c6f1e6SMasatake YAMATO 			*tail = parameter + strlen (parameter);
1760d4c6f1e6SMasatake YAMATO 			return result;
1761d4c6f1e6SMasatake YAMATO 		}
1762d4c6f1e6SMasatake YAMATO 		else
1763d4c6f1e6SMasatake YAMATO 		{
1764d4c6f1e6SMasatake YAMATO 			tmp = *p;
1765d4c6f1e6SMasatake YAMATO 			*p = '\0';
1766d4c6f1e6SMasatake YAMATO 			result = eStrdup (parameter);
1767d4c6f1e6SMasatake YAMATO 			*p = tmp;
1768d4c6f1e6SMasatake YAMATO 			*tail = p;
1769d4c6f1e6SMasatake YAMATO 			return result;
1770d4c6f1e6SMasatake YAMATO 		}
1771d4c6f1e6SMasatake YAMATO 	}
1772d4c6f1e6SMasatake YAMATO 	else if (first == PATTERN_START)  /* pattern map */
1773d4c6f1e6SMasatake YAMATO 	{
1774ce990805SThomas Braun 		*pattern_p = true;
1775d4c6f1e6SMasatake YAMATO 
1776d4c6f1e6SMasatake YAMATO 		++parameter;
1777d4c6f1e6SMasatake YAMATO 		for (p = parameter  ;  *p != PATTERN_STOP  &&  *p != '\0'  ;  ++p)
1778d4c6f1e6SMasatake YAMATO 		{
1779d4c6f1e6SMasatake YAMATO 			if (*p == '\\'  &&  *(p + 1) == PATTERN_STOP)
1780d4c6f1e6SMasatake YAMATO 				++p;
1781d4c6f1e6SMasatake YAMATO 		}
1782d4c6f1e6SMasatake YAMATO 		if (*p == '\0')
1783d4c6f1e6SMasatake YAMATO 			error (FATAL, "Unterminated file name pattern for %s language",
1784d4c6f1e6SMasatake YAMATO 			   getLanguageName (language));
1785d4c6f1e6SMasatake YAMATO 		else
1786d4c6f1e6SMasatake YAMATO 		{
1787d4c6f1e6SMasatake YAMATO 			tmp = *p;
1788d4c6f1e6SMasatake YAMATO 			*p = '\0';
1789d4c6f1e6SMasatake YAMATO 			result = eStrdup (parameter);
1790d4c6f1e6SMasatake YAMATO 			*p = tmp;
1791d4c6f1e6SMasatake YAMATO 			*tail = p + 1;
1792d4c6f1e6SMasatake YAMATO 			return result;
1793d4c6f1e6SMasatake YAMATO 		}
1794d4c6f1e6SMasatake YAMATO 	}
1795d4c6f1e6SMasatake YAMATO 
1796d4c6f1e6SMasatake YAMATO 	return NULL;
1797d4c6f1e6SMasatake YAMATO }
1798d4c6f1e6SMasatake YAMATO 
addLanguageMap(const langType language,char * map_parameter,bool exclusiveInAllLanguages)1799d932931fSMasatake YAMATO static char* addLanguageMap (const langType language, char* map_parameter,
1800ce990805SThomas Braun 			     bool exclusiveInAllLanguages)
1801d4c6f1e6SMasatake YAMATO {
1802d4c6f1e6SMasatake YAMATO 	char* p = NULL;
1803ce990805SThomas Braun 	bool pattern_p;
1804d4c6f1e6SMasatake YAMATO 	char* map;
1805d4c6f1e6SMasatake YAMATO 
1806d4c6f1e6SMasatake YAMATO 	map = extractMapFromParameter (language, map_parameter, &p, &pattern_p, skipPastMap);
1807ce990805SThomas Braun 	if (map && pattern_p == false)
1808d932931fSMasatake YAMATO 		addLanguageExtensionMap (language, map, exclusiveInAllLanguages);
1809ce990805SThomas Braun 	else if (map && pattern_p == true)
1810d932931fSMasatake YAMATO 		addLanguagePatternMap (language, map, exclusiveInAllLanguages);
1811d4c6f1e6SMasatake YAMATO 	else
1812d4c6f1e6SMasatake YAMATO 		error (FATAL, "Badly formed language map for %s language",
1813d4c6f1e6SMasatake YAMATO 				getLanguageName (language));
1814d4c6f1e6SMasatake YAMATO 
1815d4c6f1e6SMasatake YAMATO 	if (map)
1816d4c6f1e6SMasatake YAMATO 		eFree (map);
1817d4c6f1e6SMasatake YAMATO 	return p;
1818d4c6f1e6SMasatake YAMATO }
1819d4c6f1e6SMasatake YAMATO 
removeLanguageMap(const langType language,char * map_parameter)1820086a0fd9SMasatake YAMATO static char* removeLanguageMap (const langType language, char* map_parameter)
1821086a0fd9SMasatake YAMATO {
1822086a0fd9SMasatake YAMATO 	char* p = NULL;
1823ce990805SThomas Braun 	bool pattern_p;
1824086a0fd9SMasatake YAMATO 	char* map;
1825086a0fd9SMasatake YAMATO 
1826086a0fd9SMasatake YAMATO 	map = extractMapFromParameter (language, map_parameter, &p, &pattern_p, skipPastMap);
1827ce990805SThomas Braun 	if (map && pattern_p == false)
1828086a0fd9SMasatake YAMATO 		removeLanguageExtensionMap (language, map);
1829ce990805SThomas Braun 	else if (map && pattern_p == true)
1830086a0fd9SMasatake YAMATO 		removeLanguagePatternMap (language, map);
1831086a0fd9SMasatake YAMATO 	else
1832086a0fd9SMasatake YAMATO 		error (FATAL, "Badly formed language map for %s language",
1833086a0fd9SMasatake YAMATO 		       getLanguageName (language));
1834086a0fd9SMasatake YAMATO 
1835086a0fd9SMasatake YAMATO 	if (map)
1836086a0fd9SMasatake YAMATO 		eFree (map);
1837086a0fd9SMasatake YAMATO 	return p;
1838086a0fd9SMasatake YAMATO }
1839086a0fd9SMasatake YAMATO 
processLanguageMap(char * map)1840d4c6f1e6SMasatake YAMATO static char* processLanguageMap (char* map)
1841d4c6f1e6SMasatake YAMATO {
1842d4c6f1e6SMasatake YAMATO 	char* const separator = strchr (map, ':');
1843d4c6f1e6SMasatake YAMATO 	char* result = NULL;
1844d4c6f1e6SMasatake YAMATO 	if (separator != NULL)
1845d4c6f1e6SMasatake YAMATO 	{
1846d4c6f1e6SMasatake YAMATO 		langType language;
1847d4c6f1e6SMasatake YAMATO 		char *list = separator + 1;
1848ce990805SThomas Braun 		bool clear = false;
1849d4c6f1e6SMasatake YAMATO 		*separator = '\0';
18505a55f03bSMasatake YAMATO 		language = getNamedLanguage (map, 0);
1851d4c6f1e6SMasatake YAMATO 		if (language != LANG_IGNORE)
1852d4c6f1e6SMasatake YAMATO 		{
1853484c7531SMasatake YAMATO 			const char *const deflt = RSV_LANGMAP_DEFAULT;
1854d4c6f1e6SMasatake YAMATO 			char* p;
1855d4c6f1e6SMasatake YAMATO 			if (*list == '+')
1856d4c6f1e6SMasatake YAMATO 				++list;
1857d4c6f1e6SMasatake YAMATO 			else
1858ce990805SThomas Braun 				clear = true;
1859d4c6f1e6SMasatake YAMATO 			for (p = list  ;  *p != ','  &&  *p != '\0'  ;  ++p)  /*no-op*/ ;
1860d4c6f1e6SMasatake YAMATO 			if ((size_t) (p - list) == strlen (deflt) &&
1861d4c6f1e6SMasatake YAMATO 				strncasecmp (list, deflt, p - list) == 0)
1862d4c6f1e6SMasatake YAMATO 			{
1863d4c6f1e6SMasatake YAMATO 				verbose ("    Restoring default %s language map: ", getLanguageName (language));
1864d4c6f1e6SMasatake YAMATO 				installLanguageMapDefault (language);
1865d4c6f1e6SMasatake YAMATO 				list = p;
1866d4c6f1e6SMasatake YAMATO 			}
1867d4c6f1e6SMasatake YAMATO 			else
1868d4c6f1e6SMasatake YAMATO 			{
1869d4c6f1e6SMasatake YAMATO 				if (clear)
1870d4c6f1e6SMasatake YAMATO 				{
1871d4c6f1e6SMasatake YAMATO 					verbose ("    Setting %s language map:", getLanguageName (language));
1872d4c6f1e6SMasatake YAMATO 					clearLanguageMap (language);
1873d4c6f1e6SMasatake YAMATO 				}
1874d4c6f1e6SMasatake YAMATO 				else
1875d4c6f1e6SMasatake YAMATO 					verbose ("    Adding to %s language map:", getLanguageName (language));
1876d4c6f1e6SMasatake YAMATO 				while (list != NULL  &&  *list != '\0'  &&  *list != ',')
1877ce990805SThomas Braun 					list = addLanguageMap (language, list, true);
1878d4c6f1e6SMasatake YAMATO 				verbose ("\n");
1879d4c6f1e6SMasatake YAMATO 			}
1880d4c6f1e6SMasatake YAMATO 			if (list != NULL  &&  *list == ',')
1881d4c6f1e6SMasatake YAMATO 				++list;
1882d4c6f1e6SMasatake YAMATO 			result = list;
1883d4c6f1e6SMasatake YAMATO 		}
1884d4c6f1e6SMasatake YAMATO 	}
1885d4c6f1e6SMasatake YAMATO 	return result;
1886d4c6f1e6SMasatake YAMATO }
1887d4c6f1e6SMasatake YAMATO 
processLanguageMapOption(const char * const option,const char * const parameter)1888d4c6f1e6SMasatake YAMATO static void processLanguageMapOption (
1889d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1890d4c6f1e6SMasatake YAMATO {
1891d4c6f1e6SMasatake YAMATO 	char *const maps = eStrdup (parameter);
1892d4c6f1e6SMasatake YAMATO 	char *map = maps;
1893d4c6f1e6SMasatake YAMATO 
1894484c7531SMasatake YAMATO 	if (strcmp (parameter, RSV_LANGMAP_DEFAULT) == 0)
1895d4c6f1e6SMasatake YAMATO 	{
1896d4c6f1e6SMasatake YAMATO 		verbose ("    Restoring default language maps:\n");
1897d4c6f1e6SMasatake YAMATO 		installLanguageMapDefaults ();
1898d4c6f1e6SMasatake YAMATO 	}
1899d4c6f1e6SMasatake YAMATO 	else while (map != NULL  &&  *map != '\0')
1900d4c6f1e6SMasatake YAMATO 	{
1901d4c6f1e6SMasatake YAMATO 		char* const next = processLanguageMap (map);
1902d4c6f1e6SMasatake YAMATO 		if (next == NULL)
1903d4c6f1e6SMasatake YAMATO 			error (WARNING, "Unknown language \"%s\" in \"%s\" option", parameter, option);
1904d4c6f1e6SMasatake YAMATO 		map = next;
1905d4c6f1e6SMasatake YAMATO 	}
1906d4c6f1e6SMasatake YAMATO 	eFree (maps);
1907d4c6f1e6SMasatake YAMATO }
1908d4c6f1e6SMasatake YAMATO 
processLanguagesOption(const char * const option,const char * const parameter)1909d4c6f1e6SMasatake YAMATO static void processLanguagesOption (
1910d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
1911d4c6f1e6SMasatake YAMATO {
1912d4c6f1e6SMasatake YAMATO 	char *const langs = eStrdup (parameter);
1913d4c6f1e6SMasatake YAMATO 	enum { Add, Remove, Replace } mode = Replace;
1914ce990805SThomas Braun 	bool first = true;
1915d4c6f1e6SMasatake YAMATO 	char *lang = langs;
1916d4c6f1e6SMasatake YAMATO 	const char* prefix = "";
1917d4c6f1e6SMasatake YAMATO 	verbose ("    Enabled languages: ");
1918d4c6f1e6SMasatake YAMATO 	while (lang != NULL)
1919d4c6f1e6SMasatake YAMATO 	{
1920d4c6f1e6SMasatake YAMATO 		char *const end = strchr (lang, ',');
1921d4c6f1e6SMasatake YAMATO 		if (lang [0] == '+')
1922d4c6f1e6SMasatake YAMATO 		{
1923d4c6f1e6SMasatake YAMATO 			++lang;
1924d4c6f1e6SMasatake YAMATO 			mode = Add;
1925d4c6f1e6SMasatake YAMATO 			prefix = "+ ";
1926d4c6f1e6SMasatake YAMATO 		}
1927d4c6f1e6SMasatake YAMATO 		else if (lang [0] == '-')
1928d4c6f1e6SMasatake YAMATO 		{
1929d4c6f1e6SMasatake YAMATO 			++lang;
1930d4c6f1e6SMasatake YAMATO 			mode = Remove;
1931d4c6f1e6SMasatake YAMATO 			prefix = "- ";
1932d4c6f1e6SMasatake YAMATO 		}
1933d4c6f1e6SMasatake YAMATO 		if (mode == Replace)
1934ce990805SThomas Braun 			enableLanguages (false);
1935d4c6f1e6SMasatake YAMATO 		if (end != NULL)
1936d4c6f1e6SMasatake YAMATO 			*end = '\0';
1937d4c6f1e6SMasatake YAMATO 		if (lang [0] != '\0')
1938d4c6f1e6SMasatake YAMATO 		{
1939484c7531SMasatake YAMATO 			if (strcmp (lang, RSV_LANG_ALL) == 0)
1940ce990805SThomas Braun 				enableLanguages ((bool) (mode != Remove));
1941d4c6f1e6SMasatake YAMATO 			else
1942d4c6f1e6SMasatake YAMATO 			{
19435a55f03bSMasatake YAMATO 				const langType language = getNamedLanguage (lang, 0);
1944d4c6f1e6SMasatake YAMATO 				if (language == LANG_IGNORE)
1945d4c6f1e6SMasatake YAMATO 					error (WARNING, "Unknown language \"%s\" in \"%s\" option", lang, option);
1946d4c6f1e6SMasatake YAMATO 				else
1947ce990805SThomas Braun 					enableLanguage (language, (bool) (mode != Remove));
1948d4c6f1e6SMasatake YAMATO 			}
1949d4c6f1e6SMasatake YAMATO 			verbose ("%s%s%s", (first ? "" : ", "), prefix, lang);
1950d4c6f1e6SMasatake YAMATO 			prefix = "";
1951ce990805SThomas Braun 			first = false;
1952d4c6f1e6SMasatake YAMATO 			if (mode == Replace)
1953d4c6f1e6SMasatake YAMATO 				mode = Add;
1954d4c6f1e6SMasatake YAMATO 		}
1955d4c6f1e6SMasatake YAMATO 		lang = (end != NULL ? end + 1 : NULL);
1956d4c6f1e6SMasatake YAMATO 	}
1957d4c6f1e6SMasatake YAMATO 	verbose ("\n");
1958d4c6f1e6SMasatake YAMATO 	eFree (langs);
1959d4c6f1e6SMasatake YAMATO }
1960d4c6f1e6SMasatake YAMATO 
processMapOption(const char * const option,const char * const parameter)1961ce990805SThomas Braun extern bool processMapOption (
1962d4c6f1e6SMasatake YAMATO 			const char *const option, const char *const parameter)
1963d4c6f1e6SMasatake YAMATO {
1964d4c6f1e6SMasatake YAMATO 	langType language;
1965d4c6f1e6SMasatake YAMATO 	const char* spec;
1966d4c6f1e6SMasatake YAMATO 	char* map_parameter;
1967ce990805SThomas Braun 	bool clear = false;
1968086a0fd9SMasatake YAMATO 	char op;
1969d4c6f1e6SMasatake YAMATO 
1970d4ee22f1SMasatake YAMATO 	language = getLanguageComponentInOption (option, "map-");
1971d4c6f1e6SMasatake YAMATO 	if (language == LANG_IGNORE)
1972ce990805SThomas Braun 		return false;
1973d4c6f1e6SMasatake YAMATO 
1974d4c6f1e6SMasatake YAMATO 	if (parameter == NULL || parameter [0] == '\0')
1975d4c6f1e6SMasatake YAMATO 		error (FATAL, "no parameter is given for %s", option);
1976d4c6f1e6SMasatake YAMATO 
1977d4c6f1e6SMasatake YAMATO 	spec = parameter;
1978086a0fd9SMasatake YAMATO 	if (*spec == '+' || *spec == '-')
1979086a0fd9SMasatake YAMATO 	{
1980086a0fd9SMasatake YAMATO 		op = *spec;
1981d4c6f1e6SMasatake YAMATO 		spec++;
1982086a0fd9SMasatake YAMATO 	}
1983d4c6f1e6SMasatake YAMATO 	else
1984086a0fd9SMasatake YAMATO 	{
1985086a0fd9SMasatake YAMATO 		op = '\0';
1986ce990805SThomas Braun 		clear = true;
1987086a0fd9SMasatake YAMATO 	}
1988d4c6f1e6SMasatake YAMATO 
1989d4c6f1e6SMasatake YAMATO 	if (clear)
1990d4c6f1e6SMasatake YAMATO 	{
1991d4c6f1e6SMasatake YAMATO 		verbose ("    Setting %s language map:", getLanguageName (language));
1992d4c6f1e6SMasatake YAMATO 		clearLanguageMap (language);
1993086a0fd9SMasatake YAMATO 		op = '+';
1994d4c6f1e6SMasatake YAMATO 	}
1995d4c6f1e6SMasatake YAMATO 	else
1996086a0fd9SMasatake YAMATO 		verbose ("    %s %s %s %s language map:",
1997086a0fd9SMasatake YAMATO 			 op == '+'? "Adding": "Removing",
1998086a0fd9SMasatake YAMATO 			 spec,
1999086a0fd9SMasatake YAMATO 			 op == '+'? "to": "from",
2000086a0fd9SMasatake YAMATO 			 getLanguageName (language));
2001d4c6f1e6SMasatake YAMATO 	map_parameter = eStrdup (spec);
2002086a0fd9SMasatake YAMATO 
2003086a0fd9SMasatake YAMATO 	if (op == '+')
2004ce990805SThomas Braun 		addLanguageMap (language, map_parameter, false);
2005086a0fd9SMasatake YAMATO 	else if (op == '-')
2006086a0fd9SMasatake YAMATO 		removeLanguageMap (language, map_parameter);
2007086a0fd9SMasatake YAMATO 	else
2008086a0fd9SMasatake YAMATO 		Assert ("Should not reach here" == NULL);
2009086a0fd9SMasatake YAMATO 
2010d4c6f1e6SMasatake YAMATO 	eFree (map_parameter);
2011d4c6f1e6SMasatake YAMATO 	verbose ("\n");
2012d4c6f1e6SMasatake YAMATO 
2013ce990805SThomas Braun 	return true;
2014d4c6f1e6SMasatake YAMATO }
2015d4c6f1e6SMasatake YAMATO 
processParamOption(const char * const option,const char * const value)20164d6cdcecSMasatake YAMATO extern bool processParamOption (
20174d6cdcecSMasatake YAMATO 			const char *const option, const char *const value)
20184d6cdcecSMasatake YAMATO {
20194d6cdcecSMasatake YAMATO 	langType language;
202028d0ff03SMasatake YAMATO 	const char* name;
20214d6cdcecSMasatake YAMATO 	const char* sep;
20224d6cdcecSMasatake YAMATO 
20234d6cdcecSMasatake YAMATO 	language = getLanguageComponentInOption (option, "param-");
20244d6cdcecSMasatake YAMATO 	if (language == LANG_IGNORE)
20254d6cdcecSMasatake YAMATO 		return false;
20264d6cdcecSMasatake YAMATO 
202728d0ff03SMasatake YAMATO 	sep = option + strlen ("param-") + strlen (getLanguageName (language));
20288a87cfffSMasatake YAMATO 	/* `:' is only for keeping self compatibility */
20298a87cfffSMasatake YAMATO 	if (! (*sep == '.' || *sep == ':' ))
20308a87cfffSMasatake YAMATO 		error (FATAL, "no separator(.) is given for %s=%s", option, value);
203128d0ff03SMasatake YAMATO 	name = sep + 1;
203228d0ff03SMasatake YAMATO 
20334d6cdcecSMasatake YAMATO 	if (value == NULL || value [0] == '\0')
203498400563SMasatake YAMATO 		error (FATAL, "no value is given for %s", option);
20354d6cdcecSMasatake YAMATO 
203628d0ff03SMasatake YAMATO 	applyParameter (language, name, value);
20374d6cdcecSMasatake YAMATO 
20384d6cdcecSMasatake YAMATO 	return true;
20394d6cdcecSMasatake YAMATO }
20404d6cdcecSMasatake YAMATO 
processLicenseOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2041d4c6f1e6SMasatake YAMATO static void processLicenseOption (
20428ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
20438ccb7ee9SJiří Techet 		const char *const parameter CTAGS_ATTR_UNUSED)
2044d4c6f1e6SMasatake YAMATO {
2045d4c6f1e6SMasatake YAMATO 	printProgramIdentification ();
2046d4c6f1e6SMasatake YAMATO 	puts ("");
2047d4c6f1e6SMasatake YAMATO 	puts (License1);
2048d4c6f1e6SMasatake YAMATO 	puts (License2);
2049d4c6f1e6SMasatake YAMATO 	exit (0);
2050d4c6f1e6SMasatake YAMATO }
2051d4c6f1e6SMasatake YAMATO 
processListAliasesOption(const char * const option,const char * const parameter)2052d4c6f1e6SMasatake YAMATO static void processListAliasesOption (
2053d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2054d4c6f1e6SMasatake YAMATO {
2055484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
205645425726SMasatake YAMATO 		printLanguageAliases (LANG_AUTO,
205745425726SMasatake YAMATO 							  localOption.withListHeader, localOption.machinable, stdout);
2058d4c6f1e6SMasatake YAMATO 	else
2059d4c6f1e6SMasatake YAMATO 	{
20605a55f03bSMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
2061d4c6f1e6SMasatake YAMATO 		if (language == LANG_IGNORE)
2062d4c6f1e6SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
2063d4c6f1e6SMasatake YAMATO 		else
206445425726SMasatake YAMATO 			printLanguageAliases (language,
206545425726SMasatake YAMATO 								  localOption.withListHeader, localOption.machinable, stdout);
2066d4c6f1e6SMasatake YAMATO 	}
2067d4c6f1e6SMasatake YAMATO 	exit (0);
2068d4c6f1e6SMasatake YAMATO }
2069d4c6f1e6SMasatake YAMATO 
processListExtrasOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2070d76bc950SMasatake YAMATO static void processListExtrasOption (
20718ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED, const char *const parameter CTAGS_ATTR_UNUSED)
2072dab9500fSMasatake YAMATO {
2073ecb981e8SMasatake YAMATO 	struct colprintTable * table = xtagColprintTableNew ();
2074ecb981e8SMasatake YAMATO 
2075484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
20768643c5b5SMasatake YAMATO 	{
2077ecb981e8SMasatake YAMATO 		xtagColprintAddCommonLines (table);
2078ecb981e8SMasatake YAMATO 
20798643c5b5SMasatake YAMATO 		initializeParser (LANG_AUTO);
2080ecb981e8SMasatake YAMATO 		for (unsigned int i = 0; i < countParsers (); i++)
2081ecb981e8SMasatake YAMATO 		{
2082ecb981e8SMasatake YAMATO 			if (isLanguageVisible(i))
2083ecb981e8SMasatake YAMATO 				xtagColprintAddLanguageLines (table, i);
2084ecb981e8SMasatake YAMATO 		}
20858643c5b5SMasatake YAMATO 	}
20868643c5b5SMasatake YAMATO 	else
20878643c5b5SMasatake YAMATO 	{
20888643c5b5SMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
20898643c5b5SMasatake YAMATO 		if (language == LANG_IGNORE)
20908643c5b5SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
2091ecb981e8SMasatake YAMATO 
20928643c5b5SMasatake YAMATO 		initializeParser (language);
2093ecb981e8SMasatake YAMATO 		xtagColprintAddLanguageLines (table, language);
20948643c5b5SMasatake YAMATO 	}
20958643c5b5SMasatake YAMATO 
2096a2dce47aSMasatake YAMATO 	xtagColprintTablePrint (table, localOption.withListHeader, localOption.machinable, stdout);
2097ecb981e8SMasatake YAMATO 	colprintTableDelete (table);
2098dab9500fSMasatake YAMATO 	exit (0);
2099dab9500fSMasatake YAMATO }
2100dab9500fSMasatake YAMATO 
processListKindsOption(const char * const option,const char * const parameter)2101d4c6f1e6SMasatake YAMATO static void processListKindsOption (
2102d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2103d4c6f1e6SMasatake YAMATO {
2104ce990805SThomas Braun 	bool print_all = (strcmp (option, "list-kinds-full") == 0)? true: false;
210521d6a459SMasatake YAMATO 
2106484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
2107a2dce47aSMasatake YAMATO 		printLanguageKinds (LANG_AUTO, print_all,
2108a2dce47aSMasatake YAMATO 							localOption.withListHeader, localOption.machinable, stdout);
2109d4c6f1e6SMasatake YAMATO 	else
2110d4c6f1e6SMasatake YAMATO 	{
21115a55f03bSMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
2112d4c6f1e6SMasatake YAMATO 		if (language == LANG_IGNORE)
2113d4c6f1e6SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
2114d4c6f1e6SMasatake YAMATO 		else
2115a2dce47aSMasatake YAMATO 			printLanguageKinds (language, print_all,
2116a2dce47aSMasatake YAMATO 								localOption.withListHeader, localOption.machinable, stdout);
2117d4c6f1e6SMasatake YAMATO 	}
2118d4c6f1e6SMasatake YAMATO 	exit (0);
2119d4c6f1e6SMasatake YAMATO }
2120d4c6f1e6SMasatake YAMATO 
processListParametersOption(const char * const option,const char * const parameter)21213671b1d2SMasatake YAMATO static void processListParametersOption (const char *const option,
21223671b1d2SMasatake YAMATO 										 const char *const parameter)
21233671b1d2SMasatake YAMATO {
2124484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
2125813a10c0SMasatake YAMATO 		printLanguageParameters (LANG_AUTO,
2126a2dce47aSMasatake YAMATO 								 localOption.withListHeader, localOption.machinable,
2127813a10c0SMasatake YAMATO 								 stdout);
21283671b1d2SMasatake YAMATO 	else
21293671b1d2SMasatake YAMATO 	{
21303671b1d2SMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
21313671b1d2SMasatake YAMATO 		if (language == LANG_IGNORE)
21323671b1d2SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
21333671b1d2SMasatake YAMATO 		else
2134813a10c0SMasatake YAMATO 			printLanguageParameters (language,
2135a2dce47aSMasatake YAMATO 									 localOption.withListHeader, localOption.machinable,
2136813a10c0SMasatake YAMATO 									 stdout);
21373671b1d2SMasatake YAMATO 	}
21383671b1d2SMasatake YAMATO 	exit (0);
21393671b1d2SMasatake YAMATO }
21403671b1d2SMasatake YAMATO 
21413671b1d2SMasatake YAMATO 
processListMapsOptionForType(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter,langmapType type)21428ccb7ee9SJiří Techet static void processListMapsOptionForType (const char *const option CTAGS_ATTR_UNUSED,
214359204b36SMasatake YAMATO 					  const char *const  parameter,
214459204b36SMasatake YAMATO 					  langmapType type)
2145d4c6f1e6SMasatake YAMATO {
2146484c7531SMasatake YAMATO 	if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
2147e57a5ca2SMasatake YAMATO 		printLanguageMaps (LANG_AUTO, type,
2148e57a5ca2SMasatake YAMATO 						   localOption.withListHeader, localOption.machinable,
2149e57a5ca2SMasatake YAMATO 						   stdout);
2150d4c6f1e6SMasatake YAMATO 	else
2151d4c6f1e6SMasatake YAMATO 	{
21525a55f03bSMasatake YAMATO 		langType language = getNamedLanguage (parameter, 0);
2153d4c6f1e6SMasatake YAMATO 		if (language == LANG_IGNORE)
2154d4c6f1e6SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
2155d4c6f1e6SMasatake YAMATO 		else
2156e57a5ca2SMasatake YAMATO 			printLanguageMaps (language, type,
2157e57a5ca2SMasatake YAMATO 							   localOption.withListHeader, localOption.machinable,
2158e57a5ca2SMasatake YAMATO 							   stdout);
2159d4c6f1e6SMasatake YAMATO 	}
2160d4c6f1e6SMasatake YAMATO 	exit (0);
2161d4c6f1e6SMasatake YAMATO }
2162d4c6f1e6SMasatake YAMATO 
processListMapExtensionsOption(const char * const option,const char * const parameter)21634e9ff2c1SMasatake YAMATO static void processListMapExtensionsOption (const char *const option,
216459204b36SMasatake YAMATO 					 const char *const parameter)
216559204b36SMasatake YAMATO {
2166e57a5ca2SMasatake YAMATO 	processListMapsOptionForType (option, parameter, LMAP_EXTENSION|LMAP_TABLE_OUTPUT);
216759204b36SMasatake YAMATO }
216859204b36SMasatake YAMATO 
processListMapPatternsOption(const char * const option,const char * const parameter)21694e9ff2c1SMasatake YAMATO static void processListMapPatternsOption (const char *const option,
217059204b36SMasatake YAMATO 				       const char *const parameter)
217159204b36SMasatake YAMATO {
2172e57a5ca2SMasatake YAMATO 	processListMapsOptionForType (option, parameter, LMAP_PATTERN|LMAP_TABLE_OUTPUT);
217359204b36SMasatake YAMATO }
217459204b36SMasatake YAMATO 
processListMapsOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)217559204b36SMasatake YAMATO static void processListMapsOption (
21768ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
21778ccb7ee9SJiří Techet 		const char *const parameter CTAGS_ATTR_UNUSED)
217859204b36SMasatake YAMATO {
217959204b36SMasatake YAMATO 	processListMapsOptionForType (option, parameter, LMAP_ALL);
218059204b36SMasatake YAMATO }
218159204b36SMasatake YAMATO 
processListLanguagesOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2182d4c6f1e6SMasatake YAMATO static void processListLanguagesOption (
21838ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
21848ccb7ee9SJiří Techet 		const char *const parameter CTAGS_ATTR_UNUSED)
2185d4c6f1e6SMasatake YAMATO {
2186d4c6f1e6SMasatake YAMATO 	printLanguageList ();
2187d4c6f1e6SMasatake YAMATO 	exit (0);
2188d4c6f1e6SMasatake YAMATO }
2189d4c6f1e6SMasatake YAMATO 
processListPseudoTagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2190d1c41d33SMasatake YAMATO static void processListPseudoTagsOptions (
21918ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
21928ccb7ee9SJiří Techet 		const char *const parameter CTAGS_ATTR_UNUSED)
2193d1c41d33SMasatake YAMATO {
2194a2dce47aSMasatake YAMATO 	printPtags (localOption.withListHeader, localOption.machinable, stdout);
2195d1c41d33SMasatake YAMATO 	exit (0);
2196d1c41d33SMasatake YAMATO }
2197d1c41d33SMasatake YAMATO 
processListRegexFlagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)21983fac0fc6SMasatake YAMATO static void processListRegexFlagsOptions (
21998ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
2200c30b89acSMasatake YAMATO 		const char *const parameter)
22013fac0fc6SMasatake YAMATO {
2202c30b89acSMasatake YAMATO 	printRegexFlags (localOption.withListHeader, localOption.machinable, parameter, stdout);
22033fac0fc6SMasatake YAMATO 	exit (0);
22043fac0fc6SMasatake YAMATO }
22053fac0fc6SMasatake YAMATO 
processListMultilineRegexFlagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)22069653ebd3SMasatake YAMATO static void processListMultilineRegexFlagsOptions (
22079653ebd3SMasatake YAMATO 		const char *const option CTAGS_ATTR_UNUSED,
2208c30b89acSMasatake YAMATO 		const char *const parameter)
22099653ebd3SMasatake YAMATO {
2210c30b89acSMasatake YAMATO 	printMultilineRegexFlags (localOption.withListHeader, localOption.machinable, parameter, stdout);
22119653ebd3SMasatake YAMATO 	exit (0);
22129653ebd3SMasatake YAMATO }
22139653ebd3SMasatake YAMATO 
processListMultitableRegexFlagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)2214e5f37e21SMasatake YAMATO static void processListMultitableRegexFlagsOptions (
2215e5f37e21SMasatake YAMATO 		const char *const option CTAGS_ATTR_UNUSED,
2216c30b89acSMasatake YAMATO 		const char *const parameter)
2217e5f37e21SMasatake YAMATO {
2218c30b89acSMasatake YAMATO 	printMultitableRegexFlags (localOption.withListHeader, localOption.machinable, parameter, stdout);
2219e5f37e21SMasatake YAMATO 	exit (0);
2220e5f37e21SMasatake YAMATO }
2221e5f37e21SMasatake YAMATO 
processListLangdefFlagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2222d8539e07SMasatake YAMATO static void processListLangdefFlagsOptions (
2223d8539e07SMasatake YAMATO 		const char *const option CTAGS_ATTR_UNUSED,
2224d8539e07SMasatake YAMATO 		const char *const parameter CTAGS_ATTR_UNUSED)
2225d8539e07SMasatake YAMATO {
2226d8539e07SMasatake YAMATO 	printLangdefFlags (localOption.withListHeader, localOption.machinable, stdout);
2227d8539e07SMasatake YAMATO 	exit (0);
2228d8539e07SMasatake YAMATO }
2229d8539e07SMasatake YAMATO 
processListKinddefFlagsOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2230e5d40a50SMasatake YAMATO static void processListKinddefFlagsOptions (
2231e5d40a50SMasatake YAMATO 		const char *const option CTAGS_ATTR_UNUSED,
2232e5d40a50SMasatake YAMATO 		const char *const parameter CTAGS_ATTR_UNUSED)
2233e5d40a50SMasatake YAMATO {
2234e5d40a50SMasatake YAMATO 	printKinddefFlags (localOption.withListHeader, localOption.machinable, stdout);
2235e5d40a50SMasatake YAMATO 	exit (0);
2236e5d40a50SMasatake YAMATO }
2237d8539e07SMasatake YAMATO 
processListRolesOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)22388ccb7ee9SJiří Techet static void processListRolesOptions (const char *const option CTAGS_ATTR_UNUSED,
2239575c9c6cSMasatake YAMATO 				     const char *const parameter)
2240575c9c6cSMasatake YAMATO {
2241575c9c6cSMasatake YAMATO 	const char* sep;
22426348dd8fSMasatake YAMATO 	const char *kindspecs;
2243575c9c6cSMasatake YAMATO 	langType lang;
2244d4c6f1e6SMasatake YAMATO 
2245575c9c6cSMasatake YAMATO 
2246575c9c6cSMasatake YAMATO 	if (parameter == NULL || parameter[0] == '\0')
2247575c9c6cSMasatake YAMATO 	{
2248489f37b8SMasatake YAMATO 		printLanguageRoles (LANG_AUTO, "*",
2249489f37b8SMasatake YAMATO 							localOption.withListHeader,
2250489f37b8SMasatake YAMATO 							localOption.machinable,
2251489f37b8SMasatake YAMATO 							stdout);
2252575c9c6cSMasatake YAMATO 		exit (0);
2253575c9c6cSMasatake YAMATO 	}
2254575c9c6cSMasatake YAMATO 
225553e914b6SMasatake YAMATO 	sep = strchr (parameter, '.');
2256575c9c6cSMasatake YAMATO 
2257575c9c6cSMasatake YAMATO 	if (sep == NULL || sep [1] == '\0')
2258575c9c6cSMasatake YAMATO 	{
2259575c9c6cSMasatake YAMATO 		vString* vstr = vStringNewInit (parameter);
226053e914b6SMasatake YAMATO 		vStringCatS (vstr, (sep? "*": ".*"));
2261575c9c6cSMasatake YAMATO 		processListRolesOptions (option, vStringValue (vstr));
2262759d281dSK.Takata 		/* The control should never reached here. */
2263575c9c6cSMasatake YAMATO 	}
2264575c9c6cSMasatake YAMATO 
22656348dd8fSMasatake YAMATO 	kindspecs = sep + 1;
226653e914b6SMasatake YAMATO 	if (strncmp (parameter, "all.", 4) == 0
22673d795de5SMasatake YAMATO 		/* Handle the case if no language is specified.
22683d795de5SMasatake YAMATO 		 * This case is not documented. */
226953e914b6SMasatake YAMATO 	    || strncmp (parameter, ".", 1) == 0)
2270575c9c6cSMasatake YAMATO 		lang = LANG_AUTO;
2271575c9c6cSMasatake YAMATO 	else
2272575c9c6cSMasatake YAMATO 	{
2273575c9c6cSMasatake YAMATO 		lang = getNamedLanguage (parameter, sep - parameter);
2274575c9c6cSMasatake YAMATO 		if (lang == LANG_IGNORE)
22757cec90a7SMasatake YAMATO 		{
22767cec90a7SMasatake YAMATO 			const char *langName = eStrndup (parameter, sep - parameter);
22777cec90a7SMasatake YAMATO 			error (FATAL, "Unknown language \"%s\" in \"%s\"", langName, option);
22787cec90a7SMasatake YAMATO 		}
2279575c9c6cSMasatake YAMATO 	}
22806348dd8fSMasatake YAMATO 	printLanguageRoles (lang, kindspecs,
2281489f37b8SMasatake YAMATO 						localOption.withListHeader,
2282489f37b8SMasatake YAMATO 						localOption.machinable,
2283489f37b8SMasatake YAMATO 						stdout);
2284575c9c6cSMasatake YAMATO 	exit (0);
2285575c9c6cSMasatake YAMATO }
2286410a34d6SMasatake YAMATO 
processListSubparsersOptions(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)2287410a34d6SMasatake YAMATO static void processListSubparsersOptions (const char *const option CTAGS_ATTR_UNUSED,
2288410a34d6SMasatake YAMATO 				     const char *const parameter)
2289410a34d6SMasatake YAMATO {
2290410a34d6SMasatake YAMATO 	langType lang;
2291410a34d6SMasatake YAMATO 
2292410a34d6SMasatake YAMATO 
2293410a34d6SMasatake YAMATO 	if (parameter == NULL || parameter[0] == '\0'
2294484c7531SMasatake YAMATO 		|| (strcmp(parameter, RSV_LANG_ALL) == 0))
2295410a34d6SMasatake YAMATO 	{
2296406a9384SMasatake YAMATO 		printLanguageSubparsers(LANG_AUTO,
2297a2dce47aSMasatake YAMATO 								localOption.withListHeader, localOption.machinable,
2298406a9384SMasatake YAMATO 								stdout);
2299410a34d6SMasatake YAMATO 		exit (0);
2300410a34d6SMasatake YAMATO 	}
2301410a34d6SMasatake YAMATO 
2302410a34d6SMasatake YAMATO 	lang = getNamedLanguage (parameter, 0);
2303410a34d6SMasatake YAMATO 	if (lang == LANG_IGNORE)
2304410a34d6SMasatake YAMATO 		error (FATAL, "Unknown language \"%s\" in \"%s\"", parameter, option);
2305410a34d6SMasatake YAMATO 
2306406a9384SMasatake YAMATO 	printLanguageSubparsers(lang,
2307a2dce47aSMasatake YAMATO 							localOption.withListHeader, localOption.machinable,
2308406a9384SMasatake YAMATO 							stdout);
2309410a34d6SMasatake YAMATO 	exit (0);
2310410a34d6SMasatake YAMATO }
2311410a34d6SMasatake YAMATO 
processListOperators(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)2312965b7025SMasatake YAMATO static void processListOperators (const char *const option CTAGS_ATTR_UNUSED,
2313965b7025SMasatake YAMATO 								  const char *const parameter)
2314965b7025SMasatake YAMATO {
2315965b7025SMasatake YAMATO 	listRegexOpscriptOperators (stdout);
2316965b7025SMasatake YAMATO 	exit (0);
2317965b7025SMasatake YAMATO }
2318965b7025SMasatake YAMATO 
freeSearchPathList(searchPathList ** pathList)2319d4c6f1e6SMasatake YAMATO static void freeSearchPathList (searchPathList** pathList)
2320d4c6f1e6SMasatake YAMATO {
2321d4c6f1e6SMasatake YAMATO 	stringListClear (*pathList);
2322d4c6f1e6SMasatake YAMATO 	stringListDelete (*pathList);
2323d4c6f1e6SMasatake YAMATO 	*pathList = NULL;
2324d4c6f1e6SMasatake YAMATO }
2325d4c6f1e6SMasatake YAMATO 
expandOnSearchPathList(searchPathList * pathList,const char * leaf,bool (* check)(const char * const))2326d4c6f1e6SMasatake YAMATO static vString* expandOnSearchPathList (searchPathList *pathList, const char* leaf,
2327ce990805SThomas Braun 					bool (* check) (const char *const))
2328d4c6f1e6SMasatake YAMATO {
2329d4c6f1e6SMasatake YAMATO 	unsigned int i;
2330d4c6f1e6SMasatake YAMATO 
233101285918SMasatake YAMATO 	for (i = stringListCount (pathList); i > 0; --i)
2332d4c6f1e6SMasatake YAMATO 	{
233301285918SMasatake YAMATO 		const char* const body = vStringValue (stringListItem (pathList, i - 1));
2334d4c6f1e6SMasatake YAMATO 		char* tmp = combinePathAndFile (body, leaf);
2335d4c6f1e6SMasatake YAMATO 
2336d4c6f1e6SMasatake YAMATO 		if ((* check) (tmp))
2337d4c6f1e6SMasatake YAMATO 		{
2338d4c6f1e6SMasatake YAMATO 			vString *r = vStringNewOwn (tmp);
2339d4c6f1e6SMasatake YAMATO 			return r;
2340d4c6f1e6SMasatake YAMATO 		}
2341d4c6f1e6SMasatake YAMATO 		else
2342d4c6f1e6SMasatake YAMATO 			eFree (tmp);
2343d4c6f1e6SMasatake YAMATO 	}
2344d4c6f1e6SMasatake YAMATO 	return NULL;
2345d4c6f1e6SMasatake YAMATO }
2346d4c6f1e6SMasatake YAMATO 
expandOnOptlibPathList(const char * leaf)2347d4c6f1e6SMasatake YAMATO static vString* expandOnOptlibPathList (const char* leaf)
2348d4c6f1e6SMasatake YAMATO {
2349d4c6f1e6SMasatake YAMATO 
235001285918SMasatake YAMATO 	return expandOnSearchPathList (OptlibPathList, leaf,
2351d4c6f1e6SMasatake YAMATO 								   doesFileExist);
2352d4c6f1e6SMasatake YAMATO }
2353d4c6f1e6SMasatake YAMATO 
processOptionFileCommon(const char * const option,const char * const parameter,bool allowNonExistingFile)23547f74e49aSMasatake YAMATO static void processOptionFileCommon (
23557f74e49aSMasatake YAMATO 	const char *const option, const char *const parameter,
23567f74e49aSMasatake YAMATO 	bool allowNonExistingFile)
2357d4c6f1e6SMasatake YAMATO {
2358d4c6f1e6SMasatake YAMATO 	const char* path;
2359d4c6f1e6SMasatake YAMATO 	vString* vpath = NULL;
2360d4c6f1e6SMasatake YAMATO 	fileStatus *status;
2361d4c6f1e6SMasatake YAMATO 
2362d4c6f1e6SMasatake YAMATO 	if (parameter [0] == '\0')
2363d4c6f1e6SMasatake YAMATO 		error (FATAL, "no option file supplied for \"%s\"", option);
2364d4c6f1e6SMasatake YAMATO 
2365d4c6f1e6SMasatake YAMATO 	if (parameter [0] != '/' && parameter [0] != '.')
2366d4c6f1e6SMasatake YAMATO 	{
2367d4c6f1e6SMasatake YAMATO 		vpath = expandOnOptlibPathList (parameter);
2368d4c6f1e6SMasatake YAMATO 		path = vpath? vStringValue (vpath): parameter;
2369d4c6f1e6SMasatake YAMATO 	}
2370d4c6f1e6SMasatake YAMATO 	else
2371d4c6f1e6SMasatake YAMATO 		path = parameter;
2372d4c6f1e6SMasatake YAMATO 
2373d4c6f1e6SMasatake YAMATO 	status = eStat (path);
2374d4c6f1e6SMasatake YAMATO 	if (!status->exists)
2375d4c6f1e6SMasatake YAMATO 	{
23767f74e49aSMasatake YAMATO 		if (!allowNonExistingFile)
2377d4c6f1e6SMasatake YAMATO 			error (FATAL | PERROR, "cannot stat \"%s\"", path);
2378d4c6f1e6SMasatake YAMATO 	}
2379d4c6f1e6SMasatake YAMATO 	else if (status->isDirectory)
2380d4c6f1e6SMasatake YAMATO 	{
2381d4c6f1e6SMasatake YAMATO 		if (!parseAllConfigurationFilesOptionsInDirectory (path, NULL))
2382d4c6f1e6SMasatake YAMATO 			error (FATAL | PERROR, "cannot open option directory \"%s\"", path);
2383d4c6f1e6SMasatake YAMATO 	}
2384d4c6f1e6SMasatake YAMATO 	else
2385d4c6f1e6SMasatake YAMATO 	{
2386d4c6f1e6SMasatake YAMATO 		if (!parseFileOptions (path))
2387d4c6f1e6SMasatake YAMATO 			error (FATAL | PERROR, "cannot open option file \"%s\"", path);
2388d4c6f1e6SMasatake YAMATO 	}
2389d4c6f1e6SMasatake YAMATO 
2390d4c6f1e6SMasatake YAMATO 	eStatFree (status);
2391d4c6f1e6SMasatake YAMATO 	if (vpath)
2392d4c6f1e6SMasatake YAMATO 		vStringDelete (vpath);
2393d4c6f1e6SMasatake YAMATO }
2394d4c6f1e6SMasatake YAMATO 
processOptionFile(const char * const option,const char * const parameter)23957f74e49aSMasatake YAMATO static void processOptionFile (
23967f74e49aSMasatake YAMATO 	const char *const option, const char *const parameter)
23977f74e49aSMasatake YAMATO {
23987f74e49aSMasatake YAMATO 	processOptionFileCommon(option, parameter, false);
23997f74e49aSMasatake YAMATO }
24007f74e49aSMasatake YAMATO 
processOptionFileMaybe(const char * const option,const char * const parameter)24017f74e49aSMasatake YAMATO static void processOptionFileMaybe (
24027f74e49aSMasatake YAMATO 	const char *const option, const char *const parameter)
24037f74e49aSMasatake YAMATO {
24047f74e49aSMasatake YAMATO 	processOptionFileCommon(option, parameter, true);
24057f74e49aSMasatake YAMATO }
24067f74e49aSMasatake YAMATO 
processOutputFormat(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)24078ccb7ee9SJiří Techet static void processOutputFormat (const char *const option CTAGS_ATTR_UNUSED,
24084586821fSMasatake YAMATO 				 const char *const parameter)
24094586821fSMasatake YAMATO {
24104586821fSMasatake YAMATO 	if (parameter [0] == '\0')
24114586821fSMasatake YAMATO 		error (FATAL, "no output format name supplied for \"%s\"", option);
24124586821fSMasatake YAMATO 
2413039bc97fSMasatake YAMATO 	if (strcmp (parameter, "u-ctags") == 0)
2414039bc97fSMasatake YAMATO 		;
2415039bc97fSMasatake YAMATO 	else if (strcmp (parameter, "e-ctags") == 0)
2416d7738cbeSMasatake YAMATO 		setTagWriter (WRITER_E_CTAGS, NULL);
24174586821fSMasatake YAMATO 	else if (strcmp (parameter, "etags") == 0)
24184586821fSMasatake YAMATO 		setEtagsMode ();
24194586821fSMasatake YAMATO 	else if (strcmp (parameter, "xref") == 0)
24204586821fSMasatake YAMATO 		setXrefMode ();
242137e5978bSMasatake YAMATO #ifdef HAVE_JANSSON
24229b88981cSAman Gupta 	else if (strcmp (parameter, "json") == 0)
24239b88981cSAman Gupta 		setJsonMode ();
242437e5978bSMasatake YAMATO #endif
24254586821fSMasatake YAMATO 	else
24264586821fSMasatake YAMATO 		error (FATAL, "unknown output format name supplied for \"%s=%s\"", option, parameter);
24274586821fSMasatake YAMATO }
24284586821fSMasatake YAMATO 
processPseudoTags(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)24298ccb7ee9SJiří Techet static void processPseudoTags (const char *const option CTAGS_ATTR_UNUSED,
24309af19922SMasatake YAMATO 			       const char *const parameter)
24319af19922SMasatake YAMATO {
24329af19922SMasatake YAMATO 	const char *p = parameter;
2433e0653dabSMasatake YAMATO 	bool s = true;
2434fe15b456SMasatake YAMATO 	ptagType t;
2435e0653dabSMasatake YAMATO 	vString *str = vStringNew();
2436e0653dabSMasatake YAMATO 
2437e0653dabSMasatake YAMATO 	if (*p == '\0' || !strchr ("*+-", *p))
2438e0653dabSMasatake YAMATO 	{
2439e0653dabSMasatake YAMATO 		for (unsigned int i = 0; i < PTAG_COUNT; i++)
2440e0653dabSMasatake YAMATO 			enablePtag (i, false);
2441e0653dabSMasatake YAMATO 	}
2442e0653dabSMasatake YAMATO 
2443e0653dabSMasatake YAMATO 	while (1)
2444e0653dabSMasatake YAMATO 	{
2445e0653dabSMasatake YAMATO 		if (*p == '\0')
2446e0653dabSMasatake YAMATO 			break;
24479af19922SMasatake YAMATO 
24489af19922SMasatake YAMATO 		if (*p == '*')
24499af19922SMasatake YAMATO 		{
24509af19922SMasatake YAMATO 			int i;
24519af19922SMasatake YAMATO 			for (i = 0; i < PTAG_COUNT; i++)
2452ce990805SThomas Braun 				enablePtag (i, true);
2453e0653dabSMasatake YAMATO 			p++;
2454e0653dabSMasatake YAMATO 			continue;
24559af19922SMasatake YAMATO 		}
2456e0653dabSMasatake YAMATO 		else if (*p == '-')
24579af19922SMasatake YAMATO 		{
2458ce990805SThomas Braun 			s= false;
2459fe15b456SMasatake YAMATO 			p++;
2460e0653dabSMasatake YAMATO 			continue;
2461fe15b456SMasatake YAMATO 		}
2462fe15b456SMasatake YAMATO 		else if (*p == '+')
2463fe15b456SMasatake YAMATO 		{
2464ce990805SThomas Braun 			s = true;
2465fe15b456SMasatake YAMATO 			p++;
2466e0653dabSMasatake YAMATO 			continue;
2467e0653dabSMasatake YAMATO 		}
2468e0653dabSMasatake YAMATO 		else if (*p == '{')
2469e0653dabSMasatake YAMATO 		{
2470e0653dabSMasatake YAMATO 			const char *origin = p;
2471e0653dabSMasatake YAMATO 
2472e0653dabSMasatake YAMATO 			p++;
2473e0653dabSMasatake YAMATO 			while (*p != '\0' && *p != '}')
2474e0653dabSMasatake YAMATO 			{
2475e0653dabSMasatake YAMATO 				vStringPut (str, *p);
2476e0653dabSMasatake YAMATO 				p++;
2477e0653dabSMasatake YAMATO 			}
2478e0653dabSMasatake YAMATO 			if (*p != '}')
2479e0653dabSMasatake YAMATO 				error (FATAL, "curly bracket specifying a pseudo tags is unbalanced: %s",
2480e0653dabSMasatake YAMATO 					   origin);
2481e0653dabSMasatake YAMATO 			p++;
24829af19922SMasatake YAMATO 		}
24839af19922SMasatake YAMATO 		else
24849af19922SMasatake YAMATO 		{
2485e0653dabSMasatake YAMATO 			vStringCopyS (str, p);
2486e0653dabSMasatake YAMATO 			p += vStringLength (str);
2487fe15b456SMasatake YAMATO 		}
2488fe15b456SMasatake YAMATO 
2489e0653dabSMasatake YAMATO 		char *name = vStringValue (str);
2490e0653dabSMasatake YAMATO 		t = getPtagTypeForName (name);
24919af19922SMasatake YAMATO 		if (t == PTAG_UNKNOWN)
2492e0653dabSMasatake YAMATO 			error (FATAL, "Unknown pseudo tag name: %s", name);
24939af19922SMasatake YAMATO 		enablePtag (t, s);
2494e0653dabSMasatake YAMATO 		vStringClear (str);
2495e0653dabSMasatake YAMATO 	}
2496e0653dabSMasatake YAMATO 	vStringDelete (str);
24979af19922SMasatake YAMATO }
24989af19922SMasatake YAMATO 
processSortOption(const char * const option,const char * const parameter)2499d4c6f1e6SMasatake YAMATO static void processSortOption (
2500d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2501d4c6f1e6SMasatake YAMATO {
2502d4c6f1e6SMasatake YAMATO 	if (isFalse (parameter))
2503d4c6f1e6SMasatake YAMATO 		Option.sorted = SO_UNSORTED;
2504d4c6f1e6SMasatake YAMATO 	else if (isTrue (parameter))
2505d4c6f1e6SMasatake YAMATO 		Option.sorted = SO_SORTED;
2506d4c6f1e6SMasatake YAMATO 	else if (strcasecmp (parameter, "f") == 0 ||
2507d4c6f1e6SMasatake YAMATO 			strcasecmp (parameter, "fold") == 0 ||
2508d4c6f1e6SMasatake YAMATO 			strcasecmp (parameter, "foldcase") == 0)
2509d4c6f1e6SMasatake YAMATO 		Option.sorted = SO_FOLDSORTED;
2510d4c6f1e6SMasatake YAMATO 	else
2511d4c6f1e6SMasatake YAMATO 		error (FATAL, "Invalid value for \"%s\" option", option);
2512d4c6f1e6SMasatake YAMATO }
2513d4c6f1e6SMasatake YAMATO 
processTagRelative(const char * const option,const char * const parameter)251478478818SMasatake YAMATO static void processTagRelative (
251578478818SMasatake YAMATO 		const char *const option, const char *const parameter)
251678478818SMasatake YAMATO {
251778478818SMasatake YAMATO 	if (isFalse (parameter))
251878478818SMasatake YAMATO 		Option.tagRelative = TREL_NO;
251900277dc9SMasatake YAMATO 	else if (isTrue (parameter) || *parameter == '\0')
252078478818SMasatake YAMATO 		Option.tagRelative = TREL_YES;
252178478818SMasatake YAMATO 	else if (strcasecmp (parameter, "always") == 0)
252278478818SMasatake YAMATO 		Option.tagRelative = TREL_ALWAYS;
252378478818SMasatake YAMATO 	else if (strcasecmp (parameter, "never") == 0)
252478478818SMasatake YAMATO 		Option.tagRelative = TREL_NEVER;
252578478818SMasatake YAMATO 	else
252678478818SMasatake YAMATO 		error (FATAL, "Invalid value for \"%s\" option", option);
252778478818SMasatake YAMATO }
252878478818SMasatake YAMATO 
processTotals(const char * const option,const char * const parameter)2529a9c91f4dSMasatake YAMATO static void processTotals (
2530a9c91f4dSMasatake YAMATO 		const char *const option, const char *const parameter)
2531a9c91f4dSMasatake YAMATO {
2532a9c91f4dSMasatake YAMATO 	if (isFalse (parameter))
2533a9c91f4dSMasatake YAMATO 		Option.printTotals = 0;
2534a9c91f4dSMasatake YAMATO 	else if (isTrue (parameter) || *parameter == '\0')
2535a9c91f4dSMasatake YAMATO 		Option.printTotals = 1;
2536a9c91f4dSMasatake YAMATO 	else if (strcasecmp (parameter, "extra") == 0)
2537a9c91f4dSMasatake YAMATO 		Option.printTotals = 2;
2538a9c91f4dSMasatake YAMATO 	else
2539a9c91f4dSMasatake YAMATO 		error (FATAL, "Invalid value for \"%s\" option", option);
2540a9c91f4dSMasatake YAMATO }
2541a9c91f4dSMasatake YAMATO 
installHeaderListDefaults(void)2542d4c6f1e6SMasatake YAMATO static void installHeaderListDefaults (void)
2543d4c6f1e6SMasatake YAMATO {
2544d4c6f1e6SMasatake YAMATO 	Option.headerExt = stringListNewFromArgv (HeaderExtensions);
2545d4c6f1e6SMasatake YAMATO 
2546d4c6f1e6SMasatake YAMATO 	BEGIN_VERBOSE(vfp);
2547d4c6f1e6SMasatake YAMATO 	{
2548d4c6f1e6SMasatake YAMATO 		fprintf (vfp, "    Setting default header extensions: ");
2549d4c6f1e6SMasatake YAMATO 		stringListPrint (Option.headerExt, vfp);
2550d4c6f1e6SMasatake YAMATO 		putc ('\n', vfp);
2551d4c6f1e6SMasatake YAMATO 	}
2552d4c6f1e6SMasatake YAMATO 	END_VERBOSE();
2553d4c6f1e6SMasatake YAMATO }
2554d4c6f1e6SMasatake YAMATO 
processHeaderListOption(const int option,const char * parameter)2555d4c6f1e6SMasatake YAMATO static void processHeaderListOption (const int option, const char *parameter)
2556d4c6f1e6SMasatake YAMATO {
2557d4c6f1e6SMasatake YAMATO 	/*  Check to make sure that the user did not enter "ctags -h *.c"
2558d4c6f1e6SMasatake YAMATO 	 *  by testing to see if the list is a filename that exists.
2559d4c6f1e6SMasatake YAMATO 	 */
2560d4c6f1e6SMasatake YAMATO 	if (doesFileExist (parameter))
2561d4c6f1e6SMasatake YAMATO 		error (FATAL, "-%c: Invalid list", option);
2562d4c6f1e6SMasatake YAMATO 	if (strcmp (parameter, "default") == 0)
2563d4c6f1e6SMasatake YAMATO 		installHeaderListDefaults ();
2564d4c6f1e6SMasatake YAMATO 	else
2565d4c6f1e6SMasatake YAMATO 	{
2566ce990805SThomas Braun 		bool clear = true;
2567d4c6f1e6SMasatake YAMATO 
2568d4c6f1e6SMasatake YAMATO 		if (parameter [0] == '+')
2569d4c6f1e6SMasatake YAMATO 		{
2570d4c6f1e6SMasatake YAMATO 			++parameter;
2571ce990805SThomas Braun 			clear = false;
2572d4c6f1e6SMasatake YAMATO 		}
2573d4c6f1e6SMasatake YAMATO 		if (Option.headerExt == NULL)
2574d4c6f1e6SMasatake YAMATO 			Option.headerExt = stringListNew ();
2575d4c6f1e6SMasatake YAMATO 		verbose ("    Header Extensions:\n");
2576d4c6f1e6SMasatake YAMATO 		addExtensionList (Option.headerExt, parameter, clear);
2577d4c6f1e6SMasatake YAMATO 	}
2578d4c6f1e6SMasatake YAMATO }
2579d4c6f1e6SMasatake YAMATO 
2580d4c6f1e6SMasatake YAMATO /*
2581d4c6f1e6SMasatake YAMATO  *  Token ignore processing
2582d4c6f1e6SMasatake YAMATO  */
readIgnoreList(const char * const list)2583d4c6f1e6SMasatake YAMATO static void readIgnoreList (const char *const list)
2584d4c6f1e6SMasatake YAMATO {
2585f76578b0SMasatake YAMATO 	langType lang = getNamedLanguage ("CPreProcessor", 0);
2586d4c6f1e6SMasatake YAMATO 	char* newList = stringCopy (list);
2587d4c6f1e6SMasatake YAMATO 	const char *token = strtok (newList, IGNORE_SEPARATORS);
2588d4c6f1e6SMasatake YAMATO 
2589d4c6f1e6SMasatake YAMATO 	while (token != NULL)
2590d4c6f1e6SMasatake YAMATO 	{
2591f76578b0SMasatake YAMATO 		applyParameter (lang, "ignore", token);
2592d4c6f1e6SMasatake YAMATO 		token = strtok (NULL, IGNORE_SEPARATORS);
2593d4c6f1e6SMasatake YAMATO 	}
2594d4c6f1e6SMasatake YAMATO 	eFree (newList);
2595d4c6f1e6SMasatake YAMATO }
2596d4c6f1e6SMasatake YAMATO 
addIgnoreListFromFile(const char * const fileName)2597d4c6f1e6SMasatake YAMATO static void addIgnoreListFromFile (const char *const fileName)
2598d4c6f1e6SMasatake YAMATO {
2599f76578b0SMasatake YAMATO 	langType lang = getNamedLanguage ("CPreProcessor", 0);
2600f76578b0SMasatake YAMATO 
2601d4c6f1e6SMasatake YAMATO 	stringList* tokens = stringListNewFromFile (fileName);
2602d4c6f1e6SMasatake YAMATO 	if (tokens == NULL)
2603d4c6f1e6SMasatake YAMATO 		error (FATAL | PERROR, "cannot open \"%s\"", fileName);
2604e8f30158SSzymon Tomasz Stefanek 
2605e8f30158SSzymon Tomasz Stefanek 	int c = stringListCount(tokens);
26067cadc29aSSzymon Tomasz Stefanek 	int i;
26077cadc29aSSzymon Tomasz Stefanek 
26087cadc29aSSzymon Tomasz Stefanek 	for(i=0;i<c;i++)
2609e8f30158SSzymon Tomasz Stefanek 	{
2610e8f30158SSzymon Tomasz Stefanek 		vString * s = stringListItem(tokens,i);
2611f76578b0SMasatake YAMATO 		applyParameter (lang, "ignore", vStringValue(s));
2612e8f30158SSzymon Tomasz Stefanek 	}
2613e8f30158SSzymon Tomasz Stefanek 
2614e8f30158SSzymon Tomasz Stefanek 	stringListDelete(tokens);
2615d4c6f1e6SMasatake YAMATO }
2616d4c6f1e6SMasatake YAMATO 
processIgnoreOption(const char * const list,int IgnoreOrDefine)261706491a9dSSzymon Tomasz Stefanek static void processIgnoreOption (const char *const list, int IgnoreOrDefine)
2618d4c6f1e6SMasatake YAMATO {
2619f76578b0SMasatake YAMATO 	langType lang = getNamedLanguage ("CPreProcessor", 0);
2620f76578b0SMasatake YAMATO 
262106491a9dSSzymon Tomasz Stefanek 	if (IgnoreOrDefine == 'D')
262206491a9dSSzymon Tomasz Stefanek 		applyParameter (lang, "define", list);
262306491a9dSSzymon Tomasz Stefanek 	else if (strchr ("@./\\", list [0]) != NULL)
2624d4c6f1e6SMasatake YAMATO 	{
2625d4c6f1e6SMasatake YAMATO 		const char* fileName = (*list == '@') ? list + 1 : list;
2626d4c6f1e6SMasatake YAMATO 		addIgnoreListFromFile (fileName);
2627d4c6f1e6SMasatake YAMATO 	}
2628d4c6f1e6SMasatake YAMATO #if defined (WIN32)
2629d4c6f1e6SMasatake YAMATO 	else if (isalpha (list [0])  &&  list [1] == ':')
2630d4c6f1e6SMasatake YAMATO 		addIgnoreListFromFile (list);
2631d4c6f1e6SMasatake YAMATO #endif
2632d4c6f1e6SMasatake YAMATO 	else if (strcmp (list, "-") == 0)
2633f76578b0SMasatake YAMATO 		applyParameter (lang, "ignore", NULL);
2634d4c6f1e6SMasatake YAMATO 	else
2635d4c6f1e6SMasatake YAMATO 		readIgnoreList (list);
2636d4c6f1e6SMasatake YAMATO }
2637d4c6f1e6SMasatake YAMATO 
processAnonHashOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2638550152f0SMasatake YAMATO static void processAnonHashOption (const char *const option CTAGS_ATTR_UNUSED, const char *const parameter CTAGS_ATTR_UNUSED)
26392b15528aSMasatake YAMATO {
26402b15528aSMasatake YAMATO 	if (parameter == NULL || parameter[0] == '\0')
26412b15528aSMasatake YAMATO 		error (FATAL, "Something string is needed for \"%s\" option", option);
26422b15528aSMasatake YAMATO 	char buf [9];
26432b15528aSMasatake YAMATO 
26442b15528aSMasatake YAMATO 	anonHashString (parameter, buf);
26452b15528aSMasatake YAMATO 	printf("%s\n", buf);
26462b15528aSMasatake YAMATO 	exit (0);
26472b15528aSMasatake YAMATO }
26482b15528aSMasatake YAMATO 
processDumpKeywordsOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2649535da559SMasatake YAMATO static void processDumpKeywordsOption (const char *const option CTAGS_ATTR_UNUSED, const char *const parameter CTAGS_ATTR_UNUSED)
2650535da559SMasatake YAMATO {
2651535da559SMasatake YAMATO 	dumpKeywordTable (stdout);
2652535da559SMasatake YAMATO }
2653535da559SMasatake YAMATO 
processEchoOption(const char * const option,const char * const parameter)2654fc22f4d2SMasatake YAMATO static void processEchoOption (const char *const option, const char *const parameter)
2655fc22f4d2SMasatake YAMATO {
2656fc22f4d2SMasatake YAMATO 	if (parameter == NULL || parameter[0] == '\0')
2657fc22f4d2SMasatake YAMATO 		error (FATAL, "Something message is needed for \"%s\" option", option);
2658fc22f4d2SMasatake YAMATO 	notice ("%s", parameter);
2659fc22f4d2SMasatake YAMATO }
2660fc22f4d2SMasatake YAMATO 
processForceInitOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)26613a3ed99cSMasatake YAMATO static void processForceInitOption (const char *const option CTAGS_ATTR_UNUSED,
2662431f0b01SMasatake YAMATO 				    const char *const parameter CTAGS_ATTR_UNUSED)
26633a3ed99cSMasatake YAMATO {
26643a3ed99cSMasatake YAMATO 	verbose ("force initializing all built-in parsers\n");
26653a3ed99cSMasatake YAMATO 	initializeParser (LANG_AUTO);
26663a3ed99cSMasatake YAMATO }
26673a3ed99cSMasatake YAMATO 
processForceQuitOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)26688ccb7ee9SJiří Techet static void processForceQuitOption (const char *const option CTAGS_ATTR_UNUSED,
2669fc22f4d2SMasatake YAMATO 				    const char *const parameter)
2670fc22f4d2SMasatake YAMATO {
267117b30777SThomas Braun 	int s;
267217b30777SThomas Braun 	if (parameter == NULL || parameter[0] == '\0' || !strToInt(parameter, 0, &s))
267317b30777SThomas Braun 		s = 0;
2674fc22f4d2SMasatake YAMATO 	exit (s);
2675fc22f4d2SMasatake YAMATO }
2676fc22f4d2SMasatake YAMATO 
processVersionOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)2677d4c6f1e6SMasatake YAMATO static void processVersionOption (
26788ccb7ee9SJiří Techet 		const char *const option CTAGS_ATTR_UNUSED,
26798ccb7ee9SJiří Techet 		const char *const parameter CTAGS_ATTR_UNUSED)
2680d4c6f1e6SMasatake YAMATO {
2681d4c6f1e6SMasatake YAMATO 	printProgramIdentification ();
2682d4c6f1e6SMasatake YAMATO 	exit (0);
2683d4c6f1e6SMasatake YAMATO }
2684d4c6f1e6SMasatake YAMATO 
2685782707aeSMasatake YAMATO #ifdef DO_TRACING
processTraceOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)2686782707aeSMasatake YAMATO static void processTraceOption(const char *const option CTAGS_ATTR_UNUSED,
2687782707aeSMasatake YAMATO 							   const char *const parameter)
2688782707aeSMasatake YAMATO {
2689782707aeSMasatake YAMATO 	const char *langs = eStrdup (parameter);
2690782707aeSMasatake YAMATO 	const char *lang = langs;
2691782707aeSMasatake YAMATO 
2692782707aeSMasatake YAMATO 	traceMain();
2693782707aeSMasatake YAMATO 
2694782707aeSMasatake YAMATO 	while (lang != NULL)
2695782707aeSMasatake YAMATO 	{
2696782707aeSMasatake YAMATO 		if (*lang == '\0')
2697782707aeSMasatake YAMATO 			break;
2698782707aeSMasatake YAMATO 		if (*lang == ',')
2699782707aeSMasatake YAMATO 		{
2700782707aeSMasatake YAMATO 			lang++;
2701782707aeSMasatake YAMATO 			continue;
2702782707aeSMasatake YAMATO 		}
2703782707aeSMasatake YAMATO 
2704782707aeSMasatake YAMATO 		char *const end = strchr (lang, ',');
2705782707aeSMasatake YAMATO 
2706782707aeSMasatake YAMATO 		if (end != NULL)
2707782707aeSMasatake YAMATO 			*end = '\0';
2708782707aeSMasatake YAMATO 
2709782707aeSMasatake YAMATO 		const langType language = getNamedLanguage (lang, 0);
2710782707aeSMasatake YAMATO 		if (language == LANG_IGNORE)
2711782707aeSMasatake YAMATO 			error (WARNING, "Unknown language \"%s\" in \"%s\" option", lang, option);
2712782707aeSMasatake YAMATO 		else
2713782707aeSMasatake YAMATO 		{
2714782707aeSMasatake YAMATO 			traceLanguage (language);
2715782707aeSMasatake YAMATO 			verbose ("Enable tracing language: %s\n", lang);
2716782707aeSMasatake YAMATO 
2717782707aeSMasatake YAMATO 		}
2718782707aeSMasatake YAMATO 		lang = (end != NULL ? end + 1 : NULL);
2719782707aeSMasatake YAMATO 	}
2720782707aeSMasatake YAMATO 	eFree ((char *)langs);
2721782707aeSMasatake YAMATO }
2722782707aeSMasatake YAMATO #endif
2723782707aeSMasatake YAMATO 
processXformatOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter)27248ccb7ee9SJiří Techet static void processXformatOption (const char *const option CTAGS_ATTR_UNUSED,
27254a63fecaSMasatake YAMATO 				  const char *const parameter)
27264a63fecaSMasatake YAMATO {
27274a63fecaSMasatake YAMATO 	if (Option.customXfmt)
27284a63fecaSMasatake YAMATO 		fmtDelete (Option.customXfmt);
27294a63fecaSMasatake YAMATO 
27304a63fecaSMasatake YAMATO 	Option.customXfmt = fmtNew (parameter);
27314a63fecaSMasatake YAMATO }
27324a63fecaSMasatake YAMATO 
prependToOptlibPathList(const char * const dir,bool report_in_verbose)2733dc660260SMasatake YAMATO static void prependToOptlibPathList (const char *const dir, bool report_in_verbose)
2734d4c6f1e6SMasatake YAMATO {
273501285918SMasatake YAMATO 	vString *elt = vStringNewInit (dir);
273601285918SMasatake YAMATO 
273701285918SMasatake YAMATO 	if (report_in_verbose)
273801285918SMasatake YAMATO 		verbose ("Prepend %s to %s\n",
273901285918SMasatake YAMATO 				 dir, "OptlibPathList");
274001285918SMasatake YAMATO 
274101285918SMasatake YAMATO 	stringListAdd (OptlibPathList, elt);
2742d4c6f1e6SMasatake YAMATO }
2743d4c6f1e6SMasatake YAMATO 
resetOptlibPathList(bool report_in_verbose)2744dc660260SMasatake YAMATO static void resetOptlibPathList (bool report_in_verbose)
2745dc660260SMasatake YAMATO {
2746dc660260SMasatake YAMATO 	freeSearchPathList (&OptlibPathList);
2747dc660260SMasatake YAMATO 	if (report_in_verbose)
2748dc660260SMasatake YAMATO 		verbose ("Reset OptlibPathList\n");
2749dc660260SMasatake YAMATO 	OptlibPathList = stringListNew ();
2750dc660260SMasatake YAMATO }
2751dc660260SMasatake YAMATO 
processOptlibDir(const char * const option,const char * const parameter)2752dc660260SMasatake YAMATO static void processOptlibDir (
2753d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2754d4c6f1e6SMasatake YAMATO {
2755d4c6f1e6SMasatake YAMATO 	const char* path;
2756d4c6f1e6SMasatake YAMATO 
2757dc660260SMasatake YAMATO 	Assert (parameter);
2758d4c6f1e6SMasatake YAMATO 
2759dc660260SMasatake YAMATO 
2760dc660260SMasatake YAMATO 	if (parameter[0] == '\0')
2761dc660260SMasatake YAMATO 		resetOptlibPathList (true);
2762dc660260SMasatake YAMATO 	else if (parameter[0] == '+')
2763d4c6f1e6SMasatake YAMATO 	{
2764d4c6f1e6SMasatake YAMATO 		path = parameter + 1;
2765dc660260SMasatake YAMATO 		if (path[0] == '\0')
2766dc660260SMasatake YAMATO 			return;
2767dc660260SMasatake YAMATO 		prependToOptlibPathList (path, true);
2768d4c6f1e6SMasatake YAMATO 	}
2769d4c6f1e6SMasatake YAMATO 	else
2770d4c6f1e6SMasatake YAMATO 	{
2771dc660260SMasatake YAMATO 		resetOptlibPathList (true);
2772d4c6f1e6SMasatake YAMATO 		path = parameter;
277301285918SMasatake YAMATO 		prependToOptlibPathList (path, true);
2774d4c6f1e6SMasatake YAMATO 	}
2775d4c6f1e6SMasatake YAMATO }
2776d4c6f1e6SMasatake YAMATO 
processMaxRecursionDepthOption(const char * const option,const char * const parameter)2777078b8008SSzymon Tomasz Stefanek static void processMaxRecursionDepthOption (const char *const option, const char *const parameter)
2778078b8008SSzymon Tomasz Stefanek {
2779078b8008SSzymon Tomasz Stefanek 	if (parameter == NULL || parameter[0] == '\0')
2780078b8008SSzymon Tomasz Stefanek 		error (FATAL, "A parameter is needed after \"%s\" option", option);
2781078b8008SSzymon Tomasz Stefanek 
2782078b8008SSzymon Tomasz Stefanek 	if (atol (parameter) < 1)
2783078b8008SSzymon Tomasz Stefanek 		error (FATAL, "-%s: Invalid maximum recursion depth", option);
2784078b8008SSzymon Tomasz Stefanek 
2785078b8008SSzymon Tomasz Stefanek 	Option.maxRecursionDepth = atol(parameter);
2786078b8008SSzymon Tomasz Stefanek }
2787078b8008SSzymon Tomasz Stefanek 
processPatternLengthLimit(const char * const option,const char * const parameter)278887976bd8SThomas Braun static void processPatternLengthLimit(const char *const option, const char *const parameter)
278987976bd8SThomas Braun {
279087976bd8SThomas Braun 	if (parameter == NULL || parameter[0] == '\0')
279187976bd8SThomas Braun 		error (FATAL, "A parameter is needed after \"%s\" option", option);
279287976bd8SThomas Braun 
279387976bd8SThomas Braun 	if (!strToUInt(parameter, 0, &Option.patternLengthLimit))
279487976bd8SThomas Braun 		error (FATAL, "-%s: Invalid pattern length limit", option);
279587976bd8SThomas Braun }
279687976bd8SThomas Braun 
ptagMakePatternLengthLimit(ptagDesc * pdesc,langType language CTAGS_ATTR_UNUSED,const void * data)2797aa53c961SMasatake YAMATO extern bool ptagMakePatternLengthLimit (ptagDesc *pdesc, langType language CTAGS_ATTR_UNUSED,
2798aa53c961SMasatake YAMATO 										const void *data)
279939da75bcSMasatake YAMATO {
280039da75bcSMasatake YAMATO 	const optionValues *opt = data;
280139da75bcSMasatake YAMATO 	char buf [21];
280239da75bcSMasatake YAMATO 
280339da75bcSMasatake YAMATO 	if (snprintf (buf, 21, "%u", opt->patternLengthLimit) >= 0)
280439da75bcSMasatake YAMATO 		return writePseudoTag (pdesc, buf, "0 for no limit", NULL);
280539da75bcSMasatake YAMATO 	return false;
280639da75bcSMasatake YAMATO }
280739da75bcSMasatake YAMATO 
setBooleanToXtagWithWarning(booleanOption * const option,bool value)2808cf82cfa2SMasatake YAMATO static void setBooleanToXtagWithWarning(booleanOption *const option, bool value)
280935c59e96SMasatake YAMATO {
281035c59e96SMasatake YAMATO 	/* WARNING/TODO: This function breaks capsulization. */
2811cf82cfa2SMasatake YAMATO 
2812cf82cfa2SMasatake YAMATO 	char x = 0;
2813cf82cfa2SMasatake YAMATO 
2814cf82cfa2SMasatake YAMATO 	if (strcmp (option->name, "file-tags") == 0)
2815cf82cfa2SMasatake YAMATO 		x = 'f';
2816cf82cfa2SMasatake YAMATO 	else if (strcmp (option->name, "file-scope") == 0)
2817cf82cfa2SMasatake YAMATO 		x = 'F';
2818cf82cfa2SMasatake YAMATO 
2819cf82cfa2SMasatake YAMATO 	if (x)
2820cf82cfa2SMasatake YAMATO 		error (WARNING, "\"--%s\" option is obsolete; use \"--extras=%c%c\" instead",
2821cf82cfa2SMasatake YAMATO 			   option->name, value? '+': '-', x);
2822cf82cfa2SMasatake YAMATO 
282335c59e96SMasatake YAMATO 	xtagType t = (xtagType)option->pValue;
28240dfb3e97SMasatake YAMATO 	enableXtag (t, value);
282535c59e96SMasatake YAMATO }
282635c59e96SMasatake YAMATO 
2827d4c6f1e6SMasatake YAMATO /*
2828d4c6f1e6SMasatake YAMATO  *  Option tables
2829d4c6f1e6SMasatake YAMATO  */
2830d4c6f1e6SMasatake YAMATO 
2831d691a826SMasatake YAMATO static void processDumpOptionsOption (const char *const option, const char *const parameter);
283233f24afcSMasatake YAMATO static void processDumpPreludeOption (const char *const option, const char *const parameter);
2833d691a826SMasatake YAMATO 
2834d4c6f1e6SMasatake YAMATO static parametricOption ParametricOptions [] = {
2835ce990805SThomas Braun 	{ "etags-include",          processEtagsInclude,            false,  STAGE_ANY },
2836ce990805SThomas Braun 	{ "exclude",                processExcludeOption,           false,  STAGE_ANY },
2837ff29abd0SMasatake YAMATO 	{ "exclude-exception",      processExcludeExceptionOption,  false,  STAGE_ANY },
2838ce990805SThomas Braun 	{ "excmd",                  processExcmdOption,             false,  STAGE_ANY },
2839ce990805SThomas Braun 	{ "extra",                  processExtraTagsOption,         false,  STAGE_ANY },
2840d76bc950SMasatake YAMATO 	{ "extras",                 processExtraTagsOption,         false,  STAGE_ANY },
2841ce990805SThomas Braun 	{ "fields",                 processFieldsOption,            false,  STAGE_ANY },
2842ce990805SThomas Braun 	{ "filter-terminator",      processFilterTerminatorOption,  true,   STAGE_ANY },
2843ce990805SThomas Braun 	{ "format",                 processFormatOption,            true,   STAGE_ANY },
2844ce990805SThomas Braun 	{ "help",                   processHelpOption,              true,   STAGE_ANY },
284507b943caSMasatake YAMATO 	{ "help-full",              processHelpFullOption,          true,   STAGE_ANY },
2846bdd29018SMasatake YAMATO 	{ "if0",                    processIf0Option,               false,  STAGE_ANY },
28472acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
2848ce990805SThomas Braun 	{ "input-encoding",         processInputEncodingOption,     false,  STAGE_ANY },
2849ce990805SThomas Braun 	{ "output-encoding",        processOutputEncodingOption,    false,  STAGE_ANY },
28502acdcfa1SYasuhiro Matsumoto #endif
2851ce990805SThomas Braun 	{ "lang",                   processLanguageForceOption,     false,  STAGE_ANY },
2852ce990805SThomas Braun 	{ "language",               processLanguageForceOption,     false,  STAGE_ANY },
2853ce990805SThomas Braun 	{ "language-force",         processLanguageForceOption,     false,  STAGE_ANY },
2854ce990805SThomas Braun 	{ "languages",              processLanguagesOption,         false,  STAGE_ANY },
2855ce990805SThomas Braun 	{ "langdef",                processLanguageDefineOption,    false,  STAGE_ANY },
2856ce990805SThomas Braun 	{ "langmap",                processLanguageMapOption,       false,  STAGE_ANY },
2857ce990805SThomas Braun 	{ "license",                processLicenseOption,           true,   STAGE_ANY },
2858ce990805SThomas Braun 	{ "list-aliases",           processListAliasesOption,       true,   STAGE_ANY },
2859199c84cdSHadriel Kaplan 	{ "list-excludes",          processListExcludesOption,      true,   STAGE_ANY },
2860d76bc950SMasatake YAMATO 	{ "list-extras",            processListExtrasOption,        true,   STAGE_ANY },
2861ce990805SThomas Braun 	{ "list-features",          processListFeaturesOption,      true,   STAGE_ANY },
2862ce990805SThomas Braun 	{ "list-fields",            processListFieldsOption,        true,   STAGE_ANY },
2863ce990805SThomas Braun 	{ "list-kinds",             processListKindsOption,         true,   STAGE_ANY },
2864ce990805SThomas Braun 	{ "list-kinds-full",        processListKindsOption,         true,   STAGE_ANY },
2865ce990805SThomas Braun 	{ "list-languages",         processListLanguagesOption,     true,   STAGE_ANY },
2866ce990805SThomas Braun 	{ "list-maps",              processListMapsOption,          true,   STAGE_ANY },
28674e9ff2c1SMasatake YAMATO 	{ "list-map-extensions",    processListMapExtensionsOption, true,   STAGE_ANY },
28684e9ff2c1SMasatake YAMATO 	{ "list-map-patterns",      processListMapPatternsOption,   true,   STAGE_ANY },
28699653ebd3SMasatake YAMATO 	{ "list-mline-regex-flags", processListMultilineRegexFlagsOptions, true, STAGE_ANY },
28703671b1d2SMasatake YAMATO 	{ "list-params",            processListParametersOption,    true,   STAGE_ANY },
2871ce990805SThomas Braun 	{ "list-pseudo-tags",       processListPseudoTagsOptions,   true,   STAGE_ANY },
2872ce990805SThomas Braun 	{ "list-regex-flags",       processListRegexFlagsOptions,   true,   STAGE_ANY },
2873220212acSMasatake YAMATO 	{ "list-roles",             processListRolesOptions,        true,   STAGE_ANY },
2874410a34d6SMasatake YAMATO 	{ "list-subparsers",        processListSubparsersOptions,   true,   STAGE_ANY },
2875ce990805SThomas Braun 	{ "maxdepth",               processMaxRecursionDepthOption, true,   STAGE_ANY },
2876dc660260SMasatake YAMATO 	{ "optlib-dir",             processOptlibDir,               false,  STAGE_ANY },
2877ce990805SThomas Braun 	{ "options",                processOptionFile,              false,  STAGE_ANY },
28787f74e49aSMasatake YAMATO 	{ "options-maybe",          processOptionFileMaybe,         false,  STAGE_ANY },
2879ce990805SThomas Braun 	{ "output-format",          processOutputFormat,            true,   STAGE_ANY },
2880ce990805SThomas Braun 	{ "pattern-length-limit",   processPatternLengthLimit,      true,   STAGE_ANY },
2881ce990805SThomas Braun 	{ "pseudo-tags",            processPseudoTags,              false,  STAGE_ANY },
2882ce990805SThomas Braun 	{ "sort",                   processSortOption,              true,   STAGE_ANY },
288378478818SMasatake YAMATO 	{ "tag-relative",           processTagRelative,             true,   STAGE_ANY },
2884a9c91f4dSMasatake YAMATO 	{ "totals",                 processTotals,                  true,   STAGE_ANY },
2885ce990805SThomas Braun 	{ "version",                processVersionOption,           true,   STAGE_ANY },
28862b15528aSMasatake YAMATO 	{ "_anonhash",              processAnonHashOption,          false,  STAGE_ANY },
2887535da559SMasatake YAMATO 	{ "_dump-keywords",         processDumpKeywordsOption,      false,  STAGE_ANY },
2888d691a826SMasatake YAMATO 	{ "_dump-options",          processDumpOptionsOption,       false,  STAGE_ANY },
288933f24afcSMasatake YAMATO 	{ "_dump-prelude",          processDumpPreludeOption,       false,  STAGE_ANY },
2890ce990805SThomas Braun 	{ "_echo",                  processEchoOption,              false,  STAGE_ANY },
28913a3ed99cSMasatake YAMATO 	{ "_force-initializing",    processForceInitOption,         false,  STAGE_ANY },
2892ce990805SThomas Braun 	{ "_force-quit",            processForceQuitOption,         false,  STAGE_ANY },
2893e7ed5190SHan-Wen Nienhuys #ifdef HAVE_JANSSON
2894e7ed5190SHan-Wen Nienhuys 	{ "_interactive",           processInteractiveOption,       true,   STAGE_ANY },
2895e7ed5190SHan-Wen Nienhuys #endif
2896e5d40a50SMasatake YAMATO 	{ "_list-kinddef-flags",    processListKinddefFlagsOptions, true,   STAGE_ANY },
2897bb331b19SMasatake YAMATO 	{ "_list-langdef-flags",    processListLangdefFlagsOptions, true,   STAGE_ANY },
2898e5f37e21SMasatake YAMATO 	{ "_list-mtable-regex-flags", processListMultitableRegexFlagsOptions, true, STAGE_ANY },
2899965b7025SMasatake YAMATO 	{ "_list-operators",        processListOperators,           true,   STAGE_ANY },
2900782707aeSMasatake YAMATO #ifdef DO_TRACING
2901782707aeSMasatake YAMATO 	{ "_trace",                 processTraceOption,             false,  STAGE_ANY },
2902782707aeSMasatake YAMATO #endif
2903ce990805SThomas Braun 	{ "_xformat",               processXformatOption,           false,  STAGE_ANY },
2904d4c6f1e6SMasatake YAMATO };
2905d4c6f1e6SMasatake YAMATO 
2906d4c6f1e6SMasatake YAMATO static booleanOption BooleanOptions [] = {
2907ce990805SThomas Braun 	{ "append",         &Option.append,                 true,  STAGE_ANY },
2908cf82cfa2SMasatake YAMATO 	{ "file-scope",     ((bool *)XTAG_FILE_SCOPE),      false, STAGE_ANY, setBooleanToXtagWithWarning },
2909cf82cfa2SMasatake YAMATO 	{ "file-tags",      ((bool *)XTAG_FILE_NAMES),      false, STAGE_ANY, setBooleanToXtagWithWarning },
2910ce990805SThomas Braun 	{ "filter",         &Option.filter,                 true,  STAGE_ANY },
2911ce990805SThomas Braun 	{ "guess-language-eagerly", &Option.guessLanguageEagerly, false, STAGE_ANY },
2912ce990805SThomas Braun 	{ "line-directives",&Option.lineDirectives,         false, STAGE_ANY },
2913ce990805SThomas Braun 	{ "links",          &Option.followLinks,            false, STAGE_ANY },
2914a2dce47aSMasatake YAMATO 	{ "machinable",     &localOption.machinable,        true,  STAGE_ANY },
2915ce990805SThomas Braun 	{ "put-field-prefix", &Option.putFieldPrefix,       false, STAGE_ANY },
2916ce990805SThomas Braun 	{ "print-language", &Option.printLanguage,          true,  STAGE_ANY },
2917ce990805SThomas Braun 	{ "quiet",          &Option.quiet,                  false, STAGE_ANY },
2918d4c6f1e6SMasatake YAMATO #ifdef RECURSE_SUPPORTED
2919ce990805SThomas Braun 	{ "recurse",        &Option.recurse,                false, STAGE_ANY },
2920d4c6f1e6SMasatake YAMATO #endif
292141a2d6beSMasatake YAMATO 	{ "verbose",        &ctags_verbose,                 false, STAGE_ANY },
2922f4904b13SMasatake YAMATO #ifdef WIN32
2923f4904b13SMasatake YAMATO 	{ "use-slash-as-filename-separator", (bool *)&Option.useSlashAsFilenameSeparator, false, STAGE_ANY },
2924f4904b13SMasatake YAMATO #endif
2925a2dce47aSMasatake YAMATO 	{ "with-list-header", &localOption.withListHeader,  true,  STAGE_ANY },
2926ce990805SThomas Braun 	{ "_fatal-warnings",&Option.fatalWarnings,          false, STAGE_ANY },
2927d4c6f1e6SMasatake YAMATO };
2928d4c6f1e6SMasatake YAMATO 
2929d4c6f1e6SMasatake YAMATO /*
2930d4c6f1e6SMasatake YAMATO  *  Generic option parsing
2931d4c6f1e6SMasatake YAMATO  */
2932d4c6f1e6SMasatake YAMATO 
checkOptionOrder(const char * const option,bool longOption)2933ce990805SThomas Braun static void checkOptionOrder (const char* const option, bool longOption)
2934d4c6f1e6SMasatake YAMATO {
2935d4c6f1e6SMasatake YAMATO 	if (NonOptionEncountered)
293643fd3ce8SMasatake YAMATO 		error (FATAL, "-%s%s option may not follow a file name", longOption? "-": "", option);
2937d4c6f1e6SMasatake YAMATO }
2938d4c6f1e6SMasatake YAMATO 
processParametricOption(const char * const option,const char * const parameter)2939ce990805SThomas Braun static bool processParametricOption (
2940d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2941d4c6f1e6SMasatake YAMATO {
2942d4c6f1e6SMasatake YAMATO 	const int count = sizeof (ParametricOptions) / sizeof (parametricOption);
2943ce990805SThomas Braun 	bool found = false;
2944d4c6f1e6SMasatake YAMATO 	int i;
2945d4c6f1e6SMasatake YAMATO 
2946d4c6f1e6SMasatake YAMATO 	for (i = 0  ;  i < count  &&  ! found  ;  ++i)
2947d4c6f1e6SMasatake YAMATO 	{
2948d4c6f1e6SMasatake YAMATO 		parametricOption* const entry = &ParametricOptions [i];
2949d4c6f1e6SMasatake YAMATO 		if (strcmp (option, entry->name) == 0)
2950d4c6f1e6SMasatake YAMATO 		{
2951ce990805SThomas Braun 			found = true;
29528da2e646SMasatake YAMATO 			if (!(entry->acceptableStages & (1UL << Stage)))
29538da2e646SMasatake YAMATO 			{
29548da2e646SMasatake YAMATO 				error (WARNING, "Cannot use --%s option in %s",
29558da2e646SMasatake YAMATO 				       option, StageDescription[Stage]);
29568da2e646SMasatake YAMATO 				break;
29578da2e646SMasatake YAMATO 			}
2958d4c6f1e6SMasatake YAMATO 			if (entry->initOnly)
2959ce990805SThomas Braun 				checkOptionOrder (option, true);
2960d4c6f1e6SMasatake YAMATO 			(entry->handler) (option, parameter);
2961d4c6f1e6SMasatake YAMATO 		}
2962d4c6f1e6SMasatake YAMATO 	}
2963d4c6f1e6SMasatake YAMATO 	return found;
2964d4c6f1e6SMasatake YAMATO }
2965d4c6f1e6SMasatake YAMATO 
getBooleanOption(const char * const option,const char * const parameter)2966ce990805SThomas Braun static bool getBooleanOption (
2967d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2968d4c6f1e6SMasatake YAMATO {
2969c92cfeefSMasatake YAMATO 	return paramParserBool (parameter, true, option, "option");
2970d4c6f1e6SMasatake YAMATO }
2971d4c6f1e6SMasatake YAMATO 
processBooleanOption(const char * const option,const char * const parameter)2972ce990805SThomas Braun static bool processBooleanOption (
2973d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
2974d4c6f1e6SMasatake YAMATO {
2975d4c6f1e6SMasatake YAMATO 	const int count = sizeof (BooleanOptions) / sizeof (booleanOption);
2976ce990805SThomas Braun 	bool found = false;
2977d4c6f1e6SMasatake YAMATO 	int i;
2978d4c6f1e6SMasatake YAMATO 
2979d4c6f1e6SMasatake YAMATO 	for (i = 0  ;  i < count  &&  ! found  ;  ++i)
2980d4c6f1e6SMasatake YAMATO 	{
2981d4c6f1e6SMasatake YAMATO 		booleanOption* const entry = &BooleanOptions [i];
2982d4c6f1e6SMasatake YAMATO 		if (strcmp (option, entry->name) == 0)
2983d4c6f1e6SMasatake YAMATO 		{
2984ce990805SThomas Braun 			found = true;
29858da2e646SMasatake YAMATO 			if (!(entry->acceptableStages & (1UL << Stage)))
29868da2e646SMasatake YAMATO 			{
29878da2e646SMasatake YAMATO 				error (WARNING, "Cannot use --%s option in %s",
29888da2e646SMasatake YAMATO 				       option, StageDescription[Stage]);
29898da2e646SMasatake YAMATO 				break;
29908da2e646SMasatake YAMATO 			}
2991d4c6f1e6SMasatake YAMATO 			if (entry->initOnly)
2992ce990805SThomas Braun 				checkOptionOrder (option, true);
29930dfb3e97SMasatake YAMATO 
29940dfb3e97SMasatake YAMATO 			bool value = getBooleanOption (option, parameter);
29954f8ad53fSMasatake YAMATO 			if (entry->set)
29964f8ad53fSMasatake YAMATO 				entry->set (entry, value);
299735c59e96SMasatake YAMATO 			else
29980dfb3e97SMasatake YAMATO 				*entry->pValue = value;
2999d4c6f1e6SMasatake YAMATO 		}
3000d4c6f1e6SMasatake YAMATO 	}
3001d4c6f1e6SMasatake YAMATO 	return found;
3002d4c6f1e6SMasatake YAMATO }
3003d4c6f1e6SMasatake YAMATO 
enableLanguageField(langType language,const char * field,bool mode)3004ce990805SThomas Braun static void enableLanguageField (langType language, const char *field, bool mode)
30059135e21dSMasatake YAMATO {
30069135e21dSMasatake YAMATO 
30079135e21dSMasatake YAMATO 	fieldType t;
30089135e21dSMasatake YAMATO 
30099135e21dSMasatake YAMATO 	t = getFieldTypeForNameAndLanguage (field, language);
30109135e21dSMasatake YAMATO 	if (t == FIELD_UNKNOWN)
30119135e21dSMasatake YAMATO 		error(FATAL, "no such field: \'%s\'", field);
3012c0421c5eSMasatake YAMATO 	enableField (t, mode);
30139135e21dSMasatake YAMATO 	if (language == LANG_AUTO)
30149135e21dSMasatake YAMATO 	{
30159135e21dSMasatake YAMATO 		fieldType ftype_next = t;
3016a6c7c87fSMasatake YAMATO 
3017a6c7c87fSMasatake YAMATO 		while ((ftype_next = nextSiblingField (ftype_next)) != FIELD_UNKNOWN)
3018c0421c5eSMasatake YAMATO 			enableField (ftype_next, mode);
30199135e21dSMasatake YAMATO 	}
30209135e21dSMasatake YAMATO }
30219135e21dSMasatake YAMATO 
enableLanguageXtag(langType language,const char * xtag,bool mode)30228643c5b5SMasatake YAMATO static void enableLanguageXtag (langType language, const char *xtag, bool mode)
30238643c5b5SMasatake YAMATO {
30248643c5b5SMasatake YAMATO 
30258643c5b5SMasatake YAMATO 	xtagType x;
30268643c5b5SMasatake YAMATO 
30278643c5b5SMasatake YAMATO 	x = getXtagTypeForNameAndLanguage (xtag, language);
30288643c5b5SMasatake YAMATO 	if (x == XTAG_UNKNOWN)
30298643c5b5SMasatake YAMATO 		error(FATAL, "no such extra: \'%s\'", xtag);
30308643c5b5SMasatake YAMATO 	enableXtag (x, mode);
30318643c5b5SMasatake YAMATO 	if (language == LANG_AUTO)
30328643c5b5SMasatake YAMATO 	{
30338643c5b5SMasatake YAMATO 		xtagType xtag_next = x;
30348643c5b5SMasatake YAMATO 
30358643c5b5SMasatake YAMATO 		while ((xtag_next = nextSiblingXtag (xtag_next)) != XTAG_UNKNOWN)
30368643c5b5SMasatake YAMATO 			enableXtag (xtag_next, mode);
30378643c5b5SMasatake YAMATO 	}
30388643c5b5SMasatake YAMATO }
30398643c5b5SMasatake YAMATO 
processLangSpecificFieldsOption(const char * const option,const char * const parameter)3040ce990805SThomas Braun static bool processLangSpecificFieldsOption (const char *const option,
30419135e21dSMasatake YAMATO 						const char *const parameter)
30429135e21dSMasatake YAMATO {
30439135e21dSMasatake YAMATO #define PREFIX "fields-"
30449135e21dSMasatake YAMATO #define PREFIX_LEN strlen(PREFIX)
30459135e21dSMasatake YAMATO 	const char* lang;
30469135e21dSMasatake YAMATO 	size_t len;
30479135e21dSMasatake YAMATO 	langType language = LANG_IGNORE;
30489135e21dSMasatake YAMATO 	const char *p = parameter;
30499135e21dSMasatake YAMATO 	int c;
30509135e21dSMasatake YAMATO 	static vString * longName;
3051ce990805SThomas Braun 	bool mode = true;
30529135e21dSMasatake YAMATO 	const char *f;
3053ce990805SThomas Braun 	bool inLongName = false;
30549135e21dSMasatake YAMATO 
30559135e21dSMasatake YAMATO 	if ( strncmp (option, PREFIX, PREFIX_LEN) != 0 )
3056ce990805SThomas Braun 		return false;
30579135e21dSMasatake YAMATO 
30589135e21dSMasatake YAMATO 	lang = option + PREFIX_LEN;
30599135e21dSMasatake YAMATO 	len = strlen (lang);
30609135e21dSMasatake YAMATO 	if (len == 0)
306199c0a56cSMasatake YAMATO 		error (FATAL, "No language given in \"%s\" option", option);
306296400277SMasatake YAMATO 	else if (len == strlen(RSV_LANG_ALL) && (strncmp(lang, RSV_LANG_ALL, len) == 0))
30639135e21dSMasatake YAMATO 		language = LANG_AUTO;
30649135e21dSMasatake YAMATO 	else
30659135e21dSMasatake YAMATO 		language = getNamedLanguage (lang, len);
30669135e21dSMasatake YAMATO 
30679135e21dSMasatake YAMATO 	if (language == LANG_IGNORE)
306899c0a56cSMasatake YAMATO 	{
306999c0a56cSMasatake YAMATO 		error (WARNING, "Unknown language: %s (ignoring \"--%s\")", lang, option);
3070759d281dSK.Takata 		/* The option is consumed in this function. */
3071ce990805SThomas Braun 		return true;
307299c0a56cSMasatake YAMATO 	}
30739135e21dSMasatake YAMATO 
30749135e21dSMasatake YAMATO 	initializeParser (language);
30759135e21dSMasatake YAMATO 
30769135e21dSMasatake YAMATO 	if (*p == '*')
30779135e21dSMasatake YAMATO 	{
3078ce990805SThomas Braun 		resetFieldsOption (language, true);
30799135e21dSMasatake YAMATO 		p++;
30809135e21dSMasatake YAMATO 	}
3081d75564d4SMasatake YAMATO 	else if (*p == '{' || *p == '\0')
3082d75564d4SMasatake YAMATO 	{
3083ce990805SThomas Braun 		resetFieldsOption (language, false);
3084d75564d4SMasatake YAMATO 		if (*p == '\0')
3085d75564d4SMasatake YAMATO 			return true;
3086d75564d4SMasatake YAMATO 	}
30879135e21dSMasatake YAMATO 	else if (*p != '+' && *p != '-')
30889135e21dSMasatake YAMATO 		error (WARNING, "Wrong per language field specification: %s", p);
30899135e21dSMasatake YAMATO 
309056065e52SMasatake YAMATO 	longName = vStringNewOrClearWithAutoRelease (longName);
30919135e21dSMasatake YAMATO 	while ((c = *p++) != '\0')
30929135e21dSMasatake YAMATO 	{
30939135e21dSMasatake YAMATO 		switch (c)
30949135e21dSMasatake YAMATO 		{
30959135e21dSMasatake YAMATO 		case '+':
30969135e21dSMasatake YAMATO 			if (inLongName)
30979135e21dSMasatake YAMATO 				vStringPut (longName, c);
30989135e21dSMasatake YAMATO 			else
3099ce990805SThomas Braun 				mode = true;
31009135e21dSMasatake YAMATO 			break;
31019135e21dSMasatake YAMATO 		case '-':
31029135e21dSMasatake YAMATO 			if (inLongName)
31039135e21dSMasatake YAMATO 				vStringPut (longName, c);
31049135e21dSMasatake YAMATO 			else
3105ce990805SThomas Braun 				mode = false;
31069135e21dSMasatake YAMATO 			break;
31079135e21dSMasatake YAMATO 		case '{':
31089135e21dSMasatake YAMATO 			if (inLongName)
31099135e21dSMasatake YAMATO 				error (FATAL,
31109135e21dSMasatake YAMATO 				       "unexpected character in field specification: \'%c\'",
31119135e21dSMasatake YAMATO 				       c);
3112ce990805SThomas Braun 			inLongName = true;
31139135e21dSMasatake YAMATO 			break;
31149135e21dSMasatake YAMATO 		case '}':
31159135e21dSMasatake YAMATO 			if (!inLongName)
31169135e21dSMasatake YAMATO 				error (FATAL,
31179135e21dSMasatake YAMATO 				       "unexpected character in field specification: \'%c\'",
31189135e21dSMasatake YAMATO 				       c);
31199135e21dSMasatake YAMATO 
31209135e21dSMasatake YAMATO 			f = vStringValue (longName);
31219135e21dSMasatake YAMATO 			enableLanguageField (language, f, mode);
3122ce990805SThomas Braun 			inLongName = false;
31239135e21dSMasatake YAMATO 			vStringClear (longName);
31249135e21dSMasatake YAMATO 			break;
31259135e21dSMasatake YAMATO 		default:
31269135e21dSMasatake YAMATO 			if (inLongName)
31279135e21dSMasatake YAMATO 				vStringPut (longName, c);
31289135e21dSMasatake YAMATO 			else
31299135e21dSMasatake YAMATO 				error (FATAL,
31309135e21dSMasatake YAMATO 				       "only long name can be used in per language field spec: \'%c\'",
31319135e21dSMasatake YAMATO 				       c);
31329135e21dSMasatake YAMATO 			break;
31339135e21dSMasatake YAMATO 		}
31349135e21dSMasatake YAMATO 	}
31355e551e57SMasatake YAMATO #undef PREFIX_LEN
31365e551e57SMasatake YAMATO #undef PREFIX
3137ce990805SThomas Braun 	return true;
31389135e21dSMasatake YAMATO }
31399135e21dSMasatake YAMATO 
processLangSpecificExtraOption(const char * const option,const char * const parameter)31408643c5b5SMasatake YAMATO static bool processLangSpecificExtraOption (const char *const option,
31418643c5b5SMasatake YAMATO 						const char *const parameter)
31428643c5b5SMasatake YAMATO {
31438643c5b5SMasatake YAMATO #define PREFIX "extras-"
31448643c5b5SMasatake YAMATO #define PREFIX_LEN strlen(PREFIX)
31458643c5b5SMasatake YAMATO 	const char* lang;
31468643c5b5SMasatake YAMATO 	size_t len;
31478643c5b5SMasatake YAMATO 	langType language = LANG_IGNORE;
31488643c5b5SMasatake YAMATO 	const char *p = parameter;
31498643c5b5SMasatake YAMATO 	int c;
31508643c5b5SMasatake YAMATO 	static vString * longName;
31518643c5b5SMasatake YAMATO 	bool mode = true;
31528643c5b5SMasatake YAMATO 	const char *x;
31538643c5b5SMasatake YAMATO 	bool inLongName = false;
31548643c5b5SMasatake YAMATO 
31558643c5b5SMasatake YAMATO 	if ( strncmp (option, PREFIX, PREFIX_LEN) != 0 )
31568643c5b5SMasatake YAMATO 		return false;
31578643c5b5SMasatake YAMATO 
31588643c5b5SMasatake YAMATO 	lang = option + PREFIX_LEN;
31598643c5b5SMasatake YAMATO 	len = strlen (lang);
31608643c5b5SMasatake YAMATO 
31618643c5b5SMasatake YAMATO 	if (len == 0)
31628643c5b5SMasatake YAMATO 		error (FATAL, "No language given in \"%s\" option", option);
316378371f13SMasatake YAMATO 	else if (len == strlen(RSV_LANG_ALL) && (strncmp(lang, RSV_LANG_ALL, len) == 0))
31648643c5b5SMasatake YAMATO 		language = LANG_AUTO;
31658643c5b5SMasatake YAMATO 	else
31668643c5b5SMasatake YAMATO 		language = getNamedLanguage (lang, len);
31678643c5b5SMasatake YAMATO 
31688643c5b5SMasatake YAMATO 	if (language == LANG_IGNORE)
31698643c5b5SMasatake YAMATO 	{
31708643c5b5SMasatake YAMATO 		error (WARNING, "Unknown language: %s (ignoring \"--%s\")", lang, option);
3171759d281dSK.Takata 		/* The option is consumed in this function. */
31728643c5b5SMasatake YAMATO 		return true;
31738643c5b5SMasatake YAMATO 	}
31748643c5b5SMasatake YAMATO 
31758643c5b5SMasatake YAMATO 	initializeParser (language);
31768643c5b5SMasatake YAMATO 
31778643c5b5SMasatake YAMATO 	if (*p == '*')
31788643c5b5SMasatake YAMATO 	{
31798643c5b5SMasatake YAMATO 		resetXtags (language, true);
31808643c5b5SMasatake YAMATO 		p++;
31818643c5b5SMasatake YAMATO 	}
318221449c9eSMasatake YAMATO 	else if (*p == '{' || *p == '\0')
318321449c9eSMasatake YAMATO 	{
31848643c5b5SMasatake YAMATO 		resetXtags (language, false);
318521449c9eSMasatake YAMATO 		if (*p == '\0')
318621449c9eSMasatake YAMATO 			return true;
318721449c9eSMasatake YAMATO 	}
31888643c5b5SMasatake YAMATO 	else if (*p != '+' && *p != '-')
31898643c5b5SMasatake YAMATO 		error (WARNING, "Wrong per language extra specification: %s", p);
31908643c5b5SMasatake YAMATO 
319156065e52SMasatake YAMATO 	longName = vStringNewOrClearWithAutoRelease (longName);
31928643c5b5SMasatake YAMATO 	while ((c = *p++) != '\0')
31938643c5b5SMasatake YAMATO 	{
31948643c5b5SMasatake YAMATO 		switch (c)
31958643c5b5SMasatake YAMATO 		{
31968643c5b5SMasatake YAMATO 		case '+':
31978643c5b5SMasatake YAMATO 			if (inLongName)
31988643c5b5SMasatake YAMATO 				vStringPut (longName, c);
31998643c5b5SMasatake YAMATO 			else
32008643c5b5SMasatake YAMATO 				mode = true;
32018643c5b5SMasatake YAMATO 			break;
32028643c5b5SMasatake YAMATO 		case '-':
32038643c5b5SMasatake YAMATO 			if (inLongName)
32048643c5b5SMasatake YAMATO 				vStringPut (longName, c);
32058643c5b5SMasatake YAMATO 			else
32068643c5b5SMasatake YAMATO 				mode = false;
32078643c5b5SMasatake YAMATO 			break;
32088643c5b5SMasatake YAMATO 		case '{':
32098643c5b5SMasatake YAMATO 			if (inLongName)
32108643c5b5SMasatake YAMATO 				error (FATAL,
32118643c5b5SMasatake YAMATO 				       "unexpected character in extra specification: \'%c\'",
32128643c5b5SMasatake YAMATO 				       c);
32138643c5b5SMasatake YAMATO 			inLongName = true;
32148643c5b5SMasatake YAMATO 			break;
32158643c5b5SMasatake YAMATO 		case '}':
32168643c5b5SMasatake YAMATO 			if (!inLongName)
32178643c5b5SMasatake YAMATO 				error (FATAL,
32188643c5b5SMasatake YAMATO 				       "unexpected character in extra specification: \'%c\'",
32198643c5b5SMasatake YAMATO 				       c);
32208643c5b5SMasatake YAMATO 
32218643c5b5SMasatake YAMATO 			x = vStringValue (longName);
32228643c5b5SMasatake YAMATO 			enableLanguageXtag (language, x, mode);
32238643c5b5SMasatake YAMATO 			inLongName = false;
32248643c5b5SMasatake YAMATO 			vStringClear (longName);
32258643c5b5SMasatake YAMATO 			break;
32268643c5b5SMasatake YAMATO 		default:
32278643c5b5SMasatake YAMATO 			if (inLongName)
32288643c5b5SMasatake YAMATO 				vStringPut (longName, c);
32298643c5b5SMasatake YAMATO 			else
32308643c5b5SMasatake YAMATO 				error (FATAL,
32318643c5b5SMasatake YAMATO 				       "only long name can be used in per language extra spec: \'%c\'",
32328643c5b5SMasatake YAMATO 				       c);
32338643c5b5SMasatake YAMATO 			break;
32348643c5b5SMasatake YAMATO 		}
32358643c5b5SMasatake YAMATO 	}
32368643c5b5SMasatake YAMATO 	return true;
32378643c5b5SMasatake YAMATO }
32388643c5b5SMasatake YAMATO 
processRegexOption(const char * const option,const char * const parameter)3239056b32e1SMasatake YAMATO static bool processRegexOption (const char *const option,
3240056b32e1SMasatake YAMATO 								const char *const parameter)
3241056b32e1SMasatake YAMATO {
3242056b32e1SMasatake YAMATO 	langType language;
3243056b32e1SMasatake YAMATO 
3244056b32e1SMasatake YAMATO 	language = getLanguageComponentInOption (option, "regex-");
3245056b32e1SMasatake YAMATO 	if (language == LANG_IGNORE)
3246056b32e1SMasatake YAMATO 		return false;
3247056b32e1SMasatake YAMATO 
32481b9c3aecSMasatake YAMATO 	processLanguageRegexOption (language, REG_PARSER_SINGLE_LINE, parameter);
3249641e337aSMasatake YAMATO 
3250641e337aSMasatake YAMATO 	return true;
3251641e337aSMasatake YAMATO }
3252641e337aSMasatake YAMATO 
processMultilineRegexOption(const char * const option,const char * const parameter)3253641e337aSMasatake YAMATO static bool processMultilineRegexOption (const char *const option,
3254641e337aSMasatake YAMATO 										 const char *const parameter)
3255641e337aSMasatake YAMATO {
3256641e337aSMasatake YAMATO 	langType language;
3257641e337aSMasatake YAMATO 
3258641e337aSMasatake YAMATO 	language = getLanguageComponentInOption (option, "mline-regex-");
3259641e337aSMasatake YAMATO 	if (language == LANG_IGNORE)
3260641e337aSMasatake YAMATO 		return false;
3261641e337aSMasatake YAMATO 
32621b9c3aecSMasatake YAMATO 	processLanguageRegexOption (language, REG_PARSER_MULTI_LINE, parameter);
3263056b32e1SMasatake YAMATO 
3264056b32e1SMasatake YAMATO 	return true;
3265056b32e1SMasatake YAMATO }
3266056b32e1SMasatake YAMATO 
processMultitableRegexOption(const char * const option,const char * const parameter)32670cbf3f0dSMasatake YAMATO static bool processMultitableRegexOption (const char *const option,
32680cbf3f0dSMasatake YAMATO 										  const char *const parameter)
32690cbf3f0dSMasatake YAMATO {
32700cbf3f0dSMasatake YAMATO 	langType language;
32710cbf3f0dSMasatake YAMATO 
32720cbf3f0dSMasatake YAMATO 	language = getLanguageComponentInOption (option, "_mtable-regex-");
32730cbf3f0dSMasatake YAMATO 	if (language == LANG_IGNORE)
32740cbf3f0dSMasatake YAMATO 		return false;
32750cbf3f0dSMasatake YAMATO 
32760cbf3f0dSMasatake YAMATO 	processLanguageRegexOption (language, REG_PARSER_MULTI_TABLE, parameter);
32770cbf3f0dSMasatake YAMATO 
32780cbf3f0dSMasatake YAMATO 	return true;
32790cbf3f0dSMasatake YAMATO }
32800cbf3f0dSMasatake YAMATO 
processMultitableExtendingOption(const char * const option,const char * const parameter)3281bf809d1aSMasatake YAMATO static bool processMultitableExtendingOption (const char *const option,
3282bf809d1aSMasatake YAMATO 											  const char *const parameter)
3283bf809d1aSMasatake YAMATO {
3284bf809d1aSMasatake YAMATO 	langType language;
3285bf809d1aSMasatake YAMATO 
3286bf809d1aSMasatake YAMATO 	language = getLanguageComponentInOption (option, "_mtable-extend-");
3287bf809d1aSMasatake YAMATO 	if (language == LANG_IGNORE)
3288bf809d1aSMasatake YAMATO 		return false;
3289bf809d1aSMasatake YAMATO 
3290bf809d1aSMasatake YAMATO 	processLanguageMultitableExtendingOption (language, parameter);
3291bf809d1aSMasatake YAMATO 
3292bf809d1aSMasatake YAMATO 	return true;
3293bf809d1aSMasatake YAMATO }
3294bf809d1aSMasatake YAMATO 
processLongOption(const char * const option,const char * const parameter)3295d4c6f1e6SMasatake YAMATO static void processLongOption (
3296d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
3297d4c6f1e6SMasatake YAMATO {
3298d4c6f1e6SMasatake YAMATO 	Assert (parameter != NULL);
32995531261dSMasatake YAMATO 	Assert (option != NULL);
33005531261dSMasatake YAMATO 
3301c99d0c93SMasatake YAMATO 	if (parameter [0] == '\0')
3302d4c6f1e6SMasatake YAMATO 		verbose ("  Option: --%s\n", option);
3303d4c6f1e6SMasatake YAMATO 	else
3304d4c6f1e6SMasatake YAMATO 		verbose ("  Option: --%s=%s\n", option, parameter);
3305d4c6f1e6SMasatake YAMATO 
3306d4c6f1e6SMasatake YAMATO 	if (processBooleanOption (option, parameter))
3307d4c6f1e6SMasatake YAMATO 		;
33089135e21dSMasatake YAMATO 	else if (processLangSpecificFieldsOption(option, parameter))
33099135e21dSMasatake YAMATO 		 ;
3310f687ebcfSMasatake YAMATO 	else if (processExtradefOption(option, parameter))
3311f687ebcfSMasatake YAMATO 		;
33125fd045b3SMasatake YAMATO 	else if (processFielddefOption(option, parameter))
33135fd045b3SMasatake YAMATO 		;
33148643c5b5SMasatake YAMATO 	else if (processLangSpecificExtraOption(option, parameter))
33158643c5b5SMasatake YAMATO 		;
3316d4c6f1e6SMasatake YAMATO 	else if (processParametricOption (option, parameter))
3317d4c6f1e6SMasatake YAMATO 		;
331818dab48bSMasatake YAMATO 	else if (processKinddefOption (option, parameter))
33193b7988cfSMasatake YAMATO 		;
332018dab48bSMasatake YAMATO 	else if (processKindsOption (option, parameter))
3321d4c6f1e6SMasatake YAMATO 		;
3322d4c6f1e6SMasatake YAMATO 	else if (processAliasOption (option, parameter))
3323d4c6f1e6SMasatake YAMATO 		;
3324d4c6f1e6SMasatake YAMATO 	else if (processRegexOption (option, parameter))
3325d4c6f1e6SMasatake YAMATO 		;
3326641e337aSMasatake YAMATO 	else if (processMultilineRegexOption (option, parameter))
3327641e337aSMasatake YAMATO 		;
3328d4c6f1e6SMasatake YAMATO 	else if (processMapOption (option, parameter))
3329d4c6f1e6SMasatake YAMATO 		;
33304d6cdcecSMasatake YAMATO 	else if (processParamOption (option, parameter))
33314d6cdcecSMasatake YAMATO 		;
3332e0e33135SMasatake YAMATO 	else if (processTabledefOption (option, parameter))
3333e0e33135SMasatake YAMATO 		;
33340cbf3f0dSMasatake YAMATO 	else if (processMultitableRegexOption (option, parameter))
33350cbf3f0dSMasatake YAMATO 		;
3336bf809d1aSMasatake YAMATO 	else if (processMultitableExtendingOption (option, parameter))
3337bf809d1aSMasatake YAMATO 		;
33382acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
33392acdcfa1SYasuhiro Matsumoto 	else if (processLanguageEncodingOption (option, parameter))
33402acdcfa1SYasuhiro Matsumoto 		;
33412acdcfa1SYasuhiro Matsumoto #endif
3342d4c6f1e6SMasatake YAMATO #ifndef RECURSE_SUPPORTED
3343d4c6f1e6SMasatake YAMATO 	else if (strcmp (option, "recurse") == 0)
3344d4c6f1e6SMasatake YAMATO 		error (WARNING, "%s option not supported on this host", option);
3345d4c6f1e6SMasatake YAMATO #endif
33467adc9db2SMasatake YAMATO 	else if (processRoledefOption (option, parameter))
33477adc9db2SMasatake YAMATO 		;
3348acf93fd6SMasatake YAMATO 	else if (processScopesepOption (option, parameter))
3349acf93fd6SMasatake YAMATO 		;
33505c872341SMasatake YAMATO 	else if (processPreludeOption (option, parameter))
33515c872341SMasatake YAMATO 		;
33521409a195SMasatake YAMATO 	else if (processSequelOption (option, parameter))
33531409a195SMasatake YAMATO 		;
3354f02166dcSMasatake YAMATO 	else if (processPretendOption (option, parameter))
3355f02166dcSMasatake YAMATO 		;
3356d2842001SMasatake YAMATO 	else if (processRolesOption (option, parameter))
3357d2842001SMasatake YAMATO 		;
3358c48fee31SMasatake YAMATO 	else if (option[0] == '_' && option[1] == '_')
3359c48fee31SMasatake YAMATO 		/* ctags ignores an argument started from --__.
3360c48fee31SMasatake YAMATO 		 * optlib2c may handle the argument. */
3361c48fee31SMasatake YAMATO 		;
3362d4c6f1e6SMasatake YAMATO 	else
3363d4c6f1e6SMasatake YAMATO 		error (FATAL, "Unknown option: --%s", option);
3364d4c6f1e6SMasatake YAMATO }
3365d4c6f1e6SMasatake YAMATO 
processShortOption(const char * const option,const char * const parameter)3366d4c6f1e6SMasatake YAMATO static void processShortOption (
3367d4c6f1e6SMasatake YAMATO 		const char *const option, const char *const parameter)
3368d4c6f1e6SMasatake YAMATO {
3369d4c6f1e6SMasatake YAMATO 	if (parameter == NULL  ||  parameter [0] == '\0')
3370d4c6f1e6SMasatake YAMATO 		verbose ("  Option: -%s\n", option);
3371d4c6f1e6SMasatake YAMATO 	else
3372d4c6f1e6SMasatake YAMATO 		verbose ("  Option: -%s %s\n", option, parameter);
3373d4c6f1e6SMasatake YAMATO 
3374d4c6f1e6SMasatake YAMATO 	if (isCompoundOption (*option) && (parameter == NULL  ||  parameter [0] == '\0'))
3375d4c6f1e6SMasatake YAMATO 		error (FATAL, "Missing parameter for \"%s\" option", option);
3376d4c6f1e6SMasatake YAMATO 	else switch (*option)
3377d4c6f1e6SMasatake YAMATO 	{
3378d4c6f1e6SMasatake YAMATO 		case '?':
3379d4c6f1e6SMasatake YAMATO 			processHelpOption ("?", NULL);
3380d4c6f1e6SMasatake YAMATO 			exit (0);
3381d4c6f1e6SMasatake YAMATO 			break;
3382d4c6f1e6SMasatake YAMATO 		case 'a':
3383ce990805SThomas Braun 			checkOptionOrder (option, false);
3384ce990805SThomas Braun 			Option.append = true;
3385d4c6f1e6SMasatake YAMATO 			break;
3386d4c6f1e6SMasatake YAMATO #ifdef DEBUG
3387d4c6f1e6SMasatake YAMATO 		case 'b':
3388d4c6f1e6SMasatake YAMATO 			if (atol (parameter) < 0)
3389d4c6f1e6SMasatake YAMATO 				error (FATAL, "-%s: Invalid line number", option);
3390d4c6f1e6SMasatake YAMATO 			Option.breakLine = atol (parameter);
3391d4c6f1e6SMasatake YAMATO 			break;
3392a358a115SMasatake YAMATO 		case 'd':
339341a2d6beSMasatake YAMATO 			if (!strToLong(parameter, 0, &ctags_debugLevel))
33947108ce22SThomas Braun 				error (FATAL, "-%s: Invalid debug level", option);
33957108ce22SThomas Braun 
3396d4c6f1e6SMasatake YAMATO 			if (debug (DEBUG_STATUS))
339741a2d6beSMasatake YAMATO 				ctags_verbose = true;
3398d4c6f1e6SMasatake YAMATO 			break;
3399d4c6f1e6SMasatake YAMATO #endif
3400d4c6f1e6SMasatake YAMATO 		case 'B':
3401ce990805SThomas Braun 			Option.backward = true;
3402d4c6f1e6SMasatake YAMATO 			break;
340306491a9dSSzymon Tomasz Stefanek 		case 'D':
340406491a9dSSzymon Tomasz Stefanek 			processIgnoreOption (parameter, *option);
340506491a9dSSzymon Tomasz Stefanek 			break;
3406d4c6f1e6SMasatake YAMATO 		case 'e':
3407ce990805SThomas Braun 			checkOptionOrder (option, false);
3408d4c6f1e6SMasatake YAMATO 			setEtagsMode ();
3409d4c6f1e6SMasatake YAMATO 			break;
3410d4c6f1e6SMasatake YAMATO 		case 'f':
3411d4c6f1e6SMasatake YAMATO 		case 'o':
3412ce990805SThomas Braun 			checkOptionOrder (option, false);
3413d4c6f1e6SMasatake YAMATO 			if (Option.tagFileName != NULL)
3414d4c6f1e6SMasatake YAMATO 			{
3415d4c6f1e6SMasatake YAMATO 				error (WARNING,
3416d4c6f1e6SMasatake YAMATO 					"-%s option specified more than once, last value used",
3417d4c6f1e6SMasatake YAMATO 					option);
3418d4c6f1e6SMasatake YAMATO 				freeString (&Option.tagFileName);
3419d4c6f1e6SMasatake YAMATO 			}
3420d4c6f1e6SMasatake YAMATO 			else if (parameter [0] == '-'  &&  parameter [1] != '\0')
3421d4c6f1e6SMasatake YAMATO 				error (FATAL, "output file name may not begin with a '-'");
3422d4c6f1e6SMasatake YAMATO 			Option.tagFileName = stringCopy (parameter);
3423d4c6f1e6SMasatake YAMATO 			break;
3424d4c6f1e6SMasatake YAMATO 		case 'F':
3425ce990805SThomas Braun 			Option.backward = false;
3426d4c6f1e6SMasatake YAMATO 			break;
3427d4c6f1e6SMasatake YAMATO 		case 'G':
3428ce990805SThomas Braun 			Option.guessLanguageEagerly = true;
3429d4c6f1e6SMasatake YAMATO 			break;
3430d4c6f1e6SMasatake YAMATO 		case 'h':
3431d4c6f1e6SMasatake YAMATO 			processHeaderListOption (*option, parameter);
3432d4c6f1e6SMasatake YAMATO 			break;
3433d4c6f1e6SMasatake YAMATO 		case 'I':
343406491a9dSSzymon Tomasz Stefanek 			processIgnoreOption (parameter, *option);
3435d4c6f1e6SMasatake YAMATO 			break;
3436d4c6f1e6SMasatake YAMATO 		case 'L':
3437d4c6f1e6SMasatake YAMATO 			if (Option.fileList != NULL)
3438d4c6f1e6SMasatake YAMATO 			{
3439d4c6f1e6SMasatake YAMATO 				error (WARNING,
3440d4c6f1e6SMasatake YAMATO 					"-%s option specified more than once, last value used",
3441d4c6f1e6SMasatake YAMATO 					option);
3442d4c6f1e6SMasatake YAMATO 				freeString (&Option.fileList);
3443d4c6f1e6SMasatake YAMATO 			}
3444d4c6f1e6SMasatake YAMATO 			Option.fileList = stringCopy (parameter);
3445d4c6f1e6SMasatake YAMATO 			break;
3446d4c6f1e6SMasatake YAMATO 		case 'n':
3447d4c6f1e6SMasatake YAMATO 			Option.locate = EX_LINENUM;
3448d4c6f1e6SMasatake YAMATO 			break;
3449d4c6f1e6SMasatake YAMATO 		case 'N':
3450d4c6f1e6SMasatake YAMATO 			Option.locate = EX_PATTERN;
3451d4c6f1e6SMasatake YAMATO 			break;
3452d4c6f1e6SMasatake YAMATO 		case 'R':
3453d4c6f1e6SMasatake YAMATO #ifdef RECURSE_SUPPORTED
3454ce990805SThomas Braun 			Option.recurse = true;
3455d4c6f1e6SMasatake YAMATO #else
3456d4c6f1e6SMasatake YAMATO 			error (WARNING, "-%s option not supported on this host", option);
3457d4c6f1e6SMasatake YAMATO #endif
3458d4c6f1e6SMasatake YAMATO 			break;
3459d4c6f1e6SMasatake YAMATO 		case 'u':
3460ce990805SThomas Braun 			checkOptionOrder (option, false);
3461d4c6f1e6SMasatake YAMATO 			Option.sorted = SO_UNSORTED;
3462d4c6f1e6SMasatake YAMATO 			break;
3463d4c6f1e6SMasatake YAMATO 		case 'V':
346441a2d6beSMasatake YAMATO 			ctags_verbose = true;
3465d4c6f1e6SMasatake YAMATO 			break;
3466d4c6f1e6SMasatake YAMATO 		case 'w':
3467d4c6f1e6SMasatake YAMATO 			/* silently ignored */
3468d4c6f1e6SMasatake YAMATO 			break;
3469d4c6f1e6SMasatake YAMATO 		case 'x':
3470ce990805SThomas Braun 			checkOptionOrder (option, false);
3471ee022af7SMasatake YAMATO 			setXrefMode ();
3472d4c6f1e6SMasatake YAMATO 			break;
3473d4c6f1e6SMasatake YAMATO 		default:
3474d4c6f1e6SMasatake YAMATO 			error (FATAL, "Unknown option: -%s", option);
3475d4c6f1e6SMasatake YAMATO 			break;
3476d4c6f1e6SMasatake YAMATO 	}
3477d4c6f1e6SMasatake YAMATO }
3478d4c6f1e6SMasatake YAMATO 
parseOption(cookedArgs * const args)347939e5f9c4SMasatake YAMATO static void parseOption (cookedArgs* const args)
3480d4c6f1e6SMasatake YAMATO {
3481d4c6f1e6SMasatake YAMATO 	Assert (! cArgOff (args));
3482d4c6f1e6SMasatake YAMATO 	if (args->isOption)
3483d4c6f1e6SMasatake YAMATO 	{
3484d4c6f1e6SMasatake YAMATO 		if (args->longOption)
3485d4c6f1e6SMasatake YAMATO 			processLongOption (args->item, args->parameter);
3486d4c6f1e6SMasatake YAMATO 		else
3487d4c6f1e6SMasatake YAMATO 		{
3488d4c6f1e6SMasatake YAMATO 			const char *parameter = args->parameter;
3489d4c6f1e6SMasatake YAMATO 			while (*parameter == ' ')
3490d4c6f1e6SMasatake YAMATO 				++parameter;
3491d4c6f1e6SMasatake YAMATO 			processShortOption (args->item, parameter);
3492d4c6f1e6SMasatake YAMATO 		}
3493d4c6f1e6SMasatake YAMATO 		cArgForth (args);
3494d4c6f1e6SMasatake YAMATO 	}
3495d4c6f1e6SMasatake YAMATO }
3496d4c6f1e6SMasatake YAMATO 
parseOptions(cookedArgs * const args)3497d4afb66eSMasatake YAMATO static void parseOptions (cookedArgs* const args)
3498d4c6f1e6SMasatake YAMATO {
3499d4c6f1e6SMasatake YAMATO 	while (! cArgOff (args)  &&  cArgIsOption (args))
3500d4c6f1e6SMasatake YAMATO 		parseOption (args);
3501d4c6f1e6SMasatake YAMATO 	if (! cArgOff (args)  &&  ! cArgIsOption (args))
3502ce990805SThomas Braun 		NonOptionEncountered = true;
3503d4c6f1e6SMasatake YAMATO }
3504d4c6f1e6SMasatake YAMATO 
parseCmdlineOptions(cookedArgs * const args)3505d4afb66eSMasatake YAMATO extern void parseCmdlineOptions (cookedArgs* const args)
3506d4afb66eSMasatake YAMATO {
35076684eba6SMasatake YAMATO 	ENTER (Cmdline);
3508d4afb66eSMasatake YAMATO 	parseOptions (args);
3509d4afb66eSMasatake YAMATO }
3510d4afb66eSMasatake YAMATO 
checkSameFile(const char * const fileName,void * userData)3511ce990805SThomas Braun static bool checkSameFile (const char *const fileName, void * userData)
3512d4c6f1e6SMasatake YAMATO {
351395f42d11SMasatake YAMATO 	return isSameFile ((const char* const) userData, fileName);
3514d4c6f1e6SMasatake YAMATO }
3515d4c6f1e6SMasatake YAMATO 
parseFileOptions(const char * const fileName)3516ce990805SThomas Braun static bool parseFileOptions (const char* const fileName)
3517d4c6f1e6SMasatake YAMATO {
3518ce990805SThomas Braun 	bool fileFound = false;
3519d4c6f1e6SMasatake YAMATO 	const char* const format = "Considering option file %s: %s\n";
352095f42d11SMasatake YAMATO 	if (stringListHasTest (OptionFiles, checkSameFile, (void *) fileName))
352115cedc6cSFrank Fesevur 	{
3522d4c6f1e6SMasatake YAMATO 		verbose (format, fileName, "already considered");
3523ce990805SThomas Braun 		fileFound = true;
352415cedc6cSFrank Fesevur 	}
3525d4c6f1e6SMasatake YAMATO 	else
3526d4c6f1e6SMasatake YAMATO 	{
3527d4c6f1e6SMasatake YAMATO 		FILE* const fp = fopen (fileName, "r");
3528d4c6f1e6SMasatake YAMATO 		if (fp == NULL)
3529d4c6f1e6SMasatake YAMATO 			verbose (format, fileName, "not found");
3530d4c6f1e6SMasatake YAMATO 		else
3531d4c6f1e6SMasatake YAMATO 		{
3532d4c6f1e6SMasatake YAMATO 			cookedArgs* const args = cArgNewFromLineFile (fp);
3533d4c6f1e6SMasatake YAMATO 			vString* file = vStringNewInit (fileName);
3534d4c6f1e6SMasatake YAMATO 			stringListAdd (OptionFiles, file);
3535d4c6f1e6SMasatake YAMATO 			verbose (format, fileName, "reading...");
3536d4c6f1e6SMasatake YAMATO 			parseOptions (args);
3537d4c6f1e6SMasatake YAMATO 			if (NonOptionEncountered)
3538d4c6f1e6SMasatake YAMATO 				error (WARNING, "Ignoring non-option in %s\n", fileName);
3539d4c6f1e6SMasatake YAMATO 			cArgDelete (args);
3540d4c6f1e6SMasatake YAMATO 			fclose (fp);
3541ce990805SThomas Braun 			fileFound = true;
3542d4c6f1e6SMasatake YAMATO 		}
3543d4c6f1e6SMasatake YAMATO 	}
3544d4c6f1e6SMasatake YAMATO 	return fileFound;
3545d4c6f1e6SMasatake YAMATO }
3546d4c6f1e6SMasatake YAMATO 
3547d4c6f1e6SMasatake YAMATO /* Actions to be taken before reading any other options */
previewFirstOption(cookedArgs * const args)3548d4c6f1e6SMasatake YAMATO extern void previewFirstOption (cookedArgs* const args)
3549d4c6f1e6SMasatake YAMATO {
3550d4c6f1e6SMasatake YAMATO 	while (cArgIsOption (args))
3551d4c6f1e6SMasatake YAMATO 	{
3552d4c6f1e6SMasatake YAMATO 		if (strcmp (args->item, "V") == 0
3553d4c6f1e6SMasatake YAMATO 		    || strcmp (args->item, "verbose") == 0
3554d4c6f1e6SMasatake YAMATO 		    || strcmp (args->item, "quiet") == 0)
3555d4c6f1e6SMasatake YAMATO 			parseOption (args);
3556d4c6f1e6SMasatake YAMATO 		else if (strcmp (args->item, "options") == 0  &&
3557db2bf481SMasatake YAMATO 				strcmp (args->parameter, RSV_NONE) == 0)
3558d4c6f1e6SMasatake YAMATO 		{
355964cc6064SMasatake YAMATO 			notice ("No options will be read from files or environment");
3560ce990805SThomas Braun 			SkipConfiguration = true;
3561d4c6f1e6SMasatake YAMATO 			cArgForth (args);
3562d4c6f1e6SMasatake YAMATO 		}
3563d4c6f1e6SMasatake YAMATO 		else
3564d4c6f1e6SMasatake YAMATO 			break;
3565d4c6f1e6SMasatake YAMATO 	}
3566d4c6f1e6SMasatake YAMATO }
3567d4c6f1e6SMasatake YAMATO 
3568e225a827SJiří Techet #if defined (HAVE_DIRENT_H) || defined (_MSC_VER)
3569e225a827SJiří Techet extern int scanDirectory (const char *directory_name,
3570e225a827SJiří Techet 						  struct dirent ***array_pointer, int (*select_function) (const struct dirent *),
3571e225a827SJiří Techet 						  int (*compare_function) (const struct dirent **, const struct dirent **));
3572e225a827SJiří Techet 
parseConfigurationFileOptionsInDirectoryWithLeafname(const char * directory,const char * leafname)3573d4c6f1e6SMasatake YAMATO static void parseConfigurationFileOptionsInDirectoryWithLeafname (const char* directory, const char* leafname)
3574d4c6f1e6SMasatake YAMATO {
3575d4c6f1e6SMasatake YAMATO 	char* pathname = combinePathAndFile (directory, leafname);
3576d4c6f1e6SMasatake YAMATO 	parseFileOptions (pathname);
3577d4c6f1e6SMasatake YAMATO 	eFree (pathname);
3578d4c6f1e6SMasatake YAMATO }
3579d4c6f1e6SMasatake YAMATO 
ignore_dot_file(const struct dirent * dent)3580d4c6f1e6SMasatake YAMATO static int ignore_dot_file(const struct dirent* dent)
3581d4c6f1e6SMasatake YAMATO {
3582d4c6f1e6SMasatake YAMATO 	/* Ignore a file which name is started from dot. */
3583d4c6f1e6SMasatake YAMATO 	if (*dent->d_name == '.')
3584d4c6f1e6SMasatake YAMATO 		return 0;
3585d4c6f1e6SMasatake YAMATO 	else
3586d4c6f1e6SMasatake YAMATO 		return 1;
3587d4c6f1e6SMasatake YAMATO }
3588d4c6f1e6SMasatake YAMATO 
accept_only_dot_ctags(const struct dirent * dent)3589d4c6f1e6SMasatake YAMATO static int accept_only_dot_ctags(const struct dirent* dent)
3590d4c6f1e6SMasatake YAMATO {
3591d4c6f1e6SMasatake YAMATO 	size_t len;
3592d4c6f1e6SMasatake YAMATO 
359364f459f1SMasatake YAMATO 	/* accept only a file ended with ".ctags" */
3594d4c6f1e6SMasatake YAMATO 	len = strlen(dent->d_name);
3595d4c6f1e6SMasatake YAMATO 
3596d4c6f1e6SMasatake YAMATO 	if (len < 7)
3597d4c6f1e6SMasatake YAMATO 		return 0;
3598d4c6f1e6SMasatake YAMATO 	if (strcmp(dent->d_name + (len - 6), ".ctags") == 0)
3599d4c6f1e6SMasatake YAMATO 		return 1;
3600d4c6f1e6SMasatake YAMATO 
3601d4c6f1e6SMasatake YAMATO 	return 0;
3602d4c6f1e6SMasatake YAMATO }
3603d4c6f1e6SMasatake YAMATO 
alphaSort(const struct dirent ** a,const struct dirent ** b)3604c8f88a19SMasatake YAMATO static int alphaSort(const struct dirent ** a,
3605d96bd365SMasatake YAMATO 									  const struct dirent ** b)
3606d96bd365SMasatake YAMATO {
3607d96bd365SMasatake YAMATO 	return strcmp ((*a)->d_name, (*b)->d_name);
3608d96bd365SMasatake YAMATO }
3609d96bd365SMasatake YAMATO 
parseAllConfigurationFilesOptionsInDirectory(const char * const dirName,stringList * const already_loaded_files)3610ce990805SThomas Braun static bool parseAllConfigurationFilesOptionsInDirectory (const char* const dirName,
3611d4c6f1e6SMasatake YAMATO 							     stringList* const already_loaded_files)
3612d4c6f1e6SMasatake YAMATO {
3613d4c6f1e6SMasatake YAMATO 	struct dirent **dents;
3614d4c6f1e6SMasatake YAMATO 	int i, n;
3615d4c6f1e6SMasatake YAMATO 
3616c8f88a19SMasatake YAMATO 	n = scanDirectory (dirName, &dents, ignore_dot_file, alphaSort);
3617d4c6f1e6SMasatake YAMATO 	if (n < 0)
3618ce990805SThomas Braun 		return false;
3619d4c6f1e6SMasatake YAMATO 
3620d4c6f1e6SMasatake YAMATO 	for (i = 0; i < n; i++)
3621d4c6f1e6SMasatake YAMATO 	{
3622d4c6f1e6SMasatake YAMATO 		char* path;
3623d4c6f1e6SMasatake YAMATO 		fileStatus *s;
3624d4c6f1e6SMasatake YAMATO 
3625d4c6f1e6SMasatake YAMATO 		if (already_loaded_files && stringListHas (already_loaded_files, dents[i]->d_name))
3626d4c6f1e6SMasatake YAMATO 			continue;
3627d4c6f1e6SMasatake YAMATO 		else if (already_loaded_files)
3628d4c6f1e6SMasatake YAMATO 			stringListAdd (already_loaded_files, vStringNewInit (dents[i]->d_name));
3629d4c6f1e6SMasatake YAMATO 
3630d4c6f1e6SMasatake YAMATO 		path = combinePathAndFile (dirName, dents[i]->d_name);
3631d4c6f1e6SMasatake YAMATO 		s = eStat (path);
3632d4c6f1e6SMasatake YAMATO 
363301285918SMasatake YAMATO 		if (s->exists && accept_only_dot_ctags(dents[i]))
3634d4c6f1e6SMasatake YAMATO 			parseConfigurationFileOptionsInDirectoryWithLeafname (dirName,
3635d4c6f1e6SMasatake YAMATO 																  dents[i]->d_name);
3636d4c6f1e6SMasatake YAMATO 		eStatFree (s);
3637d4c6f1e6SMasatake YAMATO 		free (dents[i]);
3638d4c6f1e6SMasatake YAMATO 		eFree (path);
3639d4c6f1e6SMasatake YAMATO 	}
3640d4c6f1e6SMasatake YAMATO 	free (dents);
3641ce990805SThomas Braun 	return true;
3642d4c6f1e6SMasatake YAMATO }
3643d4c6f1e6SMasatake YAMATO #else
parseAllConfigurationFilesOptionsInDirectory(const char * const dirName,stringList * const already_loaded_files)3644ce990805SThomas Braun static bool parseAllConfigurationFilesOptionsInDirectory (const char* const dirName,
3645d4c6f1e6SMasatake YAMATO 							     stringList* const already_loaded_files)
3646d4c6f1e6SMasatake YAMATO {
3647ce990805SThomas Braun 	return false;
3648d4c6f1e6SMasatake YAMATO }
3649d4c6f1e6SMasatake YAMATO #endif
3650d4c6f1e6SMasatake YAMATO 
3651ce0617a7SMasatake YAMATO typedef char* (* preloadMakePathFunc) (const char*, const char*);
3652ce0617a7SMasatake YAMATO 
3653ce0617a7SMasatake YAMATO struct preloadPathElt {
3654ce0617a7SMasatake YAMATO 	const char *path;			/* NULL means the end of list */
3655ce0617a7SMasatake YAMATO 	bool isDirectory;
3656ce0617a7SMasatake YAMATO 	preloadMakePathFunc makePath;
3657ce0617a7SMasatake YAMATO 	const char *extra;
3658ce0617a7SMasatake YAMATO 	OptionLoadingStage stage;
3659ce0617a7SMasatake YAMATO };
3660ce0617a7SMasatake YAMATO 
prependEnvvar(const char * path,const char * envvar)3661ce0617a7SMasatake YAMATO static char* prependEnvvar (const char *path, const char* envvar)
3662ce0617a7SMasatake YAMATO {
3663ce0617a7SMasatake YAMATO 	char *full_path = NULL;
3664ce0617a7SMasatake YAMATO 
3665ce0617a7SMasatake YAMATO 	const char* const envval = getenv (envvar);
3666bb37758dSMasatake YAMATO 	if (envval && strlen (envval))
3667ce0617a7SMasatake YAMATO 		full_path = combinePathAndFile(envval, path);
3668ce0617a7SMasatake YAMATO 
3669ce0617a7SMasatake YAMATO 	return full_path;
3670ce0617a7SMasatake YAMATO }
3671ce0617a7SMasatake YAMATO 
3672f2416dcaSitchyny #ifndef WIN32
getConfigForXDG(const char * path CTAGS_ATTR_UNUSED,const char * extra CTAGS_ATTR_UNUSED)3673f2416dcaSitchyny static char *getConfigForXDG (const char *path CTAGS_ATTR_UNUSED,
3674f2416dcaSitchyny 							  const char* extra CTAGS_ATTR_UNUSED)
3675f2416dcaSitchyny {
3676f2416dcaSitchyny 	char *r = prependEnvvar ("ctags", "XDG_CONFIG_HOME");
3677f2416dcaSitchyny 	if (r)
3678f2416dcaSitchyny 		return r;
3679f2416dcaSitchyny 
3680f2416dcaSitchyny 	return prependEnvvar (".config/ctags", "HOME");
3681f2416dcaSitchyny }
3682f2416dcaSitchyny #endif
3683f2416dcaSitchyny 
3684ce0617a7SMasatake YAMATO #ifdef WIN32
getConfigAtHomeOnWindows(const char * path,const char * extra CTAGS_ATTR_UNUSED)3685ce0617a7SMasatake YAMATO static char *getConfigAtHomeOnWindows (const char *path,
3686ce0617a7SMasatake YAMATO 									   const char* extra CTAGS_ATTR_UNUSED)
3687ce0617a7SMasatake YAMATO {
3688ce0617a7SMasatake YAMATO 	/*
3689ce0617a7SMasatake YAMATO 	 * Windows users don't usually set HOME.
3690ce0617a7SMasatake YAMATO 	 * The OS sets HOMEDRIVE and HOMEPATH for them.
3691ce0617a7SMasatake YAMATO 	 */
3692ce0617a7SMasatake YAMATO 	const char* homeDrive = getenv ("HOMEDRIVE");
3693ce0617a7SMasatake YAMATO 	const char* homePath = getenv ("HOMEPATH");
3694ce0617a7SMasatake YAMATO 	if (homeDrive != NULL && homePath != NULL)
3695ce0617a7SMasatake YAMATO 	{
3696ce0617a7SMasatake YAMATO 		vString* const windowsHome = vStringNew ();
3697ce0617a7SMasatake YAMATO 		vStringCatS (windowsHome, homeDrive);
3698ce0617a7SMasatake YAMATO 		vStringCatS (windowsHome, homePath);
3699ce0617a7SMasatake YAMATO 
370041bb8fbbSMasatake YAMATO 		char *tmp = vStringIsEmpty (windowsHome)
370141bb8fbbSMasatake YAMATO 			? NULL
370241bb8fbbSMasatake YAMATO 			: combinePathAndFile (vStringValue(windowsHome), path);
3703ce0617a7SMasatake YAMATO 
370441bb8fbbSMasatake YAMATO 		vStringDelete (windowsHome);
3705ce0617a7SMasatake YAMATO 		return tmp;
3706ce0617a7SMasatake YAMATO 	}
3707ce0617a7SMasatake YAMATO 	return NULL;
3708ce0617a7SMasatake YAMATO }
3709ce0617a7SMasatake YAMATO #endif
3710ce0617a7SMasatake YAMATO 
preload(struct preloadPathElt * pathList)3711ce0617a7SMasatake YAMATO static void preload (struct preloadPathElt *pathList)
3712d4c6f1e6SMasatake YAMATO {
3713d4c6f1e6SMasatake YAMATO 	unsigned int i;
3714d4c6f1e6SMasatake YAMATO 	stringList* loaded;
3715d4c6f1e6SMasatake YAMATO 
3716d4c6f1e6SMasatake YAMATO 	loaded = stringListNew ();
3717707b3e6eSMasatake YAMATO 	for (i = 0; pathList[i].path != NULL || pathList[i].makePath != NULL; ++i)
3718d4c6f1e6SMasatake YAMATO 	{
3719ce0617a7SMasatake YAMATO 		struct preloadPathElt *elt = pathList + i;
3720ce0617a7SMasatake YAMATO 		preloadMakePathFunc maker = elt->makePath;
3721ce0617a7SMasatake YAMATO 		const char *path = elt->path;
3722ce0617a7SMasatake YAMATO 
3723ce0617a7SMasatake YAMATO 
3724ce0617a7SMasatake YAMATO 		if (maker)
3725ce0617a7SMasatake YAMATO 			path = maker(elt->path, elt->extra);
3726ce0617a7SMasatake YAMATO 
3727ce0617a7SMasatake YAMATO 		if (path == NULL)
3728ce0617a7SMasatake YAMATO 			continue;
3729ce0617a7SMasatake YAMATO 
3730ce0617a7SMasatake YAMATO 		Assert (Stage <= elt->stage);
3731ce0617a7SMasatake YAMATO 		if (Stage != elt->stage)
3732ce0617a7SMasatake YAMATO 		{
3733ce0617a7SMasatake YAMATO 			Stage = elt->stage;
3734ce0617a7SMasatake YAMATO 			verbose ("Entering configuration stage: loading %s\n", StageDescription[Stage]);
3735ce0617a7SMasatake YAMATO 		}
3736ce0617a7SMasatake YAMATO 
3737ce0617a7SMasatake YAMATO 		if (elt->isDirectory)
3738ce0617a7SMasatake YAMATO 			parseAllConfigurationFilesOptionsInDirectory (path, loaded);
3739ce0617a7SMasatake YAMATO 		else
3740ce0617a7SMasatake YAMATO 			parseFileOptions (path);
3741ce0617a7SMasatake YAMATO 
3742ce0617a7SMasatake YAMATO 		if (path != elt->path)
3743ce0617a7SMasatake YAMATO 			eFree ((void *)path);
3744d4c6f1e6SMasatake YAMATO 	}
3745d4c6f1e6SMasatake YAMATO 	stringListClear (loaded);
3746d4c6f1e6SMasatake YAMATO 	stringListDelete (loaded);
3747d4c6f1e6SMasatake YAMATO }
3748d4c6f1e6SMasatake YAMATO 
3749ce0617a7SMasatake YAMATO static struct preloadPathElt preload_path_list [] = {
3750ce0617a7SMasatake YAMATO #ifdef CUSTOM_CONFIGURATION_FILE
3751ce0617a7SMasatake YAMATO 	{
3752ce0617a7SMasatake YAMATO 		.path = CUSTOM_CONFIGURATION_FILE,
3753ce0617a7SMasatake YAMATO 		.isDirectory = false,
3754ce0617a7SMasatake YAMATO 		.makePath = NULL,
3755ce0617a7SMasatake YAMATO 		.stage = OptionLoadingStageCustom,
3756ce0617a7SMasatake YAMATO 	},
3757ce0617a7SMasatake YAMATO #endif
3758f2416dcaSitchyny #ifndef WIN32
3759f2416dcaSitchyny 	{
3760f2416dcaSitchyny 		.path = NULL,
3761f2416dcaSitchyny 		.isDirectory = true,
3762f2416dcaSitchyny 		.makePath = getConfigForXDG,
3763f2416dcaSitchyny 		.stage = OptionLoadingStageXdg,
3764f2416dcaSitchyny 	},
3765f2416dcaSitchyny #endif
3766ce0617a7SMasatake YAMATO 	{
3767ce0617a7SMasatake YAMATO 		.path = ".ctags.d",
3768ce0617a7SMasatake YAMATO 		.isDirectory = true,
3769ce0617a7SMasatake YAMATO 		.makePath = prependEnvvar,
3770ce0617a7SMasatake YAMATO 		.extra = "HOME",
3771ce0617a7SMasatake YAMATO 		.stage = OptionLoadingStageHomeRecursive,
3772ce0617a7SMasatake YAMATO 	},
3773ce0617a7SMasatake YAMATO #ifdef WIN32
3774ce0617a7SMasatake YAMATO 	{
3775ce0617a7SMasatake YAMATO 		.path = "ctags.d",
3776ce0617a7SMasatake YAMATO 		.isDirectory = true,
3777ce0617a7SMasatake YAMATO 		.makePath = getConfigAtHomeOnWindows,
3778ce0617a7SMasatake YAMATO 		.extra = NULL,
3779ce0617a7SMasatake YAMATO 		.stage = OptionLoadingStageHomeRecursive,
3780ce0617a7SMasatake YAMATO 	},
3781ce0617a7SMasatake YAMATO #endif
3782ce0617a7SMasatake YAMATO 	{
3783ce0617a7SMasatake YAMATO 		.path = ".ctags.d",
3784ce0617a7SMasatake YAMATO 		.isDirectory = true,
3785ce0617a7SMasatake YAMATO 		.makePath = NULL,
3786ce0617a7SMasatake YAMATO 		.stage = OptionLoadingStageCurrentRecursive,
3787ce0617a7SMasatake YAMATO 	},
3788ce0617a7SMasatake YAMATO 	{
3789ce0617a7SMasatake YAMATO 		.path = "ctags.d",
3790ce0617a7SMasatake YAMATO 		.isDirectory = true,
3791ce0617a7SMasatake YAMATO 		.makePath = NULL,
3792ce0617a7SMasatake YAMATO 		.stage = OptionLoadingStageCurrentRecursive,
3793ce0617a7SMasatake YAMATO 	},
3794707b3e6eSMasatake YAMATO 	{
3795707b3e6eSMasatake YAMATO 		.path = NULL,
3796707b3e6eSMasatake YAMATO 		.makePath = NULL,
3797707b3e6eSMasatake YAMATO 	},
3798ce0617a7SMasatake YAMATO };
3799ce0617a7SMasatake YAMATO 
parseConfigurationFileOptions(void)3800d4c6f1e6SMasatake YAMATO static void parseConfigurationFileOptions (void)
3801d4c6f1e6SMasatake YAMATO {
3802ce0617a7SMasatake YAMATO 	preload (preload_path_list);
3803d4c6f1e6SMasatake YAMATO }
3804d4c6f1e6SMasatake YAMATO 
readOptionConfiguration(void)3805d4c6f1e6SMasatake YAMATO extern void readOptionConfiguration (void)
3806d4c6f1e6SMasatake YAMATO {
3807d4c6f1e6SMasatake YAMATO 	if (! SkipConfiguration)
3808d4c6f1e6SMasatake YAMATO 		parseConfigurationFileOptions ();
3809d4c6f1e6SMasatake YAMATO }
3810d4c6f1e6SMasatake YAMATO 
3811d4c6f1e6SMasatake YAMATO /*
3812d4c6f1e6SMasatake YAMATO *   Option initialization
3813d4c6f1e6SMasatake YAMATO */
3814d4c6f1e6SMasatake YAMATO 
initOptions(void)3815d4c6f1e6SMasatake YAMATO extern void initOptions (void)
3816d4c6f1e6SMasatake YAMATO {
3817d4c6f1e6SMasatake YAMATO 	OptionFiles = stringListNew ();
381896767f13SMasatake YAMATO 	OptlibPathList = stringListNew ();
3819dc660260SMasatake YAMATO 
3820d4c6f1e6SMasatake YAMATO 	verbose ("Setting option defaults\n");
3821d4c6f1e6SMasatake YAMATO 	installHeaderListDefaults ();
3822d4c6f1e6SMasatake YAMATO 	verbose ("  Installing default language mappings:\n");
3823d4c6f1e6SMasatake YAMATO 	installLanguageMapDefaults ();
3824d4c6f1e6SMasatake YAMATO 	verbose ("  Installing default language aliases:\n");
3825d4c6f1e6SMasatake YAMATO 	installLanguageAliasesDefaults ();
3826d4c6f1e6SMasatake YAMATO 
3827d4c6f1e6SMasatake YAMATO 	/* always excluded by default */
3828d4c6f1e6SMasatake YAMATO 	verbose ("  Installing default exclude patterns:\n");
3829d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "{arch}");
3830d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".arch-ids");
3831d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".arch-inventory");
3832d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "autom4te.cache");
3833d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "BitKeeper");
3834d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".bzr");
3835d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".bzrignore");
3836d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "CVS");
3837d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".cvsignore");
3838d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "_darcs");
3839d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".deps");
38406acbaf4aSMasatake YAMATO 	processExcludeOption (NULL, ".dvi");
38417514ea60SHadriel Kaplan 	processExcludeOption (NULL, ".DS_Store");
3842d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "EIFGEN");
3843d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".git");
3844298582b8SMasatake YAMATO 	processExcludeOption (NULL, ".gitignore");
38455ee3b074SMasatake YAMATO 	processExcludeOption (NULL, ".gitattributes");
3846d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".hg");
3847298582b8SMasatake YAMATO 	processExcludeOption (NULL, ".hgignore");
3848d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "PENDING");
3849d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "RCS");
3850d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "RESYNC");
3851d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, "SCCS");
3852d4c6f1e6SMasatake YAMATO 	processExcludeOption (NULL, ".svn");
3853298582b8SMasatake YAMATO 	processExcludeOption (NULL, "*~");
38542be1308fSMasatake YAMATO 	processExcludeOption (NULL, ".*.swp");
38559ed45ea9SMasatake YAMATO 
38569ed45ea9SMasatake YAMATO 	/* Exclude binary files
38579ed45ea9SMasatake YAMATO 	 * -----------------------------------------------
38589ed45ea9SMasatake YAMATO 	 *
38599ed45ea9SMasatake YAMATO 	 * TODO
38609ed45ea9SMasatake YAMATO 	 *
38619ed45ea9SMasatake YAMATO 	 * It will be interesting if ctags can extract
38629ed45ea9SMasatake YAMATO 	 * symbols from these binaries.
38639ed45ea9SMasatake YAMATO 	 *
38649ed45ea9SMasatake YAMATO 	 * --langdef=nm --regex-nm=...
38659ed45ea9SMasatake YAMATO 	 * --langdef=elf --pre-processor-elf=/bin/nm ...
38669ed45ea9SMasatake YAMATO 	 *
38679ed45ea9SMasatake YAMATO 	 * vim/emacs users never wants the cursor to jump to
38689ed45ea9SMasatake YAMATO 	 * a binary file but may wants to utilize the symbol
38699ed45ea9SMasatake YAMATO 	 * information for completion.
38709ed45ea9SMasatake YAMATO 	 *
38719ed45ea9SMasatake YAMATO 	 * https://bitbucket.org/haypo/hachoir3 can be
38729ed45ea9SMasatake YAMATO 	 * used the alternative for /bin/nm
38739ed45ea9SMasatake YAMATO 	 */
38749ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.o");
38759ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.a");
38769ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.so");
38779ed45ea9SMasatake YAMATO 
38789ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.obj");
38799ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.lib");
38809ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.dll");
38819ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.exe");
38829ed45ea9SMasatake YAMATO 
38839ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.gcno");
38849ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.gcda");
38859ed45ea9SMasatake YAMATO 
38869ed45ea9SMasatake YAMATO 	processExcludeOption (NULL, "*.class");
3887ae0fe4e0SMasatake YAMATO 
3888ae0fe4e0SMasatake YAMATO 	processExcludeOption (NULL, "*.pyc");
3889ae0fe4e0SMasatake YAMATO 	processExcludeOption (NULL, "*.pyo");
3890d4c6f1e6SMasatake YAMATO }
3891d4c6f1e6SMasatake YAMATO 
freeOptionResources(void)3892d4c6f1e6SMasatake YAMATO extern void freeOptionResources (void)
3893d4c6f1e6SMasatake YAMATO {
3894d4c6f1e6SMasatake YAMATO 	freeString (&Option.tagFileName);
3895d4c6f1e6SMasatake YAMATO 	freeString (&Option.fileList);
3896d4c6f1e6SMasatake YAMATO 	freeString (&Option.filterTerminator);
3897d4c6f1e6SMasatake YAMATO 
3898d4c6f1e6SMasatake YAMATO 	freeList (&Excluded);
3899ff29abd0SMasatake YAMATO 	freeList (&ExcludedException);
3900d4c6f1e6SMasatake YAMATO 	freeList (&Option.headerExt);
3901d4c6f1e6SMasatake YAMATO 	freeList (&Option.etagsInclude);
3902d4c6f1e6SMasatake YAMATO 
3903d4c6f1e6SMasatake YAMATO 	freeSearchPathList (&OptlibPathList);
3904d4c6f1e6SMasatake YAMATO 
3905d4c6f1e6SMasatake YAMATO 	freeList (&OptionFiles);
3906d4c6f1e6SMasatake YAMATO }
3907d691a826SMasatake YAMATO 
processDumpOptionsOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)3908d691a826SMasatake YAMATO static void processDumpOptionsOption (const char *const option CTAGS_ATTR_UNUSED, const char *const parameter CTAGS_ATTR_UNUSED)
3909d691a826SMasatake YAMATO {
3910d691a826SMasatake YAMATO 	fprintf(stdout, "# %s\n", "ParametricOptions");
3911d691a826SMasatake YAMATO 	for (unsigned int i = 0; i < ARRAY_SIZE(ParametricOptions); i++)
3912d691a826SMasatake YAMATO 		fprintf(stdout, "%s\n", ParametricOptions[i].name);
3913d691a826SMasatake YAMATO 
3914d691a826SMasatake YAMATO 	fprintf(stdout, "# %s\n", "BooleanOptions");
3915d691a826SMasatake YAMATO 	for (unsigned int i = 0; i < ARRAY_SIZE(BooleanOptions); i++)
3916d691a826SMasatake YAMATO 		fprintf(stdout, "%s\n", BooleanOptions[i].name);
3917d691a826SMasatake YAMATO }
3918aa3cc57dSMasatake YAMATO 
processDumpPreludeOption(const char * const option CTAGS_ATTR_UNUSED,const char * const parameter CTAGS_ATTR_UNUSED)391933f24afcSMasatake YAMATO static void processDumpPreludeOption (const char *const option CTAGS_ATTR_UNUSED, const char *const parameter CTAGS_ATTR_UNUSED)
392033f24afcSMasatake YAMATO {
392133f24afcSMasatake YAMATO 	extern const char ctagsCommonPrelude[];
392233f24afcSMasatake YAMATO 	fprintf(stdout, "%s\n", ctagsCommonPrelude);
392333f24afcSMasatake YAMATO 	exit (0);
392433f24afcSMasatake YAMATO }
392533f24afcSMasatake YAMATO 
inSandbox(void)3926aa3cc57dSMasatake YAMATO extern bool inSandbox (void)
3927aa3cc57dSMasatake YAMATO {
3928aa3cc57dSMasatake YAMATO 	return (Option.interactive == INTERACTIVE_SANDBOX);
3929aa3cc57dSMasatake YAMATO }
3930fb5ef688SMasatake YAMATO 
canUseLineNumberAsLocator(void)3931fb5ef688SMasatake YAMATO extern bool canUseLineNumberAsLocator (void)
3932fb5ef688SMasatake YAMATO {
3933fb5ef688SMasatake YAMATO 	return (Option.locate != EX_PATTERN);
3934fb5ef688SMasatake YAMATO }
3935ecaa3a91SMasatake YAMATO 
isDestinationStdout(void)3936ecaa3a91SMasatake YAMATO extern bool isDestinationStdout (void)
3937ecaa3a91SMasatake YAMATO {
3938ecaa3a91SMasatake YAMATO 	bool toStdout = false;
3939ecaa3a91SMasatake YAMATO 
3940ecaa3a91SMasatake YAMATO 	if (Option.filter || Option.interactive ||
3941ecaa3a91SMasatake YAMATO 		(Option.tagFileName != NULL  &&  (strcmp (Option.tagFileName, "-") == 0
3942ecaa3a91SMasatake YAMATO 						  || strcmp (Option.tagFileName, "/dev/stdout") == 0
3943ecaa3a91SMasatake YAMATO 		)))
3944ecaa3a91SMasatake YAMATO 		toStdout = true;
3945ecaa3a91SMasatake YAMATO 	else if (Option.tagFileName == NULL && NULL == outputDefaultFileName ())
3946ecaa3a91SMasatake YAMATO 		toStdout = true;
3947ecaa3a91SMasatake YAMATO 
3948ecaa3a91SMasatake YAMATO 	return toStdout;
3949ecaa3a91SMasatake YAMATO }
3950