[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#5624: 23.1; etags elisp and scheme "=" in names
From: |
Alex |
Subject: |
bug#5624: 23.1; etags elisp and scheme "=" in names |
Date: |
Sun, 11 Jun 2017 20:44:29 -0600 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/25.1 (gnu/linux) |
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Alex <agrambot@gmail.com>
>> Date: Sat, 10 Jun 2017 19:37:49 -0600
>> Cc: 5624@debbugs.gnu.org
>> This appears to be because in etags.c, all languages use the same
>> `notinname' procedure to determine a valid identifier.
>
> Yes. But there are exceptions from this rule, where that is deemed
> necessary. For example, Ruby_functions has this:
>
> /* Ruby method names can end in a '='. Also, operator overloading can
> define operators whose names include '='. */
> while (!notinname (*cp) || *cp == '=')
> cp++;
>
>> Shouldn't each language (optionally) use a different procedure to
>> determine the bounds of an identifier? Lisp and Scheme, for instance,
>> would not have '=' in their respective `notinname' procedures.
>
> Feel free to work on this, if you want to scratch that particular
> itch. Alternatively, just augment notinname in language-specific
> support code, like some of the supported languages already do.
>
> TIA.
One issue is that the Lisp and Scheme functions use get_tag, which uses
notinname. What do you think about the following diff? It adds a wrapper
to notinname which get_tag uses. I had to add an additional parameter to
get_tag.
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 6f280d8ab4..e354325ad5 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -181,6 +181,20 @@ notinname (unsigned char c)
return table[c];
}
+/* C is not in a name in language LANG. */
+static bool
+notinname_lang (unsigned char c, char const *lang)
+{
+ if (lang == NULL)
+ return notinname (c);
+
+ else if (streq ("lisp", lang) || streq ("scheme", lang))
+ if (c == '=')
+ return false;
+
+ return notinname (c);
+}
+
/* C can start a token. */
static bool
begtoken (unsigned char c)
@@ -371,7 +385,7 @@ static language *get_language_from_langname (const char *);
static void readline (linebuffer *, FILE *);
static long readline_internal (linebuffer *, FILE *, char const *);
static bool nocase_tail (const char *);
-static void get_tag (char *, char **);
+static void get_tag (char *, char **, char const *);
static void analyze_regex (char *);
static void free_regexps (void);
@@ -4715,7 +4729,7 @@ Perl_functions (FILE *inf)
if (LOOKING_AT (cp, "package"))
{
free (package);
- get_tag (cp, &package);
+ get_tag (cp, &package, NULL);
}
else if (LOOKING_AT (cp, "sub"))
{
@@ -5346,7 +5360,7 @@ L_getit (void)
/* Ok, then skip "(" before name in (defstruct (foo)) */
dbp = skip_spaces (dbp);
}
- get_tag (dbp, NULL);
+ get_tag (dbp, NULL, "lisp");
}
static void
@@ -5426,7 +5440,7 @@ Lua_functions (FILE *inf)
{
char *tag_name, *tp_dot, *tp_colon;
- get_tag (bp, &tag_name);
+ get_tag (bp, &tag_name, NULL);
/* If the tag ends with ".foo" or ":foo", make an additional tag for
"foo". */
tp_dot = strrchr (tag_name, '.');
@@ -5436,7 +5450,7 @@ Lua_functions (FILE *inf)
char *p = tp_dot > tp_colon ? tp_dot : tp_colon;
int len_add = p - tag_name + 1;
- get_tag (bp + len_add, NULL);
+ get_tag (bp + len_add, NULL, NULL);
}
}
}
@@ -5468,7 +5482,7 @@ PS_functions (FILE *inf)
lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
}
else if (LOOKING_AT (bp, "defineps"))
- get_tag (bp, NULL);
+ get_tag (bp, NULL, NULL);
}
}
@@ -5550,12 +5564,12 @@ Scheme_functions (FILE *inf)
bp = skip_non_spaces (bp+4);
/* Skip over open parens and white space. Don't continue past
'\0'. */
- while (*bp && notinname (*bp))
+ while (*bp && notinname_lang (*bp, "scheme"))
bp++;
- get_tag (bp, NULL);
+ get_tag (bp, NULL, "scheme");
}
if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!"))
- get_tag (bp, NULL);
+ get_tag (bp, NULL, "scheme");
}
}
@@ -6573,14 +6587,14 @@ nocase_tail (const char *cp)
}
static void
-get_tag (register char *bp, char **namepp)
+get_tag (register char *bp, char **namepp, char const *lang)
{
register char *cp = bp;
if (*bp != '\0')
{
/* Go till you get to white space or a syntactic break */
- for (cp = bp + 1; !notinname (*cp); cp++)
+ for (cp = bp + 1; !notinname_lang (*cp, lang); cp++)
continue;
make_tag (bp, cp - bp, true,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);