*
*/
-char pot_etags_version[] = "@(#) pot revision number is 16.32";
+char pot_etags_version[] = "@(#) pot revision number is 16.42";
#define TRUE 1
#define FALSE 0
#endif
#define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
+#define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
#define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
+#define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
#define CHARS 256 /* 2^sizeof(char) */
#define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
-#define iswhite(c) (_wht[CHAR(c)]) /* c is white */
-#define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
-#define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
-#define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
-#define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
+#define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
+#define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
+#define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
+#define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
+#define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
#define ISALNUM(c) isalnum (CHAR(c))
#define ISALPHA(c) isalpha (CHAR(c))
language *lang; /* language of file */
char *prop; /* file properties to write in tagfile */
bool usecharno; /* etags tags shall contain char number */
+ bool written; /* entry written in the tags file */
} fdesc;
typedef struct node_st
struct node_st *left, *right; /* left and right sons */
fdesc *fdp; /* description of file to whom tag belongs */
char *name; /* tag name */
- char *pat; /* search pattern */
+ char *regex; /* search regexp */
bool valid; /* write this tag on the tag file */
- bool is_func; /* function tag: use pattern in CTAGS mode */
+ bool is_func; /* function tag: use regexp in CTAGS mode */
bool been_warned; /* warning already given for duplicated tag */
int lno; /* line number tag is on */
long cno; /* character number line starts on */
#ifdef ETAGS_REGEXPS
/* Structure defining a regular expression. */
-typedef struct pattern
+typedef struct regexp
{
- struct pattern *p_next;
- language *lang;
- char *regex;
- struct re_pattern_buffer *pat;
- struct re_registers regs;
- char *name_pattern;
- bool error_signaled;
- bool ignore_case;
- bool multi_line;
-} pattern;
+ struct regexp *p_next; /* pointer to next in list */
+ language *lang; /* if set, use only for this language */
+ char *pattern; /* the regexp pattern */
+ char *name; /* tag name */
+ struct re_pattern_buffer *pat; /* the compiled pattern */
+ struct re_registers regs; /* re registers */
+ bool error_signaled; /* already signaled for this regexp */
+ bool force_explicit_name; /* do not allow implict tag name */
+ bool ignore_case; /* ignore case when matching */
+ bool multi_line; /* do a multi-line match on the whole file */
+} regexp;
#endif /* ETAGS_REGEXPS */
static void Cstar_entries __P((FILE *));
static void Erlang_functions __P((FILE *));
static void Fortran_functions __P((FILE *));
-static void Yacc_entries __P((FILE *));
+static void HTML_labels __P((FILE *));
static void Lisp_functions __P((FILE *));
static void Makefile_targets __P((FILE *));
static void Pascal_functions __P((FILE *));
static void Scheme_functions __P((FILE *));
static void TeX_commands __P((FILE *));
static void Texinfo_nodes __P((FILE *));
+static void Yacc_entries __P((FILE *));
static void just_read_file __P((FILE *));
static void print_language_names __P((void));
#ifdef ETAGS_REGEXPS
static void analyse_regex __P((char *));
-static void free_patterns __P((void));
+static void free_regexps __P((void));
static void regex_tag_multiline __P((void));
#endif /* ETAGS_REGEXPS */
static void error __P((const char *, const char *));
static void add_node __P((node *, node **));
static void init __P((void));
-static void initbuffer __P((linebuffer *));
static void process_file_name __P((char *, language *));
static void process_file __P((FILE *, char *, language *));
static void find_entries __P((FILE *));
static char *savestr __P((char *));
static char *etags_strchr __P((const char *, int));
static char *etags_strrchr __P((const char *, int));
-static bool strcaseeq __P((const char *, const char *));
+static int etags_strcasecmp __P((const char *, const char *));
+static int etags_strncasecmp __P((const char *, const char *, int));
static char *etags_getcwd __P((void));
static char *relative_filename __P((char *, char *));
static char *absolute_filename __P((char *, char *));
static char *absolute_dirname __P((char *, char *));
static bool filename_is_absolute __P((char *f));
static void canonicalize_filename __P((char *));
+static void linebuffer_init __P((linebuffer *));
static void linebuffer_setlen __P((linebuffer *, int));
static PTR xmalloc __P((unsigned int));
static PTR xrealloc __P((char *, unsigned int));
static linebuffer lb; /* the current line */
static linebuffer filebuf; /* a buffer containing the whole file */
+static linebuffer token_name; /* a buffer containing a tag name */
/* boolean "functions" (see init) */
static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
static bool parsing_stdin; /* --parse-stdin used */
#ifdef ETAGS_REGEXPS
-static pattern *p_head; /* list of all regexps */
+static regexp *p_head; /* list of all regexps */
static bool need_filebuf; /* some regexes are multi-line */
#else
# define need_filebuf FALSE
static char *Fortran_suffixes [] =
{ "F", "f", "f90", "for", NULL };
+static char *HTML_suffixes [] =
+ { "htm", "html", "shtml", NULL };
+
static char *Lisp_suffixes [] =
{ "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
{ "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL },
{ "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL },
{ "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL },
+ { "html", FALSE, HTML_labels, NULL, HTML_suffixes, NULL },
{ "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL },
{ "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL },
{ "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL },
init (); /* set up boolean "functions" */
- initbuffer (&lb);
- initbuffer (&filename_lb);
- initbuffer (&filebuf);
+ linebuffer_init (&lb);
+ linebuffer_init (&filename_lb);
+ linebuffer_init (&filebuf);
+ linebuffer_init (&token_name);
if (!CTAGS)
{
}
#ifdef ETAGS_REGEXPS
- free_patterns ();
+ free_regexps ();
#endif /* ETAGS_REGEXPS */
+ free (lb.buffer);
free (filebuf.buffer);
+ free (token_name.buffer);
if (!CTAGS || cxref_style)
{
free_tree (nodehead);
nodehead = NULL;
if (!CTAGS)
- while (nincluded_files-- > 0)
- fprintf (tagf, "\f\n%s,include\n", *included_files++);
+ {
+ fdesc *fdp;
+
+ /* Output file entries that have no tags. */
+ for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
+ if (!fdp->written)
+ fprintf (tagf, "\f\n%s,0\n", fdp->taggedfname);
+
+ while (nincluded_files-- > 0)
+ fprintf (tagf, "\f\n%s,include\n", *included_files++);
+ }
if (fclose (tagf) == EOF)
pfatal (tagfile);
}
fdp->usecharno = TRUE; /* use char position when making tags */
fdp->prop = NULL;
+ fdp->written = FALSE; /* not written on tags file yet */
fdhead = fdp;
curfdp = fdhead; /* the current file description */
assert (parser != NULL);
/* Generic initialisations before reading from file. */
- filebuf.len = 0; /* reset the file buffer */
+ linebuffer_setlen (&filebuf, 0); /* reset the file buffer */
/* Generic initialisations before parsing file with readline. */
lineno = 0; /* reset global line number */
int lno; /* line number */
long cno; /* character number */
{
- bool named = TRUE;
+ bool named = (name != NULL && namelen > 0);
- if (!CTAGS && name != NULL && namelen > 0)
+ if (!CTAGS && named) /* maybe set named to false */
+ /* Let's try to make an implicit tag name, that is, create an unnamed tag
+ such that etags.el can guess a name from it. */
{
int i;
register char *cp = name;
if (CTAGS && !cxref_style)
{
if (strlen (linestart) < 50)
- np->pat = concat (linestart, "$", "");
+ np->regex = concat (linestart, "$", "");
else
- np->pat = savenstr (linestart, 50);
+ np->regex = savenstr (linestart, 50);
}
else
- np->pat = savenstr (linestart, linelen);
+ np->regex = savenstr (linestart, linelen);
add_node (np, &nodehead);
}
free_tree (np->left);
if (np->name != NULL)
free (np->name);
- free (np->pat);
+ free (np->regex);
free (np);
np = node_right;
}
register int total = 0;
for (; np != NULL; np = np->right)
- {
- total += strlen (np->pat) + 1; /* pat\177 */
- if (np->name != NULL)
- total += strlen (np->name) + 1; /* name\001 */
- total += number_len ((long) np->lno) + 1; /* lno, */
- if (np->cno != invalidcharno) /* cno */
- total += number_len (np->cno);
- total += 1; /* newline */
- }
+ if (np->valid)
+ {
+ total += strlen (np->regex) + 1; /* pat\177 */
+ if (np->name != NULL)
+ total += strlen (np->name) + 1; /* name\001 */
+ total += number_len ((long) np->lno) + 1; /* lno, */
+ if (np->cno != invalidcharno) /* cno */
+ total += number_len (np->cno);
+ total += 1; /* newline */
+ }
return total;
}
fdp = np->fdp;
fprintf (tagf, "\f\n%s,%d\n",
fdp->taggedfname, total_size_of_entries (np));
+ fdp->written = TRUE;
}
- fputs (np->pat, tagf);
+ fputs (np->regex, tagf);
fputc ('\177', tagf);
if (np->name != NULL)
{
np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
else
fprintf (stdout, "%-16s %3d %-16s %s\n",
- np->name, np->lno, np->fdp->taggedfname, np->pat);
+ np->name, np->lno, np->fdp->taggedfname, np->regex);
}
else
{
putc (searchar, tagf);
putc ('^', tagf);
- for (sp = np->pat; *sp; sp++)
+ for (sp = np->regex; *sp; sp++)
{
if (*sp == '\\' || *sp == searchar)
putc ('\\', tagf);
long linepos;
char *line;
} token; /* latest token read */
-static linebuffer token_name; /* its name */
/*
* Variables and functions for dealing with nested structures.
struct tok savetoken; /* token saved during preprocessor handling */
- initbuffer (&token_name);
- initbuffer (&lbs[0].lb);
- initbuffer (&lbs[1].lb);
+ linebuffer_init (&lbs[0].lb);
+ linebuffer_init (&lbs[1].lb);
if (cstack.size == 0)
{
cstack.size = (DEBUG) ? 1 : 4;
} /* while not eof */
- free (token_name.buffer);
free (lbs[0].lb.buffer);
free (lbs[1].lb.buffer);
}
/*
* Ada parsing
* Original code by
- * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
+ * Philippe Waroquiers <philippe.waroquiers@eurocontrol.int> (1998)
*/
static void Ada_getit __P((FILE *, char *));
FILE *inf;
{
bool inquote = FALSE;
+ bool skip_till_semicolumn = FALSE;
LOOP_ON_INPUT_LINES (inf, lb, dbp)
{
continue;
}
+ if (skip_till_semicolumn)
+ {
+ if (*dbp == ';')
+ skip_till_semicolumn = FALSE;
+ dbp++;
+ continue; /* advance char */
+ }
+
/* Search for beginning of a token. */
if (!begtoken (*dbp))
{
else
break; /* from switch */
continue; /* advance char */
+
+ case 'u':
+ if (typedefs && !packages_only && nocase_tail ("use"))
+ {
+ /* when tagging types, avoid tagging use type Pack.Typename;
+ for this, we will skip everything till a ; */
+ skip_till_semicolumn = TRUE;
+ continue; /* advance char */
+ }
+
case 't':
if (!packages_only && nocase_tail ("task"))
Ada_getit (inf, "/k");
name = NULL; /* keep compiler quiet */
dbp = lb.buffer;
*dbp = '\0';
- initbuffer (&tline);
+ linebuffer_init (&tline);
incomment = inquote = FALSE;
found_tag = FALSE; /* have a proc name; check if extern */
}
else if (lowcase (*dbp) == 'f')
{
- if (nocase_tail ("forward")) /* check for forward reference */
+ if (nocase_tail ("forward")) /* check for forward reference */
{
found_tag = FALSE;
verify_tag = FALSE;
}
}
+\f
+/* Similar to LOOKING_AT but does not use notinname, does not skip */
+#define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \
+ (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
+ && ((cp) += sizeof(kw)-1)) /* skip spaces */
+
+/*
+ * HTML support.
+ * Contents of <title>, <h1>, <h2>, <h3> are tags.
+ * Contents of <a name=xxx> are tags with name xxx.
+ *
+ * Francesco Potortì, 2002.
+ */
+static void
+HTML_labels (inf)
+ FILE * inf;
+{
+ bool getnext = FALSE; /* next text outside of HTML tags is a tag */
+ bool ignoretag = FALSE; /* skip to the end of the current HTML tag */
+ bool inanchor = FALSE; /* inside an A HTML tag, looking for NAME= */
+ char *end;
+
+
+ linebuffer_setlen (&token_name, 0); /* no name in buffer */
+
+ LOOP_ON_INPUT_LINES (inf, lb, dbp)
+ {
+ for (;;) /* loop on the same line */
+
+ if (ignoretag) /* skip HTML tag */
+ {
+ while (*dbp != '\0' && *dbp != '>')
+ dbp++;
+ if (*dbp == '>')
+ {
+ dbp += 1;
+ ignoretag = FALSE;
+ continue; /* look on the same line */
+ }
+ break; /* go to next line */
+ }
+
+ else if (inanchor) /* look for "name=" */
+ {
+ while (*dbp != '\0' && *dbp != '>' && lowcase (*dbp) != 'n')
+ dbp++;
+ if (*dbp == '\0')
+ break; /* go to next line */
+ if (*dbp == '>')
+ {
+ dbp += 1;
+ inanchor = FALSE;
+ continue; /* look on the same line */
+ }
+ dbp += 1;
+ if (LOOKING_AT_NOCASE (dbp, "ame="))
+ {
+ bool quoted = (dbp[0] == '"');
+
+ if (quoted)
+ for (end = ++dbp; *end != '\0' && *end != '"'; end++)
+ continue;
+ else
+ for (end = dbp; *end != '\0' && intoken (*end); end++)
+ continue;
+ linebuffer_setlen (&token_name, end - dbp);
+ strncpy (token_name.buffer, dbp, end - dbp);
+ token_name.buffer[end - dbp] = '\0';
+
+ dbp = end;
+ inanchor = FALSE; /* we found what we looked for */
+ ignoretag = TRUE; /* skip to the end of the anchor */
+ getnext = TRUE; /* then grab the text */
+ continue; /* look on the same line */
+ }
+ }
+
+ else if (getnext) /* grab next tokens and tag them */
+ {
+ dbp = skip_spaces (dbp);
+ if (*dbp == '\0')
+ break; /* go to next line */
+ if (*dbp == '<')
+ {
+ if (lowcase (dbp[1]) == 'a' && !intoken (dbp[2]))
+ inanchor = TRUE;
+ else
+ ignoretag = TRUE;
+ continue; /* look on the same line */
+ }
+
+ for (end = dbp + 1; *end != '\0' && *end != '<'; end++)
+ continue;
+ make_tag (token_name.buffer, token_name.len, TRUE,
+ dbp, end - dbp, lineno, linecharno);
+ linebuffer_setlen (&token_name, 0); /* no name in buffer */
+ getnext = FALSE;
+ break; /* go to next line */
+ }
+
+ else /* look for an interesting HTML tag */
+ {
+ while (*dbp != '\0' && *dbp != '<')
+ dbp++;
+ if (*dbp == '\0')
+ break; /* go to next line */
+ dbp += 1;
+ if (lowcase (dbp[0]) == 'a' && !intoken (dbp[1]))
+ inanchor = TRUE;
+ else if (LOOKING_AT_NOCASE (dbp, "title>")
+ || LOOKING_AT_NOCASE (dbp, "h1>")
+ || LOOKING_AT_NOCASE (dbp, "h2>")
+ || LOOKING_AT_NOCASE (dbp, "h3>"))
+ {
+ getnext = TRUE;
+ continue; /* look on the same line */
+ }
+ }
+ }
+}
+
\f
/*
* Prolog support
{
if (regex_arg == NULL)
{
- free_patterns (); /* --no-regex: remove existing regexps */
+ free_regexps (); /* --no-regex: remove existing regexps */
return;
}
pfatal (regexfile);
return;
}
- initbuffer (®exbuf);
+ linebuffer_init (®exbuf);
while (readline_internal (®exbuf, regexfp) > 0)
analyse_regex (regexbuf.buffer);
free (regexbuf.buffer);
}
}
-/* Turn a name, which is an ed-style (but Emacs syntax) regular
- expression, into a real regular expression by compiling it. */
+/* Separate the regexp pattern, compile it,
+ and care for optional name and modifiers. */
static void
add_regex (regexp_pattern, lang)
char *regexp_pattern;
char sep, *pat, *name, *modifiers;
const char *err;
struct re_pattern_buffer *patbuf;
- pattern *pp;
- bool ignore_case, multi_line, single_line;
+ regexp *rp;
+ bool
+ force_explicit_name = TRUE, /* do not use implicit tag names */
+ ignore_case = FALSE, /* case is significant */
+ multi_line = FALSE, /* matches are done one line at a time */
+ single_line = FALSE; /* dot does not match newline */
if (strlen(regexp_pattern) < 3)
modifiers += 1; /* skip separator */
/* Parse regex modifiers. */
- ignore_case = FALSE; /* case is significant */
- multi_line = FALSE; /* matches are done one line at a time */
- single_line = FALSE; /* dot does not match newline */
for (; modifiers[0] != '\0'; modifiers++)
switch (modifiers[0])
{
+ case 'N':
+ if (modifiers == name)
+ error ("forcing explicit tag name but no name, ignoring", NULL);
+ force_explicit_name = TRUE;
+ break;
case 'i':
ignore_case = TRUE;
break;
return;
}
- pp = p_head;
- p_head = xnew (1, pattern);
- p_head->regex = savestr (regexp_pattern);
- p_head->p_next = pp;
+ rp = p_head;
+ p_head = xnew (1, regexp);
+ p_head->pattern = savestr (regexp_pattern);
+ p_head->p_next = rp;
p_head->lang = lang;
p_head->pat = patbuf;
- p_head->name_pattern = savestr (name);
+ p_head->name = savestr (name);
p_head->error_signaled = FALSE;
+ p_head->force_explicit_name = force_explicit_name;
p_head->ignore_case = ignore_case;
p_head->multi_line = multi_line;
}
return result;
}
-/* Deallocate all patterns. */
+/* Deallocate all regexps. */
static void
-free_patterns ()
+free_regexps ()
{
- pattern *pp;
+ regexp *rp;
while (p_head != NULL)
{
- pp = p_head->p_next;
- free (p_head->regex);
- free (p_head->name_pattern);
+ rp = p_head->p_next;
+ free (p_head->pattern);
+ free (p_head->name);
free (p_head);
- p_head = pp;
+ p_head = rp;
}
return;
}
regex_tag_multiline ()
{
char *buffer = filebuf.buffer;
- pattern *pp;
+ regexp *rp;
+ char *name;
- for (pp = p_head; pp != NULL; pp = pp->p_next)
+ for (rp = p_head; rp != NULL; rp = rp->p_next)
{
int match = 0;
- if (!pp->multi_line)
+ if (!rp->multi_line)
continue; /* skip normal regexps */
/* Generic initialisations before parsing file from memory. */
linecharno = 0; /* reset global char number of line start */
/* Only use generic regexps or those for the current language. */
- if (pp->lang != NULL && pp->lang != curfdp->lang)
+ if (rp->lang != NULL && rp->lang != curfdp->lang)
continue;
while (match >= 0 && match < filebuf.len)
{
- match = re_search (pp->pat, buffer, filebuf.len, charno,
- filebuf.len - match, &pp->regs);
+ match = re_search (rp->pat, buffer, filebuf.len, charno,
+ filebuf.len - match, &rp->regs);
switch (match)
{
case -2:
/* Some error. */
- if (!pp->error_signaled)
+ if (!rp->error_signaled)
{
error ("regexp stack overflow while matching \"%s\"",
- pp->regex);
- pp->error_signaled = TRUE;
+ rp->pattern);
+ rp->error_signaled = TRUE;
}
break;
case -1:
/* No match. */
break;
default:
- if (match == pp->regs.end[0])
+ if (match == rp->regs.end[0])
{
- if (!pp->error_signaled)
+ if (!rp->error_signaled)
{
error ("regexp matches the empty string: \"%s\"",
- pp->regex);
- pp->error_signaled = TRUE;
+ rp->pattern);
+ rp->error_signaled = TRUE;
}
match = -3; /* exit from while loop */
break;
}
/* Match occurred. Construct a tag. */
- while (charno < pp->regs.end[0])
+ while (charno < rp->regs.end[0])
if (buffer[charno++] == '\n')
lineno++, linecharno = charno;
- if (pp->name_pattern[0] != '\0')
- {
- /* 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)
- pfnote (name, TRUE, buffer + linecharno,
- charno - linecharno + 1, lineno, linecharno);
- }
+ name = rp->name;
+ if (name[0] != '\0')
+ /* Make a named tag. */
+ name = substitute (buffer, rp->name, &rp->regs);
+ if (rp->force_explicit_name)
+ /* Force explicit tag name, if a name is there. */
+ pfnote (name, TRUE, buffer + linecharno,
+ charno - linecharno + 1, lineno, linecharno);
else
- {
- /* Make an unnamed tag. */
- pfnote ((char *)NULL, TRUE, buffer + linecharno,
+ make_tag (name, strlen (name), TRUE, buffer + linecharno,
charno - linecharno + 1, lineno, linecharno);
- }
break;
}
}
*namepp = savenstr (bp, cp - bp);
}
-/* Initialize a linebuffer for use */
-static void
-initbuffer (lbp)
- linebuffer *lbp;
-{
- lbp->size = (DEBUG) ? 3 : 200;
- lbp->buffer = xnew (lbp->size, char);
- lbp->buffer[0] = '\0';
- lbp->len = 0;
-}
-
/*
* Read a line of text from `stream' into `lbp', excluding the
* newline or CR-NL, if any. Return the number of characters read from
fdhead->infabsdir = savestr (curfdp->infabsdir);
fdhead->taggedfname = taggedfname;
fdhead->usecharno = FALSE;
+ fdhead->prop = NULL;
+ fdhead->written = FALSE;
curfdp = fdhead;
}
}
#ifdef ETAGS_REGEXPS
{
int match;
- pattern *pp;
+ regexp *rp;
+ char *name;
- /* Match against relevant patterns. */
+ /* Match against relevant regexps. */
if (lbp->len > 0)
- for (pp = p_head; pp != NULL; pp = pp->p_next)
+ for (rp = p_head; rp != NULL; rp = rp->p_next)
{
/* Only use generic regexps or those for the current language.
Also do not use multiline regexps, which is the job of
regex_tag_multiline. */
- if ((pp->lang != NULL && pp->lang != fdhead->lang)
- || pp->multi_line)
+ if ((rp->lang != NULL && rp->lang != fdhead->lang)
+ || rp->multi_line)
continue;
- match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
+ match = re_match (rp->pat, lbp->buffer, lbp->len, 0, &rp->regs);
switch (match)
{
case -2:
/* Some error. */
- if (!pp->error_signaled)
+ if (!rp->error_signaled)
{
error ("regexp stack overflow while matching \"%s\"",
- pp->regex);
- pp->error_signaled = TRUE;
+ rp->pattern);
+ rp->error_signaled = TRUE;
}
break;
case -1:
break;
case 0:
/* Empty string matched. */
- if (!pp->error_signaled)
+ if (!rp->error_signaled)
{
- error ("regexp matches the empty string: \"%s\"",
- pp->regex);
- pp->error_signaled = TRUE;
+ error ("regexp matches the empty string: \"%s\"", rp->pattern);
+ rp->error_signaled = TRUE;
}
break;
default:
/* Match occurred. Construct a tag. */
- if (pp->name_pattern[0] != '\0')
- {
- /* 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)
- pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
- }
+ name = rp->name;
+ if (name[0] != '\0')
+ /* Make a named tag. */
+ name = substitute (lbp->buffer, rp->name, &rp->regs);
+ if (rp->force_explicit_name)
+ /* Force explicit tag name, if a name is there. */
+ pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
else
- {
- /* Make an unnamed tag. */
- pfnote ((char *)NULL, TRUE,
+ make_tag (name, strlen (name), TRUE,
lbp->buffer, match, lineno, linecharno);
- }
break;
}
}
}
/*
- * Return TRUE if the two strings are equal, ignoring case for alphabetic
- * characters.
+ * Compare two strings, ignoring case for alphabetic characters.
*
- * Analogous to BSD's strcasecmp, included for portability.
+ * Same as BSD's strcasecmp, included for portability.
*/
-static bool
-strcaseeq (s1, s2)
+static int
+etags_strcasecmp (s1, s2)
register const char *s1;
register const char *s2;
{
: *s1 == *s2))
s1++, s2++;
- return (*s1 == *s2);
+ return (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) - lowcase (*s2)
+ : *s1 - *s2);
+}
+
+/*
+ * Compare two strings, ignoring case for alphabetic characters.
+ * Stop after a given number of characters
+ *
+ * Same as BSD's strncasecmp, included for portability.
+ */
+static int
+etags_strncasecmp (s1, s2, n)
+ register const char *s1;
+ register const char *s2;
+ register int n;
+{
+ while (*s1 != '\0' && n-- > 0
+ && (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) == lowcase (*s2)
+ : *s1 == *s2))
+ s1++, s2++;
+
+ if (n < 0)
+ return 0;
+ else
+ return (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) - lowcase (*s2)
+ : *s1 - *s2);
}
/* Skip spaces, return new pointer. */
linebuffer path;
FILE *pipe;
- initbuffer (&path);
+ linebuffer_init (&path);
pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
if (pipe == NULL || readline_internal (&path, pipe) == 0)
pfatal ("pwd");
#endif
}
+\f
+/* Initialize a linebuffer for use */
+static void
+linebuffer_init (lbp)
+ linebuffer *lbp;
+{
+ lbp->size = (DEBUG) ? 3 : 200;
+ lbp->buffer = xnew (lbp->size, char);
+ lbp->buffer[0] = '\0';
+ lbp->len = 0;
+}
+
/* Set the minimum size of a string contained in a linebuffer. */
static void
linebuffer_setlen (lbp, toksize)
lbp->len = toksize;
}
-/* Like malloc but get fatal error if memory is exhausted. */
+/* Like malloc but get fatal error if memory is exhausted. */
static PTR
xmalloc (size)
unsigned int size;
* indent-tabs-mode: t
* tab-width: 8
* fill-column: 79
- * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "pattern")
+ * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")
* End:
*/