[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/lib-src/etags.c
From: |
Francesco Potortì |
Subject: |
[Emacs-diffs] Changes to emacs/lib-src/etags.c |
Date: |
Thu, 13 Jun 2002 06:44:17 -0400 |
Index: emacs/lib-src/etags.c
diff -c emacs/lib-src/etags.c:3.21 emacs/lib-src/etags.c:3.22
*** emacs/lib-src/etags.c:3.21 Thu Jun 6 18:37:28 2002
--- emacs/lib-src/etags.c Thu Jun 13 06:44:15 2002
***************
*** 2,22 ****
Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
Free Software Foundation, Inc. and Ken Arnold
! This file is not considered part of GNU Emacs.
! This program is free software; you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation; either version 2 of the License, or
! (at your option) any later version.
!
! This program is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program; if not, write to the Free Software Foundation,
! Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*
* Authors:
--- 2,22 ----
Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
Free Software Foundation, Inc. and Ken Arnold
! This file is not considered part of GNU Emacs.
! This program is free software; you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation; either version 2 of the License, or
! (at your option) any later version.
!
! This program is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program; if not, write to the Free Software Foundation,
! Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*
* Authors:
***************
*** 34,40 ****
* Francesco Potortì <address@hidden> has maintained it since 1993.
*/
! char pot_etags_version[] = "@(#) pot revision number is 16.10";
#define TRUE 1
#define FALSE 0
--- 34,40 ----
* Francesco Potortì <address@hidden> has maintained it since 1993.
*/
! char pot_etags_version[] = "@(#) pot revision number is 16.19";
#define TRUE 1
#define FALSE 0
***************
*** 288,294 ****
enum {
at_language, /* a language specification */
at_regexp, /* a regular expression */
- at_icregexp, /* same, but with case ignored */
at_filename, /* a file name */
at_stdin /* read from stdin here */
} arg_type; /* argument type */
--- 288,293 ----
***************
*** 308,313 ****
--- 307,313 ----
char *name_pattern;
bool error_signaled;
bool ignore_case;
+ bool multi_line;
} pattern;
#endif /* ETAGS_REGEXPS */
***************
*** 355,363 ****
static char *get_tag __P((char *));
#ifdef ETAGS_REGEXPS
! static void analyse_regex __P((char *, bool));
! static void add_regex __P((char *, bool, language *));
static void free_patterns __P((void));
#endif /* ETAGS_REGEXPS */
static void error __P((const char *, const char *));
static void suggest_asking_for_help __P((void));
--- 355,363 ----
static char *get_tag __P((char *));
#ifdef ETAGS_REGEXPS
! static void analyse_regex __P((char *));
static void free_patterns __P((void));
+ static void regex_tag_multiline __P((void));
#endif /* ETAGS_REGEXPS */
static void error __P((const char *, const char *));
static void suggest_asking_for_help __P((void));
***************
*** 417,422 ****
--- 417,423 ----
static node *last_node; /* the last node created */
static linebuffer lb; /* the current line */
+ static linebuffer filebuf; /* a buffer containing the whole file */
/* boolean "functions" (see init) */
static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
***************
*** 457,469 ****
static bool parsing_stdin; /* --parse-stdin used */
#ifdef ETAGS_REGEXPS
! /* List of all regexps. */
! static pattern *p_head;
!
! /* How many characters in the character set. (From regex.c.) */
! #define CHAR_SET_SIZE 256
! /* Translation table for case-insensitive matching. */
! static char lc_trans[CHAR_SET_SIZE];
#endif /* ETAGS_REGEXPS */
#ifdef LONG_OPTIONS
--- 458,467 ----
static bool parsing_stdin; /* --parse-stdin used */
#ifdef ETAGS_REGEXPS
! static pattern *p_head; /* list of all regexps */
! static bool need_filebuf; /* some regexes are multi-line */
! #else
! # define need_filebuf FALSE
#endif /* ETAGS_REGEXPS */
#ifdef LONG_OPTIONS
***************
*** 680,689 ****
}
#ifndef EMACS_NAME
! # define EMACS_NAME "GNU Emacs"
#endif
#ifndef VERSION
! # define VERSION "21"
#endif
static void
print_version ()
--- 678,687 ----
}
#ifndef EMACS_NAME
! # define EMACS_NAME "standalone"
#endif
#ifndef VERSION
! # define VERSION "version"
#endif
static void
print_version ()
***************
*** 775,783 ****
REGEXP is anchored (as if preceded by ^).\n\
The form /REGEXP/NAME/ creates a named tag.\n\
For example Tcl named tags can be created with:\n\
! --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\"");
! puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or address@hidden
! Like -r, --regex but ignore case when matching expressions.");
puts ("-R, --no-regex\n\
Don't create tags from regexps for the following files.");
#endif /* ETAGS_REGEXPS */
--- 773,783 ----
REGEXP is anchored (as if preceded by ^).\n\
The form /REGEXP/NAME/ creates a named tag.\n\
For example Tcl named tags can be created with:\n\
! --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".");
! puts ("In the form /REGEXP/MODS or /REGEXP/NAME/MODS, MODS are\n\
! one-letter modifiers: `i' means to ignore case, `m' means\n\
! allow multi-line matches, `s' implies `m' and additionally\n\
! causes dot to match the newline character.");
puts ("-R, --no-regex\n\
Don't create tags from regexps for the following files.");
#endif /* ETAGS_REGEXPS */
***************
*** 996,1009 ****
is small. */
argbuffer = xnew (argc, argument);
- #ifdef ETAGS_REGEXPS
- /* Set syntax for regular expression routines. */
- re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
- /* Translation table for case-insensitive search. */
- for (i = 0; i < CHAR_SET_SIZE; i++)
- lc_trans[i] = lowcase (i);
- #endif /* ETAGS_REGEXPS */
-
/*
* If etags, always find typedefs and structure tags. Why not?
* Also default to find macro constants, enum constants and
--- 996,1001 ----
***************
*** 1079,1084 ****
--- 1071,1080 ----
}
}
break;
+ case 'c':
+ /* Backward compatibility: support obsolete --ignore-case-regexp. */
+ optarg = concat (optarg, "i", ""); /* memory leak here */
+ /* FALLTHRU */
case 'r':
argbuffer[current_arg].arg_type = at_regexp;
argbuffer[current_arg].what = optarg;
***************
*** 1089,1099 ****
argbuffer[current_arg].what = NULL;
++current_arg;
break;
- case 'c':
- argbuffer[current_arg].arg_type = at_icregexp;
- argbuffer[current_arg].what = optarg;
- ++current_arg;
- break;
case 'V':
print_version ();
break;
--- 1085,1090 ----
***************
*** 1152,1157 ****
--- 1143,1149 ----
initbuffer (&lb);
initbuffer (&filename_lb);
+ initbuffer (&filebuf);
if (!CTAGS)
{
***************
*** 1186,1195 ****
break;
#ifdef ETAGS_REGEXPS
case at_regexp:
! analyse_regex (argbuffer[i].what, FALSE);
! break;
! case at_icregexp:
! analyse_regex (argbuffer[i].what, TRUE);
break;
#endif
case at_filename:
--- 1178,1184 ----
break;
#ifdef ETAGS_REGEXPS
case at_regexp:
! analyse_regex (argbuffer[i].what);
break;
#endif
case at_filename:
***************
*** 1234,1239 ****
--- 1223,1229 ----
#ifdef ETAGS_REGEXPS
free_patterns ();
#endif /* ETAGS_REGEXPS */
+ free (filebuf.buffer);
if (!CTAGS || cxref_style)
{
***************
*** 1648,1654 ****
FILE *inf;
{
char *cp;
- node *old_last_node;
language *lang = curfdp->lang;
Lang_function *parser = NULL;
--- 1638,1643 ----
***************
*** 1703,1709 ****
/* We rewind here, even if inf may be a pipe. We fail if the
length of the first line is longer than the pipe block size,
which is unlikely. */
! rewind (inf);
/* Else try to guess the language given the case insensitive file name. */
if (parser == NULL)
--- 1692,1698 ----
/* We rewind here, even if inf may be a pipe. We fail if the
length of the first line is longer than the pipe block size,
which is unlikely. */
! rewind (inf);
/* Else try to guess the language given the case insensitive file name. */
if (parser == NULL)
***************
*** 1716,1721 ****
--- 1705,1730 ----
}
}
+ /* Else try Fortran or C. */
+ if (parser == NULL)
+ {
+ node *old_last_node = last_node;
+
+ curfdp->lang = get_language_from_langname ("fortran");
+ find_entries (inf);
+
+ if (old_last_node == last_node)
+ /* No Fortran entries found. Try C. */
+ {
+ /* We do not tag if rewind fails.
+ Only the file name will be recorded in the tags file. */
+ rewind (inf);
+ curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
+ find_entries (inf);
+ }
+ return;
+ }
+
if (!no_line_directive
&& curfdp->lang != NULL && curfdp->lang->metasource)
/* It may be that this is a bingo.y file, and we already parsed a bingo.c
***************
*** 1748,1779 ****
fdpp = &(*fdpp)->next; /* advance the list pointer */
}
! if (parser != NULL)
! {
! /* Generic initialisations before reading from file. */
! lineno = 0; /* reset global line number */
! charno = 0; /* reset global char number */
! linecharno = 0; /* reset global char number of line start */
! parser (inf);
! return;
! }
! /* Else try Fortran. */
! old_last_node = last_node;
! curfdp->lang = get_language_from_langname ("fortran");
! find_entries (inf);
!
! if (old_last_node == last_node)
! /* No Fortran entries found. Try C. */
! {
! /* We do not tag if rewind fails.
! Only the file name will be recorded in the tags file. */
! rewind (inf);
! curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
! find_entries (inf);
! }
! return;
}
--- 1757,1777 ----
fdpp = &(*fdpp)->next; /* advance the list pointer */
}
! assert (parser != NULL);
! /* Generic initialisations before reading from file. */
! filebuf.len = 0; /* reset the file buffer */
! /* Generic initialisations before parsing file with readline. */
! lineno = 0; /* reset global line number */
! charno = 0; /* reset global char number */
! linecharno = 0; /* reset global char number of line start */
!
! parser (inf);
!
! #ifdef ETAGS_REGEXPS
! regex_tag_multiline ();
! #endif /* ETAGS_REGEXPS */
}
***************
*** 2014,2019 ****
--- 2012,2022 ----
* invalidate_nodes ()
* Scan the node tree and invalidate all nodes pointing to the
* given file description (CTAGS case) or free them (ETAGS case).
+ *
+ * This function most likely contains a bug, but I cannot tell where.
+ * I have a case of a binary that crashes inside this function with a bus
+ * error. Unfortunately, the binary does not contain debug information, and
+ * compiling with debugging information makes the bug disappear.
*/
static void
invalidate_nodes (badfdp, npp)
***************
*** 2030,2036 ****
if (np->left != NULL)
invalidate_nodes (badfdp, &np->left);
if (np->fdp == badfdp)
! np-> valid = FALSE;
if (np->right != NULL)
invalidate_nodes (badfdp, &np->right);
}
--- 2033,2039 ----
if (np->left != NULL)
invalidate_nodes (badfdp, &np->left);
if (np->fdp == badfdp)
! np->valid = FALSE;
if (np->right != NULL)
invalidate_nodes (badfdp, &np->right);
}
***************
*** 5263,5279 ****
#ifdef ETAGS_REGEXPS
static char *scan_separators __P((char *));
! static void analyse_regex __P((char *, bool));
! static void add_regex __P((char *, bool, language *));
static char *substitute __P((char *, char *, struct re_registers *));
! /* Take a string like "/blah/" and turn it into "blah", making sure
! that the first and last characters are the same, and handling
! quoted separator characters. Actually, stops on the occurrence of
! an unquoted separator. Also turns "\t" into a Tab character, and
! similarly for all character escape sequences supported by Gcc.
! Returns pointer to terminating separator. Works in place. Null
! terminates name string. */
static char *
scan_separators (name)
char *name;
--- 5266,5283 ----
#ifdef ETAGS_REGEXPS
static char *scan_separators __P((char *));
! static void add_regex __P((char *, language *));
static char *substitute __P((char *, char *, struct re_registers *));
! /*
! * Take a string like "/blah/" and turn it into "blah", verifying
! * that the first and last characters are the same, and handling
! * quoted separator characters. Actually, stops on the occurrence of
! * an unquoted separator. Also process \t, \n, etc. and turn into
! * appropriate characters. Works in place. Null terminates name string.
! * Returns pointer to terminating separator, or NULL for
! * unterminated regexps.
! */
static char *
scan_separators (name)
char *name;
***************
*** 5288,5302 ****
{
switch (*name)
{
! case 'a': *copyto++ = '\007'; break;
! case 'b': *copyto++ = '\b'; break;
! case 'd': *copyto++ = 0177; break;
! case 'e': *copyto++ = 033; break;
! case 'f': *copyto++ = '\f'; break;
! case 'n': *copyto++ = '\n'; break;
! case 'r': *copyto++ = '\r'; break;
! case 't': *copyto++ = '\t'; break;
! case 'v': *copyto++ = '\v'; break;
default:
if (*name == sep)
*copyto++ = sep;
--- 5292,5306 ----
{
switch (*name)
{
! case 'a': *copyto++ = '\007'; break; /* BEL (bell) */
! case 'b': *copyto++ = '\b'; break; /* BS (back space) */
! case 'd': *copyto++ = 0177; break; /* DEL (delete) */
! case 'e': *copyto++ = 033; break; /* ESC (delete) */
! case 'f': *copyto++ = '\f'; break; /* FF (form feed) */
! case 'n': *copyto++ = '\n'; break; /* NL (new line) */
! case 'r': *copyto++ = '\r'; break; /* CR (carriage return) */
! case 't': *copyto++ = '\t'; break; /* TAB (horizontal tab) */
! case 'v': *copyto++ = '\v'; break; /* VT (vertical tab) */
default:
if (*name == sep)
*copyto++ = sep;
***************
*** 5317,5322 ****
--- 5321,5328 ----
else
*copyto++ = *name;
}
+ if (*name != sep)
+ name = NULL; /* signal unterminated regexp */
/* Terminate copied string. */
*copyto = '\0';
***************
*** 5326,5334 ****
/* Look at the argument of --regex or --no-regex and do the right
thing. Same for each line of a regexp file. */
static void
! analyse_regex (regex_arg, ignore_case)
char *regex_arg;
- bool ignore_case;
{
if (regex_arg == NULL)
{
--- 5332,5339 ----
/* Look at the argument of --regex or --no-regex and do the right
thing. Same for each line of a regexp file. */
static void
! analyse_regex (regex_arg)
char *regex_arg;
{
if (regex_arg == NULL)
{
***************
*** 5362,5368 ****
}
initbuffer (®exbuf);
while (readline_internal (®exbuf, regexfp) > 0)
! analyse_regex (regexbuf.buffer, ignore_case);
free (regexbuf.buffer);
fclose (regexfp);
}
--- 5367,5373 ----
}
initbuffer (®exbuf);
while (readline_internal (®exbuf, regexfp) > 0)
! analyse_regex (regexbuf.buffer);
free (regexbuf.buffer);
fclose (regexfp);
}
***************
*** 5381,5397 ****
error ("unterminated language name in regex: %s", regex_arg);
return;
}
! *cp = '\0';
lang = get_language_from_langname (lang_name);
if (lang == NULL)
return;
! add_regex (cp + 1, ignore_case, lang);
}
break;
/* Regexp to be used for any language. */
default:
! add_regex (regex_arg, ignore_case, NULL);
break;
}
}
--- 5386,5402 ----
error ("unterminated language name in regex: %s", regex_arg);
return;
}
! *cp++ = '\0';
lang = get_language_from_langname (lang_name);
if (lang == NULL)
return;
! add_regex (cp, lang);
}
break;
/* Regexp to be used for any language. */
default:
! add_regex (regex_arg, NULL);
break;
}
}
***************
*** 5399,5435 ****
/* Turn a name, which is an ed-style (but Emacs syntax) regular
expression, into a real regular expression by compiling it. */
static void
! add_regex (regexp_pattern, ignore_case, lang)
char *regexp_pattern;
- bool ignore_case;
language *lang;
{
static struct re_pattern_buffer zeropattern;
! char *name;
const char *err;
struct re_pattern_buffer *patbuf;
pattern *pp;
! if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
{
! error ("%s: unterminated regexp", regexp_pattern);
return;
}
name = scan_separators (regexp_pattern);
! if (regexp_pattern[0] == '\0')
{
! error ("null regexp", (char *)NULL);
return;
}
! (void) scan_separators (name);
patbuf = xnew (1, struct re_pattern_buffer);
*patbuf = zeropattern;
if (ignore_case)
! patbuf->translate = lc_trans; /* translation table to fold case */
! err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
if (err != NULL)
{
error ("%s while compiling pattern", err);
--- 5404,5494 ----
/* Turn a name, which is an ed-style (but Emacs syntax) regular
expression, into a real regular expression by compiling it. */
static void
! add_regex (regexp_pattern, lang)
char *regexp_pattern;
language *lang;
{
static struct re_pattern_buffer zeropattern;
! char sep, *pat, *name, *modifiers;
const char *err;
struct re_pattern_buffer *patbuf;
pattern *pp;
+ bool ignore_case, multi_line, single_line;
! if (strlen(regexp_pattern) < 3)
{
! error ("null regexp", (char *)NULL);
return;
}
+ sep = regexp_pattern[0];
name = scan_separators (regexp_pattern);
! if (name == NULL)
{
! error ("%s: unterminated regexp", regexp_pattern);
! return;
! }
! if (name[1] == sep)
! {
! error ("null name for regexp \"%s\"", regexp_pattern);
return;
}
! modifiers = scan_separators (name);
! if (modifiers == NULL) /* no terminating separator --> no name */
! {
! modifiers = name;
! name = "";
! }
! else
! 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 'i':
! ignore_case = TRUE;
! break;
! case 's':
! single_line = TRUE;
! /* FALLTHRU */
! case 'm':
! multi_line = TRUE;
! need_filebuf = TRUE;
! break;
! default:
! modifiers[1] = '\0';
! error ("invalid regexp modifier `%s'", modifiers);
! return;
! }
patbuf = xnew (1, struct re_pattern_buffer);
*patbuf = zeropattern;
if (ignore_case)
! {
! static char lc_trans[CHARS];
! int i;
! for (i = 0; i < CHARS; i++)
! lc_trans[i] = lowcase (i);
! patbuf->translate = lc_trans; /* translation table to fold case */
! }
!
! if (multi_line)
! pat = concat ("^", regexp_pattern, ""); /* anchor to beginning of line */
! else
! pat = regexp_pattern;
! if (single_line)
! re_set_syntax (RE_SYNTAX_EMACS | RE_DOT_NEWLINE);
! else
! re_set_syntax (RE_SYNTAX_EMACS);
!
! err = re_compile_pattern (pat, strlen (regexp_pattern), patbuf);
! if (multi_line)
! free (pat);
if (err != NULL)
{
error ("%s while compiling pattern", err);
***************
*** 5445,5450 ****
--- 5504,5510 ----
p_head->name_pattern = savestr (name);
p_head->error_signaled = FALSE;
p_head->ignore_case = ignore_case;
+ p_head->multi_line = multi_line;
}
/*
***************
*** 5512,5517 ****
--- 5572,5663 ----
}
return;
}
+
+ /*
+ * Reads the whole file as a single string from `filebuf' and looks for
+ * multi-line regular expressions, creating tags on matches.
+ * readline already dealt with normal regexps.
+ *
+ * Idea by Ben Wing <address@hidden> (2002).
+ */
+ static void
+ regex_tag_multiline ()
+ {
+ char *buffer = filebuf.buffer;
+ pattern *pp;
+
+ for (pp = p_head; pp != NULL; pp = pp->p_next)
+ {
+ int match = 0;
+
+ if (!pp->multi_line)
+ continue; /* skip normal regexps */
+
+ /* Generic initialisations before parsing file from memory. */
+ lineno = 1; /* reset global line number */
+ charno = 0; /* reset global char number */
+ 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)
+ continue;
+
+ while (match >= 0 && match < filebuf.len)
+ {
+ match = re_search (pp->pat, buffer, filebuf.len, charno,
+ filebuf.len - match, &pp->regs);
+ switch (match)
+ {
+ case -2:
+ /* Some error. */
+ if (!pp->error_signaled)
+ {
+ error ("regexp stack overflow while matching \"%s\"",
+ pp->regex);
+ pp->error_signaled = TRUE;
+ }
+ break;
+ case -1:
+ /* No match. */
+ break;
+ default:
+ if (match == pp->regs.end[0])
+ {
+ if (!pp->error_signaled)
+ {
+ error ("regexp matches the empty string: \"%s\"",
+ pp->regex);
+ pp->error_signaled = TRUE;
+ }
+ match = -3; /* exit from while loop */
+ break;
+ }
+
+ /* Match occurred. Construct a tag. */
+ while (charno < pp->regs.end[0])
+ if (buffer[charno++] == '\n')
+ lineno++, linecharno = charno;
+ if (pp->name_pattern[0] != '\0')
+ {
+ /* Make a named tag. */
+ char *name = substitute (buffer,
+ pp->name_pattern, &pp->regs);
+ if (name != NULL)
+ pfnote (name, TRUE, buffer + linecharno,
+ charno - linecharno + 1, lineno, linecharno);
+ }
+ else
+ {
+ /* Make an unnamed tag. */
+ pfnote ((char *)NULL, TRUE, buffer + linecharno,
+ charno - linecharno + 1, lineno, linecharno);
+ }
+ break;
+ }
+ }
+ }
+ }
+
#endif /* ETAGS_REGEXPS */
***************
*** 5564,5573 ****
* newline or CR-NL, if any. Return the number of characters read from
* `stream', which is the length of the line including the newline.
*
! * On DOS or Windows we do not count the CR character, if any, before the
! * NL, in the returned length; this mirrors the behavior of emacs on those
* platforms (for text files, it translates CR-NL to NL as it reads in the
* file).
*/
static long
readline_internal (lbp, stream)
--- 5710,5722 ----
* newline or CR-NL, if any. Return the number of characters read from
* `stream', which is the length of the line including the newline.
*
! * On DOS or Windows we do not count the CR character, if any before the
! * NL, in the returned length; this mirrors the behavior of Emacs on those
* platforms (for text files, it translates CR-NL to NL as it reads in the
* file).
+ *
+ * If multi-line regular expressions are requested, each line read is
+ * appended to `filebuf'.
*/
static long
readline_internal (lbp, stream)
***************
*** 5626,5637 ****
}
lbp->len = p - buffer;
return lbp->len + chars_deleted;
}
/*
* Like readline_internal, above, but in addition try to match the
! * input line against relevant regular expressions.
*/
static void
readline (lbp, stream)
--- 5775,5802 ----
}
lbp->len = p - buffer;
+ if (need_filebuf /* we need filebuf for multi-line regexps */
+ && chars_deleted > 0) /* not at EOF */
+ {
+ while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
+ {
+ /* Expand filebuf. */
+ filebuf.size *= 2;
+ xrnew (filebuf.buffer, filebuf.size, char);
+ }
+ strncpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
+ filebuf.len += lbp->len;
+ filebuf.buffer[filebuf.len++] = '\n';
+ filebuf.buffer[filebuf.len] = '\0';
+ }
+
return lbp->len + chars_deleted;
}
/*
* Like readline_internal, above, but in addition try to match the
! * input line against relevant regular expressions and manage #line
! * directives.
*/
static void
readline (lbp, stream)
***************
*** 5752,5759 ****
{
if (result > 0)
{
! /* Do a tail recursion on ourselves, thus discarding the contents
! of the line buffer. */
readline (lbp, stream);
return;
}
--- 5917,5924 ----
{
if (result > 0)
{
! /* Do a tail recursion on ourselves, thus discarding the contents
! of the line buffer. */
readline (lbp, stream);
return;
}
***************
*** 5772,5779 ****
if (lbp->len > 0)
for (pp = p_head; pp != NULL; pp = pp->p_next)
{
! /* Only use generic regexps or those for the current language. */
! if (pp->lang != NULL && pp->lang != fdhead->lang)
continue;
match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
--- 5937,5947 ----
if (lbp->len > 0)
for (pp = p_head; pp != NULL; pp = pp->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)
continue;
match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
***************
*** 5783,5795 ****
/* Some error. */
if (!pp->error_signaled)
{
! error ("error while matching \"%s\"", pp->regex);
pp->error_signaled = TRUE;
}
break;
case -1:
/* No match. */
break;
default:
/* Match occurred. Construct a tag. */
if (pp->name_pattern[0] != '\0')
--- 5951,5973 ----
/* Some error. */
if (!pp->error_signaled)
{
! error ("regexp stack overflow while matching \"%s\"",
! pp->regex);
pp->error_signaled = TRUE;
}
break;
case -1:
/* No match. */
break;
+ case 0:
+ /* Empty string matched. */
+ if (!pp->error_signaled)
+ {
+ error ("regexp matches the empty string: \"%s\"",
+ pp->regex);
+ pp->error_signaled = TRUE;
+ }
+ break;
default:
/* Match occurred. Construct a tag. */
if (pp->name_pattern[0] != '\0')
***************
*** 6229,6234 ****
* indent-tabs-mode: t
* tab-width: 8
* fill-column: 79
! * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc"
"node")
* End:
*/
--- 6407,6412 ----
* indent-tabs-mode: t
* tab-width: 8
* fill-column: 79
! * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc"
"node" "pattern")
* End:
*/
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/05
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/05
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/05
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/06
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/06
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/06
- [Emacs-diffs] Changes to emacs/lib-src/etags.c,
Francesco Potortì <=
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/13
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/20
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/20
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/20
- [Emacs-diffs] Changes to emacs/lib-src/etags.c, Francesco Potortì, 2002/06/21