Subject: bug#28403: 25.2; find-tag works, but xref-find-definitions

From: Winston <[email-masked]>
Date: Sun, 10 Sep 2017 14:27 EDT

Eli kindly replied:
> Could you please post a complete example of the code in question,
> including the definition of the _ARGS1 macro, and any other macros and
> typedefs that would make the example stand-alone?  I think I
> understand what has happened, but I'd like to be sure before we decide
> what to do about it.

   Sure (well, it's a semi-complete example).  The code, in general,
seeks to be as widely compatible with any compiler, ancient or modern,
as possible.  That's in part because the earliest versions originated
back in the 90's when, for example, Sun's bundled cc was a K&R C
compiler.  The _ARGS* macros provide compatibility between K&R C's

	name (arg1, arg2)
	type arg1; type arg2;
	{ ... }

and ANSI C's

	name (type arg1, type arg2)
	{ ... }.

_ARGS1 through _ARGS# (enough for whatever function takes the most
arguments (or more)) are #define'd in a header file.

   The other coding style that may matter here is the practice of
putting the return value type on a separate line at the function
definition (as you'll see below).  That makes the function name easier
to see (always at the left edge) and allows more arguments to fit on the
function name line (nice when grep'ing).

   The following edited extracts are the basic pieces:

----------

   In a common header file:

#ifdef __STDC__

# define _ARGS(args) args

# define _ARGS0(void) \
	(void)
# define _ARGS1(A,a) \
	(A a)
# define _ARGS2(A,a,B,b) \
	(A a, B b)
# define _ARGS3(A,a,B,b,C,c) \
	(A a, B b, C c)
 [...]

#else /* !__STDC__ */

# define _ARGS(args) ()

# define _ARGS0(args)       ()
# define _ARGS1(A,a) \
	(a) \
	A a;
# define _ARGS2(A,a,B,b) \
	(a, b) \
	A a; B b;
# define _ARGS3(A,a,B,b,C,c) \
	(a, b, c) \
	A a; B b; C c;
 [...]

#endif /* __STDC__ */

   Function declarations use _ARGS():

extern void baz _ARGS((int x,  int y));

   Function definitions in the *.c files use _ARGS#():

static struct mumblefrotzage *
foo _ARGS2(const char *,s, int,n)
{
 ...
}

int
main _ARGS3(int,argc, char**,argv, char**,env)
{
  struct mumblefrotzage *bar = foo ("example", 3);
  ...
}

   etags would extract "foo _ARGS2(" and "main _ARGS3(" as tag lines.
(find-tag) would find foo and main.

----------

Earlier in this thread, Dmitry suggested:
>>> Try adding `tag-symbol-match-p' to
>>> etags-xref-find-definitions-tag-order. This example should work
>>> then, but you'll get more false positives (like treating return
>>> types as function names).

to which Eli replied:
> Dmitry, how about providing a more user-friendly customization to that
> effect?  As a "fire escape"?

I initially replied to Dmitry's suggestion:
>> For the moment I think I'll just continue to use find-tag and hope
>> that xref-find-definitions will eventually work as well as find-tag
>> before find-tag disappears.

> I'd rather like to encourage you to continue using xref and report any
> issue you find.

   As you may have seen in my reply to Dmitry, I tried his suggestion,
and it seemed to fix the problem in the quick testing I tried, so I'm
willing to switch.

   The main issue I haven't gotten to yet is how best to change the
value of etags-xref-find-definitions-tag-order (exfdto) in a way that
will maximize long-term compatibility with future Emacs versions.  Doing
just (setq exfdto '(..)) in ~/.emacs I would expect to be the worst,
because either the default value or the symbol names might change in
future releases; (setq exfdto (append exfdto '(tag-symbol-match-p)))
might be better, but requires preloading etags.el to get the variable's
default value.  There are also onload hooks, site local lisp, etc.  It's
not yet clear to me what the best approach is, so I like your suggestion
to Dmitry above.  :)

> [The new xref function] is already better in several areas:

   I noticed that, and I liked seeing the list of matches when there's >1,
rather than having to do {arg} find-tag, possibly repeatedly, when the
one find-tag finds first isn't the one I wanted.  However, if the basic
find wasn't going to work, or was going to have a lot of false positives,
then I'd stick with find-tag, which has generally worked well (almost no
wrong matches, but it helps that my code tries to have all function
names in all files be unique, even when they're static, so there's
rarely >1 match).

> It is even possible that, given the details I requested above, I will
> be able to help you get your use case working with xref, so please
> don't give up on xref, not just yet.

   I haven't.  :)

   Thanks!  HTH,
 -WBE