IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2011
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2012
Free Software Foundation, Inc.
This file is not considered part of GNU Emacs.
# define NDEBUG /* disable assert */
#endif
-#ifdef HAVE_CONFIG_H
-# include <config.h>
- /* This is probably not necessary any more. On some systems, config.h
- used to define static as nothing for the sake of unexec. We don't
- want that here since we don't use unexec. None of these systems
- are supported any more, but the idea is still mentioned in
- etc/PROBLEMS. */
-# undef static
-# ifndef PTR /* for XEmacs */
-# define PTR void *
-# endif
-#else /* no config.h */
-# if defined (__STDC__) && (__STDC__ || defined (__SUNPRO_C))
-# define PTR void * /* for generic pointers */
-# else /* not standard C */
-# define const /* remove const for old compilers' sake */
-# define PTR long * /* don't use void* */
-# endif
-#endif /* !HAVE_CONFIG_H */
+#include <config.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
# include <fcntl.h>
# include <sys/param.h>
# include <io.h>
-# ifndef HAVE_CONFIG_H
-# define DOS_NT
-# include <sys/config.h>
-# endif
#else
# define MSDOS FALSE
#endif /* MSDOS */
# endif
#endif /* HAVE_UNISTD_H */
+#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <c-strcase.h>
#include <assert.h>
#ifdef NDEBUG
# include <getopt.h>
#endif /* NO_LONG_OPTIONS */
-#ifndef HAVE_CONFIG_H /* this is a standalone compilation */
-# ifdef __CYGWIN__ /* compiling on Cygwin */
- !!! NOTICE !!!
- the regex.h distributed with Cygwin is not compatible with etags, alas!
-If you want regular expression support, you should delete this notice and
- arrange to use the GNU regex.h and regex.c.
-# endif
-#endif
#include <regex.h>
/* Define CTAGS to make the program "ctags" compatible with the usual one.
#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 strcaseeq(s,t) (assert ((s)!=NULL && (t)!=NULL), !c_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 strncaseeq(s,t,n) (assert ((s)!=NULL && (t)!=NULL), !c_strncasecmp (s, t, n))
#define CHARS 256 /* 2^sizeof(char) */
#define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
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 force_explicit_name; /* do not allow implicit tag name */
bool ignore_case; /* ignore case when matching */
bool multi_line; /* do a multi-line match on the whole file */
} regexp;
static void analyse_regex (char *);
static void free_regexps (void);
static void regex_tag_multiline (void);
-static void error (const char *, const char *);
-static void suggest_asking_for_help (void) NO_RETURN;
-void fatal (const char *, const char *) NO_RETURN;
-static void pfatal (const char *) NO_RETURN;
+static void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
+static _Noreturn void suggest_asking_for_help (void);
+_Noreturn void fatal (const char *, const char *);
+static _Noreturn void pfatal (const char *);
static void add_node (node *, node **);
static void init (void);
static char *savestr (const char *);
static char *etags_strchr (const char *, int);
static char *etags_strrchr (const char *, int);
-static int etags_strcasecmp (const char *, const char *);
-static int etags_strncasecmp (const char *, const char *, int);
static char *etags_getcwd (void);
static char *relative_filename (char *, char *);
static char *absolute_filename (char *, char *);
static void canonicalize_filename (char *);
static void linebuffer_init (linebuffer *);
static void linebuffer_setlen (linebuffer *, int);
-static PTR xmalloc (size_t);
-static PTR xrealloc (char *, size_t);
+static void *xmalloc (size_t);
+static void *xrealloc (char *, size_t);
\f
static char searchar = '/'; /* use /.../ searches */
print_version (void)
{
/* Makes it easier to update automatically. */
- char emacs_copyright[] = "Copyright (C) 2011 Free Software Foundation, Inc.";
+ char emacs_copyright[] = "Copyright (C) 2012 Free Software Foundation, Inc.";
printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
puts (emacs_copyright);
case 'o':
if (tagfile)
{
- error ("-o option may only be given once.", (char *)NULL);
+ error ("-o option may only be given once.");
suggest_asking_for_help ();
/* NOTREACHED */
}
if (nincluded_files == 0 && file_count == 0)
{
- error ("no input files specified.", (char *)NULL);
+ error ("no input files specified.");
suggest_asking_for_help ();
/* NOTREACHED */
}
language *lang;
if (name == NULL)
- error ("empty language name", (char *)NULL);
+ error ("empty language name");
else
{
for (lang = lang_names; lang->name != NULL; lang++)
assert (parser != NULL);
- /* Generic initialisations before reading from file. */
+ /* Generic initializations before reading from file. */
linebuffer_setlen (&filebuf, 0); /* reset the file buffer */
- /* Generic initialisations before parsing file with readline. */
+ /* Generic initializations 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 */
* 4. the character, if any, immediately after NAME in LINESTART must
* also be a character in NONAM.
*
- * The implementation uses the notinname() macro, which recognises the
+ * The implementation uses the notinname() macro, which recognizes the
* characters stored in the string `nonam'.
* etags.el needs to use the same characters that are in NONAM.
*/
\f
static int total_size_of_entries (node *);
-static int number_len (long);
+static int number_len (long) ATTRIBUTE_CONST;
/* Length of a non-negative number's decimal representation. */
static int
{
/* Ctags mode */
if (np->name == NULL)
- error ("internal error: NULL name in ctags mode.", (char *)NULL);
+ error ("internal error: NULL name in ctags mode.");
if (cxref_style)
{
case dignorerest:
return FALSE;
default:
- error ("internal error: definedef value.", (char *)NULL);
+ error ("internal error: definedef value.");
}
/*
make_tag (token_name.buffer, token_name.len, isfun, token.line,
token.offset+token.length+1, token.lineno, token.linepos);
else if (DEBUG)
- { /* this branch is optimised away if !DEBUG */
+ { /* this branch is optimized away if !DEBUG */
make_tag (concat ("INVALID TOKEN:-->", token_name.buffer, ""),
token_name.len + 17, isfun, token.line,
token.offset+token.length+1, token.lineno, token.linepos);
- error ("INVALID TOKEN", NULL);
+ error ("INVALID TOKEN");
}
token.valid = FALSE;
}
continue;
}
- else if (bracketlev > 0)
- {
- switch (c)
- {
- case ']':
- if (--bracketlev > 0)
- continue;
- break;
- case '\0':
- CNL_SAVE_DEFINEDEF ();
- break;
- }
- continue;
- }
else switch (c)
{
case '"':
inquote = TRUE;
+ if (bracketlev > 0)
+ continue;
if (inattribute)
break;
switch (fvdef)
continue;
case '\'':
inchar = TRUE;
+ if (bracketlev > 0)
+ continue;
if (inattribute)
break;
- if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
+ if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
{
fvextern = FALSE;
fvdef = fvnone;
incomm = TRUE;
lp++;
c = ' ';
+ if (bracketlev > 0)
+ continue;
}
else if (/* cplpl && */ *lp == '/')
{
for (cp = newlb.buffer; cp < lp-1; cp++)
if (!iswhite (*cp))
{
- if (*cp == '*' && *(cp+1) == '/')
+ if (*cp == '*' && cp[1] == '/')
{
cp++;
cpptoken = TRUE;
continue;
case '[':
bracketlev++;
- continue;
+ continue;
+ default:
+ if (bracketlev > 0)
+ {
+ if (c == ']')
+ --bracketlev;
+ else if (c == '\0')
+ CNL_SAVE_DEFINEDEF ();
+ continue;
+ }
+ break;
} /* switch (c) */
if (c == ':' && *lp == ':' && begtoken (lp[1]))
/* This handles :: in the middle,
but not at the beginning of an identifier.
- Also, space-separated :: is not recognised. */
+ Also, space-separated :: is not recognized. */
{
if (c_ext & C_AUTO) /* automatic detection of C++ */
c_ext = (c_ext | C_PLPL) & ~C_AUTO;
{
static struct re_pattern_buffer zeropattern;
char sep, *pat, *name, *modifiers;
- char empty[] = "";
+ char empty = '\0';
const char *err;
struct re_pattern_buffer *patbuf;
regexp *rp;
if (strlen (regexp_pattern) < 3)
{
- error ("null regexp", (char *)NULL);
+ error ("null regexp");
return;
}
sep = regexp_pattern[0];
if (modifiers == NULL) /* no terminating separator --> no name */
{
modifiers = name;
- name = empty;
+ name = ∅
}
else
modifiers += 1; /* skip separator */
{
case 'N':
if (modifiers == name)
- error ("forcing explicit tag name but no name, ignoring", NULL);
+ error ("forcing explicit tag name but no name, ignoring");
force_explicit_name = TRUE;
break;
case 'i':
need_filebuf = TRUE;
break;
default:
- {
- char wrongmod [2];
- wrongmod[0] = modifiers[0];
- wrongmod[1] = '\0';
- error ("invalid regexp modifier `%s', ignoring", wrongmod);
- }
+ error ("invalid regexp modifier `%c', ignoring", modifiers[0]);
break;
}
if (!rp->multi_line)
continue; /* skip normal regexps */
- /* Generic initialisations before parsing file from memory. */
+ /* Generic initializations 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 */
return NULL;
}
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- *
- * Same as BSD's strcasecmp, included for portability.
- */
-static int
-etags_strcasecmp (register const char *s1, register const char *s2)
-{
- while (*s1 != '\0'
- && (ISALPHA (*s1) && ISALPHA (*s2)
- ? lowcase (*s1) == lowcase (*s2)
- : *s1 == *s2))
- 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 (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 (end of string is not space), return new pointer. */
static char *
skip_spaces (char *cp)
exit (EXIT_FAILURE);
}
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+/* Output a diagnostic with printf-style FORMAT and args. */
static void
-error (const char *s1, const char *s2)
+error (const char *format, ...)
{
+ va_list ap;
+ va_start (ap, format);
fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s1, s2);
+ vfprintf (stderr, format, ap);
fprintf (stderr, "\n");
+ va_end (ap);
}
/* Return a newly-allocated string whose contents
}
/* Like malloc but get fatal error if memory is exhausted. */
-static PTR
+static void *
xmalloc (size_t size)
{
- PTR result = (PTR) malloc (size);
+ void *result = malloc (size);
if (result == NULL)
fatal ("virtual memory exhausted", (char *)NULL);
return result;
}
-static PTR
+static void *
xrealloc (char *ptr, size_t size)
{
- PTR result = (PTR) realloc (ptr, size);
+ void *result = realloc (ptr, size);
if (result == NULL)
fatal ("virtual memory exhausted", (char *)NULL);
return result;