*
*/
-char pot_etags_version[] = "@(#) pot revision number is 16.29";
+char pot_etags_version[] = "@(#) pot revision number is 16.32";
#define TRUE 1
#define FALSE 0
static void readline __P((linebuffer *, FILE *));
static long readline_internal __P((linebuffer *, FILE *));
static bool nocase_tail __P((char *));
-static char *get_tag __P((char *));
+static void get_tag __P((char *, char **));
#ifdef ETAGS_REGEXPS
static void analyse_regex __P((char *));
}
\f
-/* Record a tag. */
-static void
-pfnote (name, is_func, linestart, linelen, lno, cno)
- char *name; /* tag name, or NULL if unnamed */
- bool is_func; /* tag is a function */
- char *linestart; /* start of the line where tag is */
- int linelen; /* length of the line where tag is */
- int lno; /* line number */
- long cno; /* character number */
-{
- register node *np;
-
- if (CTAGS && name == NULL)
- return;
-
- np = xnew (1, node);
-
- /* If ctags mode, change name "main" to M<thisfilename>. */
- if (CTAGS && !cxref_style && streq (name, "main"))
- {
- register char *fp = etags_strrchr (curfdp->taggedfname, '/');
- np->name = concat ("M", fp == NULL ? curfdp->taggedfname : fp + 1, "");
- fp = etags_strrchr (np->name, '.');
- if (fp != NULL && fp[1] != '\0' && fp[2] == '\0')
- fp[0] = '\0';
- }
- else
- np->name = name;
- np->valid = TRUE;
- np->been_warned = FALSE;
- np->fdp = curfdp;
- np->is_func = is_func;
- np->lno = lno;
- if (np->fdp->usecharno)
- /* Our char numbers are 0-base, because of C language tradition?
- ctags compatibility? old versions compatibility? I don't know.
- Anyway, since emacs's are 1-base we expect etags.el to take care
- of the difference. If we wanted to have 1-based numbers, we would
- uncomment the +1 below. */
- np->cno = cno /* + 1 */ ;
- else
- np->cno = invalidcharno;
- np->left = np->right = NULL;
- if (CTAGS && !cxref_style)
- {
- if (strlen (linestart) < 50)
- np->pat = concat (linestart, "$", "");
- else
- np->pat = savenstr (linestart, 50);
- }
- else
- np->pat = savenstr (linestart, linelen);
-
- add_node (np, &nodehead);
-}
-
/*
* Check whether an implicitly named tag should be created,
* then call `pfnote'.
*
* TAGS format specification
* Idea by Sam Kendall <kendall@mv.mv.com> (1997)
+ * The following is explained in some more detail in etc/ETAGS.EBNF.
*
* make_tag creates tags with "implicit tag names" (unnamed tags)
* if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
{
bool named = TRUE;
- if (!CTAGS)
+ if (!CTAGS && name != NULL && namelen > 0)
{
int i;
register char *cp = name;
pfnote (name, is_func, linestart, linelen, lno, cno);
}
+/* Record a tag. */
+static void
+pfnote (name, is_func, linestart, linelen, lno, cno)
+ char *name; /* tag name, or NULL if unnamed */
+ bool is_func; /* tag is a function */
+ char *linestart; /* start of the line where tag is */
+ int linelen; /* length of the line where tag is */
+ int lno; /* line number */
+ long cno; /* character number */
+{
+ register node *np;
+
+ if (CTAGS && name == NULL)
+ return;
+
+ np = xnew (1, node);
+
+ /* If ctags mode, change name "main" to M<thisfilename>. */
+ if (CTAGS && !cxref_style && streq (name, "main"))
+ {
+ register char *fp = etags_strrchr (curfdp->taggedfname, '/');
+ np->name = concat ("M", fp == NULL ? curfdp->taggedfname : fp + 1, "");
+ fp = etags_strrchr (np->name, '.');
+ if (fp != NULL && fp[1] != '\0' && fp[2] == '\0')
+ fp[0] = '\0';
+ }
+ else
+ np->name = name;
+ np->valid = TRUE;
+ np->been_warned = FALSE;
+ np->fdp = curfdp;
+ np->is_func = is_func;
+ np->lno = lno;
+ if (np->fdp->usecharno)
+ /* Our char numbers are 0-base, because of C language tradition?
+ ctags compatibility? old versions compatibility? I don't know.
+ Anyway, since emacs's are 1-base we expect etags.el to take care
+ of the difference. If we wanted to have 1-based numbers, we would
+ uncomment the +1 below. */
+ np->cno = cno /* + 1 */ ;
+ else
+ np->cno = invalidcharno;
+ np->left = np->right = NULL;
+ if (CTAGS && !cxref_style)
+ {
+ if (strlen (linestart) < 50)
+ np->pat = concat (linestart, "$", "");
+ else
+ np->pat = savenstr (linestart, 50);
+ }
+ else
+ np->pat = savenstr (linestart, linelen);
+
+ add_node (np, &nodehead);
+}
+
/*
* free_tree ()
* recurse on left children, iterate on right children.
return;
for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++)
continue;
- pfnote (savenstr (dbp, cp-dbp), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (dbp, cp-dbp, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
{
dbp = skip_spaces (dbp);
if (*dbp == '\0') /* assume un-named */
- pfnote (savestr ("blockdata"), TRUE,
- lb.buffer, dbp - lb.buffer, lineno, linecharno);
+ make_tag ("blockdata", 9, TRUE,
+ lb.buffer, dbp - lb.buffer, lineno, linecharno);
else
F_getit (inf); /* look for name */
}
*cp = '\0';
name = concat (dbp, name_qualifier, "");
*cp = c;
- pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, strlen (name), TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ free (name);
if (c == '"')
dbp = cp + 1;
return;
while (ISALNUM (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
cp++;
if (*cp == ':' || iswhite (*cp))
- {
- /* Found end of label, so copy it and add it to the table. */
- pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE,
+ /* Found end of label, so copy it and add it to the table. */
+ make_tag (lb.buffer, cp - lb.buffer, TRUE,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- }
}
}
}
if (LOOKING_AT (cp, "package"))
{
free (package);
- package = get_tag (cp);
- if (package == NULL) /* can't parse package name */
- package = savestr ("");
- else
- package = savestr(package); /* make a copy */
+ get_tag (cp, &package);
}
else if (LOOKING_AT (cp, "sub"))
{
- char *name, *fullname, *pos;
+ char *pos;
char *sp = cp;
while (!notinname (*cp))
cp++;
if (cp == sp)
- continue;
- name = savenstr (sp, cp-sp);
- if ((pos = etags_strchr (name, ':')) != NULL && pos[1] == ':')
- fullname = name;
+ continue; /* nothing found */
+ if ((pos = etags_strchr (sp, ':')) != NULL
+ && pos < cp && pos[1] == ':')
+ /* The name is already qualified. */
+ make_tag (sp, cp - sp, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
else
- fullname = concat (package, "::", name);
- pfnote (fullname, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- if (name != fullname)
- free (name);
+ /* Qualify it. */
+ {
+ char savechar, *name;
+
+ savechar = *cp;
+ *cp = '\0';
+ name = concat (package, "::", sp);
+ *cp = savechar;
+ make_tag (name, strlen(name), TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ free (name);
+ }
}
- else if (globals /* only if tagging global vars is enabled */
- && (LOOKING_AT (cp, "my") || LOOKING_AT (cp, "local")))
+ else if (globals) /* only if we are tagging global vars */
{
+ /* Skip a qualifier, if any. */
+ bool qual = LOOKING_AT (cp, "my") || LOOKING_AT (cp, "local");
/* After "my" or "local", but before any following paren or space. */
- char *varname = NULL;
+ char *varstart = cp;
- if (*cp == '$' || *cp == '@' || *cp == '%')
+ if (qual /* should this be removed? If yes, how? */
+ && (*cp == '$' || *cp == '@' || *cp == '%'))
{
- char* varstart = ++cp;
- while (ISALNUM (*cp) || *cp == '_')
+ varstart += 1;
+ do
cp++;
- varname = savenstr (varstart, cp-varstart);
+ while (ISALNUM (*cp) || *cp == '_');
}
- else
+ else if (qual)
{
/* Should be examining a variable list at this point;
could insist on seeing an open parenthesis. */
while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
cp++;
}
+ else
+ continue;
- /* Perhaps I should back cp up one character, so the TAGS table
- doesn't mention (and so depend upon) the following char. */
- pfnote (varname, FALSE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (varstart, cp - varstart, FALSE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
}
}
char *name = cp;
while (!notinname (*cp) && *cp != ':')
cp++;
- pfnote (savenstr (name, cp-name), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
}
}
{
while (!notinname (*cp))
cp++;
- pfnote (savenstr (name, cp-name), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
search_identifier = FALSE;
}
else if (LOOKING_AT (cp, "function"))
name = cp;
while (!notinname (*cp))
cp++;
- pfnote (savenstr (name, cp-name), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
else
search_identifier = TRUE;
name = cp;
while (*cp != '\0' && !iswhite (*cp))
cp++;
- pfnote (savenstr (name, cp-name), FALSE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, FALSE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
else
search_identifier = TRUE;
name = cp;
while (*cp != quote && *cp != '\0')
cp++;
- pfnote (savenstr (name, cp-name), FALSE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, FALSE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
else if (members
&& LOOKING_AT (cp, "var")
name = cp;
while (!notinname(*cp))
cp++;
- pfnote (savenstr (name, cp-name), FALSE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (name, cp - name, FALSE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
}
}
for (ep = bp; ISALNUM (*ep) || *ep == '-'; ep++)
continue;
if (*ep++ == '.')
- pfnote (savenstr (bp, ep-bp), TRUE,
- lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
+ make_tag (bp, ep - bp, TRUE,
+ lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
}
}
while (*bp != '\0' && *bp != '=' && *bp != ':')
bp++;
if (*bp == ':' || (globals && *bp == '='))
- pfnote (savenstr (lb.buffer, bp - lb.buffer), TRUE,
- lb.buffer, bp - lb.buffer + 1, lineno, linecharno);
+ make_tag (lb.buffer, bp - lb.buffer, TRUE,
+ lb.buffer, bp - lb.buffer + 1, lineno, linecharno);
}
}
{
linebuffer tline; /* mostly copied from C_entries */
long save_lcno;
- int save_lineno, save_len;
- char c, *cp, *namebuf;
+ int save_lineno, namelen, taglen;
+ char c, *name;
bool /* each of these flags is TRUE iff: */
incomment, /* point is inside a comment */
is a FORWARD/EXTERN to be ignored, or
whether it is a real tag */
- save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
- namebuf = NULL; /* keep compiler quiet */
+ save_lcno = save_lineno = namelen = taglen = 0; /* keep compiler quiet */
+ name = NULL; /* keep compiler quiet */
dbp = lb.buffer;
*dbp = '\0';
initbuffer (&tline);
incomment = inquote = FALSE;
found_tag = FALSE; /* have a proc name; check if extern */
- get_tagname = FALSE; /* have found "procedure" keyword */
+ get_tagname = FALSE; /* found "procedure" keyword */
inparms = FALSE; /* found '(' after "proc" */
verify_tag = FALSE; /* check if "extern" is ahead */
}
if (found_tag && verify_tag && (*dbp != ' '))
{
- /* check if this is an "extern" declaration */
+ /* Check if this is an "extern" declaration. */
if (*dbp == '\0')
continue;
if (lowcase (*dbp == 'e'))
{
found_tag = FALSE;
verify_tag = FALSE;
- pfnote (namebuf, TRUE,
- tline.buffer, save_len, save_lineno, save_lcno);
+ make_tag (name, namelen, TRUE,
+ tline.buffer, taglen, save_lineno, save_lcno);
continue;
}
}
if (get_tagname) /* grab name of proc or fn */
{
+ char *cp;
+
if (*dbp == '\0')
continue;
- /* save all values for later tagging */
+ /* Find block name. */
+ for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
+ continue;
+
+ /* Save all values for later tagging. */
linebuffer_setlen (&tline, lb.len);
strcpy (tline.buffer, lb.buffer);
save_lineno = lineno;
save_lcno = linecharno;
+ name = tline.buffer + (dbp - lb.buffer);
+ namelen = cp - dbp;
+ taglen = cp - lb.buffer + 1;
- /* grab block name */
- for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
- continue;
- namebuf = savenstr (dbp, cp-dbp);
dbp = cp; /* set dbp to e-o-token */
- save_len = dbp - lb.buffer + 1;
get_tagname = FALSE;
found_tag = TRUE;
continue;
- /* and proceed to check for "extern" */
+ /* And proceed to check for "extern". */
}
else if (!incomment && !inquote && !found_tag)
{
- /* check for proc/fn keywords */
+ /* Check for proc/fn keywords. */
switch (lowcase (c))
{
case 'p':
continue;
}
}
- } /* while not eof */
+ } /* while not eof */
free (tline.buffer);
}
/* Ok, then skip "(" before name in (defstruct (foo)) */
dbp = skip_spaces (dbp);
}
- get_tag (dbp);
+ get_tag (dbp, NULL);
}
static void
*ep != '\0' && *ep != ' ' && *ep != '{';
ep++)
continue;
- pfnote (savenstr (bp, ep-bp), TRUE,
- lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
+ make_tag (bp, ep - bp, TRUE,
+ lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
}
else if (LOOKING_AT (bp, "defineps"))
- get_tag (bp);
+ get_tag (bp, NULL);
}
}
/* Skip over open parens and white space */
while (notinname (*bp))
bp++;
- get_tag (bp);
+ get_tag (bp, NULL);
}
if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!"))
- get_tag (bp);
+ get_tag (bp, NULL);
}
}
if (strneq (cp, key->buffer, key->len))
{
register char *p;
- char *name;
- int linelen;
+ int namelen, linelen;
bool opgrp = FALSE;
cp = skip_spaces (cp + key->len);
*p != TEX_opgrp && *p != TEX_clgrp);
p++)
continue;
- name = savenstr (cp, p-cp);
+ namelen = p - cp;
linelen = lb.len;
if (!opgrp || *p == TEX_clgrp)
{
*p++;
linelen = p - lb.buffer + 1;
}
- pfnote (name, TRUE, lb.buffer, linelen, lineno, linecharno);
+ make_tag (cp, namelen, TRUE,
+ lb.buffer, linelen, lineno, linecharno);
goto tex_next_line; /* We only tag a line once */
}
}
start = cp;
while (*cp != '\0' && *cp != ',')
cp++;
- pfnote (savenstr (start, cp - start), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ make_tag (start, cp - start, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
}
|| len != strlen (last)
|| !strneq (s, last, len)))
{
- pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
+ make_tag (s, len, TRUE, s, pos, lineno, linecharno);
return len;
}
else
|| len != (int)strlen (last)
|| !strneq (s, last, len)))
{
- pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
+ make_tag (s, len, TRUE, s, pos, lineno, linecharno);
return len;
}
{
int len = erlang_atom (skip_spaces (cp));
if (len > 0)
- pfnote (savenstr (cp, len), TRUE,
- s, cp + len - s, lineno, linecharno);
+ make_tag (cp, len, TRUE, s, cp + len - s, lineno, linecharno);
}
return;
}
lineno++, linecharno = charno;
if (pp->name_pattern[0] != '\0')
{
- /* Make a named tag. */
+ /* Make a named tag.
+ Do not use make_tag here, as it would make the name
+ implicit if possible, while we want to respect the user's
+ request to create an explicit tag name. */
char *name = substitute (buffer,
pp->name_pattern, &pp->regs);
if (name != NULL)
return FALSE;
}
-static char *
-get_tag (bp)
+static void
+get_tag (bp, namepp)
register char *bp;
+ char **namepp;
{
- register char *cp, *name;
+ register char *cp = bp;
- if (*bp == '\0')
- return NULL;
- /* Go till you get to white space or a syntactic break */
- for (cp = bp + 1; !notinname (*cp); cp++)
- continue;
- name = savenstr (bp, cp-bp);
- pfnote (name, TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- return name;
+ if (*bp != '\0')
+ {
+ /* Go till you get to white space or a syntactic break */
+ for (cp = bp + 1; !notinname (*cp); cp++)
+ continue;
+ make_tag (bp, cp - bp, TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ }
+
+ if (namepp != NULL)
+ *namepp = savenstr (bp, cp - bp);
}
/* Initialize a linebuffer for use */
/* Match occurred. Construct a tag. */
if (pp->name_pattern[0] != '\0')
{
- /* Make a named tag. */
+ /* Make a named tag.
+ Do not use make_tag here, as it would make the name
+ implicit if possible, while we want to respect the user's
+ request to create an explicit tag name. */
char *name = substitute (lbp->buffer,
pp->name_pattern, &pp->regs);
if (name != NULL)