main: ctags option processing fails if "Language already defined", including ctags --help
Hello,
recently gentoo updated to ctags-20210321.0. Since this version added the BibTeX parser but I had the file ~/.ctags.d/BibTeX.ctags I got the message 'ctags: Language "BibTeX" already defined'. So far so good - but 'ctags --help' or 'ctags --list-languages' only outputs the message above and apparently bails out of option processing. I think that at least such info requests should continue to work.
$ ctags --version
ctags: Language "BibTeX" already defined
After removing ~/.ctags.d/BibTeX.ctags:
$ ctags --version
Universal Ctags 5.9.0, Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
Compiled: Mar 30 2021, 09:48:49
URL: https://ctags.io/
Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath, +sandbox, +packcc
How do you get ctags binary:
via gentoo portage
I agree with you. Thank you for the sugestion. I will try to fix. However, I cannot find a simple way to implement the behavior now.
Maybe I have to rewrite the initialization code.
@masatake san,
Maybe I have to rewrite the initialization code.
main.c
579 initOptions ();
580 readOptionConfiguration (); // ~/.ctags.d/BibTeX.ctags is read and causes the error
581 verbose ("Reading initial options from command line\n");
582 parseCmdlineOptions (args); // --version is processed
How about deferring errors in readOptionConfiguration () after parseCmdlineOptions (args) by using setErrorPrinter()?
Something like;
579 initOptions ();
xxx setErrorPrinter (deferredErrorPrinter, NULL); // register a new ErrorPrinter
580 readOptionConfiguration (); // ~/.ctags.d/BibTeX.ctags is read and causes the error
581 verbose ("Reading initial options from command line\n");
582 parseCmdlineOptions (args); // --version is processed
xxx if (haveDeferredError()) exit (1); // check errors defered
xxx setErrorPrinter (stderrDefaultErrorPrinter, NULL); // revert the default ErrorPrinter
Or how about this?
--- a/main/parse.c
+++ b/main/parse.c
@@ -2173,8 +2173,8 @@ extern void processLanguageDefineOption (
}
else if (getNamedLanguage (name, 0) != LANG_IGNORE)
{
- /* name cannot be freed because it is used in the FATAL message. */
- error (FATAL, "Language \"%s\" already defined", name);
+ error (WARNING, "Language \"%s\" already defined. Ignored.", name);
+ eFree (name);
}
else if (strcmp(name, RSV_LANG_ALL) == 0)
{
The former one is not acceptable. Users expect they can override the configuration given in .ctags.d from options specified in the command line like make command.
The direction of the latter one is good. I got inspiration from the latter one. The latter one is not perfect.
.ctags.d/foo.ctags
--langdef=C
--regex-C=....
...
With the latter one, ctags warns when reading --langdef=C. However, ctags doesn't stop and ctags can parse
an input file after reading --regex-C=..... The tags output may be an unwanted one.
As you show in the latter one, ctags should not stop when reading --langdef=C but it should stop before parsing.
+ struct delayedFatalError {
+ const char *msg;
+ };
+
+ static stringList * delayed_fatal_errors = stringListNew();
+ static void flush_delayed_fatal_errors (void)
+ {
+ for_each_msg (delayed_fatal_errors) {
+ fputs(msg, stderr);
+ exit (1);
+ }
...
else if (getNamedLanguage (name, 0) != LANG_IGNORE)
{
- /* name cannot be freed because it is used in the FATAL message. */
- error (FATAL, "Language \"%s\" already defined", name);
+ enqueue_delayed_fatal_error ( "Language \"%s\" already defined", name);
+ eFree (name);
}
...
extern void checkOptions (void)
{
...
+flush_delayed_fatal_errors ();
...
}
~I implemented my idea in #2987. What I got is many coredumps.~ I took a mistake.
The fix I proposed in #2987 causes crashes on Windows.
I found another solution to this.
Instead of accepting --langdef-<LANG> option for an already defined language, we handle --version and --help in an earlier stage like:
diff --git a/main/options.c b/main/options.c
index ac87072cd..52f1133c6 100644
--- a/main/options.c
+++ b/main/options.c
@@ -3549,7 +3549,10 @@ extern void previewFirstOption (cookedArgs* const args)
{
if (strcmp (args->item, "V") == 0
|| strcmp (args->item, "verbose") == 0
- || strcmp (args->item, "quiet") == 0)
+ || strcmp (args->item, "quiet") == 0
+ || (strcmp (args->item, "version") == 0 &&
+ (strcmp (args->parameter, RSV_NONE) == 0
+ || (*args->parameter == '\0'))))
parseOption (args);
else if (strcmp (args->item, "options") == 0 &&
strcmp (args->parameter, RSV_NONE) == 0)