/* Tags file maker to go with GNU Emacs
- Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98
+ Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98, 99
Free Software Foundation, Inc. and Ken Arnold
This file is not considered part of GNU Emacs.
* Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
* Regexp tags by Tom Tromey.
*
- * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
+ * Francesco Potorti` (pot@gnu.org) is the current maintainer.
+ * Ansified by Martin Buchholz, 19991105.
*/
-char pot_etags_version[] = "@(#) pot revision number is 13.7";
+char pot_etags_version[] = "@(#) pot revision number is 13.33";
#define TRUE 1
#define FALSE 0
# define DEBUG FALSE
#endif
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+ /* On some systems, Emacs defines static as nothing for the sake
+ of unexec. We don't want that here since we don't use unexec. */
+# undef static
+# define ETAGS_REGEXPS /* use the regexp features */
+# define LONG_OPTIONS /* accept long options */
+#endif /* HAVE_CONFIG_H */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
+#endif
+
#ifdef MSDOS
# include <fcntl.h>
# include <sys/param.h>
# undef HAVE_NTGUI
# else
# define DOS_NT
-# define HAVE_GETCWD
# endif /* not HAVE_CONFIG_H */
+# ifndef HAVE_GETCWD
+# define HAVE_GETCWD
+# endif /* undef HAVE_GETCWD */
#endif /* WINDOWSNT */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
- /* On some systems, Emacs defines static as nothing for the sake
- of unexec. We don't want that here since we don't use unexec. */
-# undef static
-# define ETAGS_REGEXPS /* use the regexp features */
-# define LONG_OPTIONS /* accept long options */
-#endif /* HAVE_CONFIG_H */
-
#if !defined (WINDOWSNT) && defined (STDC_HEADERS)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
-#ifndef errno
- extern int errno;
-#endif
#include <sys/types.h>
#include <sys/stat.h>
typedef struct
{
char *suffix;
- int sufflen;
char *command; /* Takes one arg and decompresses to stdout */
} compressor;
char **interpreters;
} language;
-extern char *getenv ();
-
-/* Many compilers barf on this:
- Lang_function Asm_labels;
- so let's write it this way */
-void Asm_labels ();
-void C_entries ();
-void default_C_entries ();
-void plain_C_entries ();
-void Cjava_entries ();
-void Cobol_paragraphs ();
-void Cplusplus_entries ();
-void Cstar_entries ();
-void Erlang_functions ();
-void Fortran_functions ();
-void Yacc_entries ();
-void Lisp_functions ();
-void Pascal_functions ();
-void Perl_functions ();
-void Postscript_functions ();
-void Prolog_functions ();
-void Python_functions ();
-void Scheme_functions ();
-void TeX_functions ();
-void just_read_file ();
-
-compressor *get_compressor_from_suffix ();
-language *get_language_from_name ();
-language *get_language_from_interpreter ();
-language *get_language_from_suffix ();
-int total_size_of_entries ();
-long readline (), readline_internal ();
-#ifdef ETAGS_REGEXPS
-void analyse_regex ();
-void add_regex ();
-void free_patterns ();
-#endif /* ETAGS_REGEXPS */
-void error ();
-void suggest_asking_for_help ();
-void fatal (), pfatal ();
-void add_node ();
-
-void init ();
-void initbuffer ();
-void find_entries ();
-void free_tree ();
-void pfnote (), new_pfnote ();
-void process_file ();
-void put_entries ();
-void takeprec ();
-
-char *concat ();
-char *skip_spaces (), *skip_non_spaces ();
-char *savenstr (), *savestr ();
-char *etags_strchr (), *etags_strrchr ();
-char *etags_getcwd ();
-char *relative_filename (), *absolute_filename (), *absolute_dirname ();
-bool filename_is_absolute ();
-void canonicalize_filename ();
-void grow_linebuffer ();
-long *xmalloc (), *xrealloc ();
-
-\f
-char searchar = '/'; /* use /.../ searches */
-
-char *tagfile; /* output file */
-char *progname; /* name this program was invoked with */
-char *cwd; /* current working directory */
-char *tagfiledir; /* directory of tagfile */
-FILE *tagf; /* ioptr for tags file */
-
-char *curfile; /* current input file name */
-language *curlang; /* current language */
-
-int lineno; /* line number of current line */
-long charno; /* current character number */
-long linecharno; /* charno of start of current line */
-char *dbp; /* pointer to start of current tag */
-
typedef struct node_st
{ /* sorting structure */
char *name; /* function or type name */
struct node_st *left, *right; /* left and right sons */
} node;
-node *head; /* the head of the binary tree of tags */
-
/*
* A `linebuffer' is a structure which holds a line of text.
* `readline_internal' reads a line from a stream into a linebuffer
char *buffer;
} linebuffer;
+/* Many compilers barf on this:
+ Lang_function Ada_funcs;
+ so let's write it this way */
+void Ada_funcs (FILE *inf);
+void Asm_labels (FILE *inf);
+void C_entries (int c_ext, FILE *inf);
+void default_C_entries (FILE *inf);
+void plain_C_entries (FILE *inf);
+void Cjava_entries (FILE *inf);
+void Cobol_paragraphs (FILE *inf);
+void Cplusplus_entries (FILE *inf);
+void Cstar_entries (FILE *inf);
+void Erlang_functions (FILE *inf);
+void Fortran_functions (FILE *inf);
+void Yacc_entries (FILE *inf);
+void Lisp_functions (FILE *inf);
+void Pascal_functions (FILE *inf);
+void Perl_functions (FILE *inf);
+void Postscript_functions (FILE *inf);
+void Prolog_functions (FILE *inf);
+void Python_functions (FILE *inf);
+void Scheme_functions (FILE *inf);
+void TeX_functions (FILE *inf);
+void just_read_file (FILE *inf);
+
+compressor *get_compressor_from_suffix (char *file, char **extptr);
+language *get_language_from_name (char *name);
+language *get_language_from_interpreter (char *interpreter);
+language *get_language_from_suffix (char *file);
+int total_size_of_entries (register node *np);
+long readline (linebuffer *lbp, FILE *stream);
+long readline_internal (linebuffer *lbp, register FILE *stream);
+void get_tag (register char *bp);
+
+#ifdef ETAGS_REGEXPS
+void analyse_regex (char *regex_arg, bool ignore_case);
+void add_regex (char *regexp_pattern, bool ignore_case, language *lan);
+void free_patterns (void);
+#endif /* ETAGS_REGEXPS */
+void error (const char *s1, const char *s2);
+void suggest_asking_for_help (void);
+void fatal (char *s1, char *s2);
+void pfatal (char *s1);
+void add_node (node *np, node **cur_node_p);
+
+void init (void);
+void initbuffer (linebuffer *lbp);
+void find_entries (char *file, FILE *inf);
+void free_tree (register node *np);
+void pfnote (char *name, bool is_func, char *linestart, int linelen, int lno, long int cno);
+void new_pfnote (char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long int cno);
+void process_file (char *file);
+void put_entries (register node *np);
+void takeprec (void);
+
+char *concat (char *s1, char *s2, char *s3);
+char *skip_spaces (char *cp);
+char *skip_non_spaces (char *cp);
+char *savenstr (char *cp, int len);
+char *savestr (char *cp);
+char *etags_strchr (const char *sp, int c);
+char *etags_strrchr (const char *sp, int c);
+char *etags_getcwd (void);
+char *relative_filename (char *file, char *dir);
+char *absolute_filename (char *file, char *dir);
+char *absolute_dirname (char *file, char *dir);
+bool filename_is_absolute (char *fn);
+void canonicalize_filename (register char *fn);
+void grow_linebuffer (linebuffer *lbp, int toksize);
+long *xmalloc (unsigned int size);
+long *xrealloc (char *ptr, unsigned int size);
+
+\f
+char searchar = '/'; /* use /.../ searches */
+
+char *tagfile; /* output file */
+char *progname; /* name this program was invoked with */
+char *cwd; /* current working directory */
+char *tagfiledir; /* directory of tagfile */
+FILE *tagf; /* ioptr for tags file */
+
+char *curfile; /* current input file name */
+language *curlang; /* current language */
+
+int lineno; /* line number of current line */
+long charno; /* current character number */
+long linecharno; /* charno of start of current line */
+char *dbp; /* pointer to start of current tag */
+
+node *head; /* the head of the binary tree of tags */
+
linebuffer lb; /* the current line */
linebuffer token_name; /* used by C_entries as a temporary area */
struct
bool append_to_tagfile; /* -a: append to tags */
/* The following four default to TRUE for etags, but to FALSE for ctags. */
-bool typedefs; /* -t: create tags for C typedefs */
+bool typedefs; /* -t: create tags for C and Ada typedefs */
bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
/* 0 struct/enum/union decls, and C++ */
/* member functions. */
bool constantypedefs; /* -d: create tags for C #define, enum */
/* constants and variables. */
/* -D: opposite of -d. Default under ctags. */
+bool declarations; /* --declarations: tag them and extern in C&Co*/
bool globals; /* create tags for global variables */
bool members; /* create tags for C member variables */
bool update; /* -u: update tags */
bool cxref_style; /* -x: create cxref style output */
bool cplusplus; /* .[hc] means C++, not C */
bool noindentypedefs; /* -I: ignore indentation in C */
+bool packages_only; /* --packages-only: in Ada, only tag packages*/
#ifdef LONG_OPTIONS
struct option longopts[] =
{
- { "append", no_argument, NULL, 'a' },
- { "backward-search", no_argument, NULL, 'B' },
- { "c++", no_argument, NULL, 'C' },
- { "cxref", no_argument, NULL, 'x' },
- { "defines", no_argument, NULL, 'd' },
- { "no-defines", no_argument, NULL, 'D' },
- { "globals", no_argument, &globals, TRUE },
- { "no-globals", no_argument, &globals, FALSE },
- { "help", no_argument, NULL, 'h' },
- { "help", no_argument, NULL, 'H' },
- { "ignore-indentation", no_argument, NULL, 'I' },
- { "include", required_argument, NULL, 'i' },
- { "language", required_argument, NULL, 'l' },
- { "members", no_argument, &members, TRUE },
- { "no-members", no_argument, &members, FALSE },
- { "no-warn", no_argument, NULL, 'w' },
- { "output", required_argument, NULL, 'o' },
-#ifdef ETAGS_REGEXPS
- { "regex", required_argument, NULL, 'r' },
- { "no-regex", no_argument, NULL, 'R' },
-#endif /* ETAGS_REGEXPS */
- { "typedefs", no_argument, NULL, 't' },
- { "typedefs-and-c++", no_argument, NULL, 'T' },
- { "update", no_argument, NULL, 'u' },
- { "version", no_argument, NULL, 'V' },
- { "vgrind", no_argument, NULL, 'v' },
- { 0 }
+ { "packages-only", no_argument, &packages_only, TRUE },
+ { "append", no_argument, NULL, 'a' },
+ { "backward-search", no_argument, NULL, 'B' },
+ { "c++", no_argument, NULL, 'C' },
+ { "cxref", no_argument, NULL, 'x' },
+ { "defines", no_argument, NULL, 'd' },
+ { "declarations", no_argument, &declarations, TRUE },
+ { "no-defines", no_argument, NULL, 'D' },
+ { "globals", no_argument, &globals, TRUE },
+ { "no-globals", no_argument, &globals, FALSE },
+ { "help", no_argument, NULL, 'h' },
+ { "help", no_argument, NULL, 'H' },
+ { "ignore-indentation", no_argument, NULL, 'I' },
+ { "include", required_argument, NULL, 'i' },
+ { "language", required_argument, NULL, 'l' },
+ { "members", no_argument, &members, TRUE },
+ { "no-members", no_argument, &members, FALSE },
+ { "no-warn", no_argument, NULL, 'w' },
+ { "output", required_argument, NULL, 'o' },
+#ifdef ETAGS_REGEXPS
+ { "regex", required_argument, NULL, 'r' },
+ { "no-regex", no_argument, NULL, 'R' },
+ { "ignore-case-regex", required_argument, NULL, 'c' },
+#endif /* ETAGS_REGEXPS */
+ { "typedefs", no_argument, NULL, 't' },
+ { "typedefs-and-c++", no_argument, NULL, 'T' },
+ { "update", no_argument, NULL, 'u' },
+ { "version", no_argument, NULL, 'V' },
+ { "vgrind", no_argument, NULL, 'v' },
+ { NULL }
};
#endif /* LONG_OPTIONS */
bool error_signaled;
} pattern;
-/* Array of all regexps. */
+/* List of all regexps. */
pattern *p_head = NULL;
+
+/* How many characters in the character set. (From regex.c.) */
+#define CHAR_SET_SIZE 256
+/* Translation table for case-insensitive matching. */
+char lc_trans[CHAR_SET_SIZE];
#endif /* ETAGS_REGEXPS */
compressor compressors[] =
{
- { "z", 1, "gzip -d -c"},
- { "Z", 1, "gzip -d -c"},
- { "gz", 2, "gzip -d -c"},
- { "GZ", 2, "gzip -d -c"},
- { "bz2", 3, "bzip2 -d -c" },
+ { "z", "gzip -d -c"},
+ { "Z", "gzip -d -c"},
+ { "gz", "gzip -d -c"},
+ { "GZ", "gzip -d -c"},
+ { "bz2", "bzip2 -d -c" },
{ NULL }
};
/* Non-NULL if language fixed. */
language *forced_lang = NULL;
+/* Ada code */
+char *Ada_suffixes [] =
+ { "ads", "adb", "ada", NULL };
+
/* Assembly code */
char *Asm_suffixes [] = { "a", /* Unix assembler */
"asm", /* Microcontroller assembly */
NULL };
char *Postscript_suffixes [] =
- { "ps", NULL };
+ { "ps", "psw", NULL }; /* .psw is for PSWrap */
char *Prolog_suffixes [] =
{ "prolog", NULL };
language lang_names [] =
{
+ { "ada", Ada_funcs, Ada_suffixes, NULL },
{ "asm", Asm_labels, Asm_suffixes, NULL },
{ "c", default_C_entries, default_C_suffixes, NULL },
{ "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
{ NULL, NULL } /* end of list */
};
\f
-void
+static void
print_language_names ()
{
language *lang;
Compressed files are supported using gzip and bzip2.");
}
+#ifdef XEMACS
+# define EMACS_NAME "XEmacs"
+#else
+# define EMACS_NAME "GNU Emacs"
+#endif
+
#ifndef VERSION
# define VERSION "20"
#endif
-void
+static void
print_version ()
{
- printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
- puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
+ printf ("%s (" EMACS_NAME " %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
+ puts ("Copyright (C) 1999 Free Software Foundation, Inc. and Ken Arnold");
puts ("This program is distributed under the same terms as Emacs");
exit (GOOD);
}
-void
+static void
print_help ()
{
printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
puts ("-a, --append\n\
Append tag entries to existing tags file.");
+ puts ("--packages-only\n\
+ For Ada files, only generate tags for packages .");
+
if (CTAGS)
puts ("-B, --backward-search\n\
Write the search commands for the tag entries using '?', the\n\
puts ("-C, --c++\n\
Treat files whose name suffix defaults to C language as C++ files.");
+ puts ("--declarations\n\
+ In C and derived languages, create tags for function declarations,");
+ if (CTAGS)
+ puts ("\tand create tags for extern variables if --globals is used.");
+ else
+ puts
+ ("\tand create tags for extern variables unless --no-globals is used.");
+
if (CTAGS)
puts ("-d, --defines\n\
Create tag entries for C #define constants and enum constants, too.");
#ifdef ETAGS_REGEXPS
puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
- Make a tag for each line matching pattern REGEXP in the\n\
- following files. regexfile is a file containing one REGEXP\n\
- per line. REGEXP is anchored (as if preceded by ^).\n\
- The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
- named tags can be created with:\n\
+ Make a tag for each line matching pattern REGEXP in the following\n\
+ files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\
+ regexfile is a file containing one REGEXP per line.\n\
+ 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 --ignore-case-regex=@regexfile\n\
+ 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 */
if (CTAGS)
{
puts ("-t, --typedefs\n\
- Generate tag entries for C typedefs.");
+ Generate tag entries for C and Ada typedefs.");
puts ("-T, --typedefs-and-c++\n\
Generate tag entries for C typedefs, C struct/enum/union tags,\n\
and C++ member functions.");
print_language_names ();
puts ("");
- puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
+ puts ("Report bugs to bug-gnu-emacs@gnu.org");
exit (GOOD);
}
{
at_language,
at_regexp,
- at_filename
+ at_filename,
+ at_icregexp
};
/* This structure helps us allow mixing of --lang and file names. */
#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 is to find macro constants, enum constants and
- * global variables.
+ * global variables.
*/
if (!CTAGS)
{
char *optstring;
#ifdef ETAGS_REGEXPS
- optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
+ optstring = "-aCdDf:Il:o:r:c:RStTi:BuvxwVhH";
#else
optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
#endif /* ETAGS_REGEXPS */
case 'o':
if (tagfile)
{
- error ("-%c option may only be given once.", opt);
+ error ("-o option may only be given once.", (char *)NULL);
suggest_asking_for_help ();
}
tagfile = optarg;
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;
#endif /* ETAGS_REGEXPS */
case 'V':
print_version ();
if (nincluded_files == 0 && file_count == 0)
{
- error ("no input files specified.", 0);
+ error ("no input files specified.", (char *)NULL);
suggest_asking_for_help ();
}
break;
#ifdef ETAGS_REGEXPS
case at_regexp:
- analyse_regex (argbuffer[i].what);
+ analyse_regex (argbuffer[i].what, FALSE);
+ break;
+ case at_icregexp:
+ analyse_regex (argbuffer[i].what, TRUE);
break;
#endif
case at_filename:
/*
- * Return a compressor given the file name.
+ * Return a compressor given the file name. If EXTPTR is non-zero,
+ * return a pointer into FILE where the compressor-specific
+ * extension begins. If no compressor is found, NULL is returned
+ * and EXTPTR is not significant.
* Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca>
*/
compressor *
-get_compressor_from_suffix (file)
+get_compressor_from_suffix (file, extptr)
char *file;
+ char **extptr;
{
compressor *compr;
- char *suffix;
+ char *slash, *suffix;
+ /* This relies on FN to be after canonicalize_filename,
+ so we don't need to consider backslashes on DOS_NT. */
+ slash = etags_strrchr (file, '/');
suffix = etags_strrchr (file, '.');
- if (suffix == NULL)
+ if (suffix == NULL || suffix < slash)
return NULL;
+ if (extptr != NULL)
+ *extptr = suffix;
suffix += 1;
+ /* Let those poor souls who live with DOS 8+3 file name limits get
+ some solace by treating foo.cgz as if it were foo.c.gz, etc.
+ Only the first do loop is run if not MSDOS */
+#ifdef MSDOS
+ do
+ {
+ for (compr = compressors; compr->suffix != NULL; compr++)
+ if (streq (compr->suffix, suffix))
+ return compr;
+ if (extptr != NULL)
+ *extptr = ++suffix;
+ } while (*suffix != '\0');
+#else
for (compr = compressors; compr->suffix != NULL; compr++)
if (streq (compr->suffix, suffix))
return compr;
+#endif
+
return NULL;
}
FILE *inf;
compressor *compr;
char *compressed_name, *uncompressed_name;
- char *real_name;
+ char *ext, *real_name;
+
canonicalize_filename (file);
if (streq (file, tagfile) && !streq (tagfile, "-"))
error ("skipping inclusion of %s in self.", file);
return;
}
- if ((compr = get_compressor_from_suffix (file)) == NULL)
+ if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
{
compressed_name = NULL;
real_name = uncompressed_name = savestr (file);
else
{
real_name = compressed_name = savestr (file);
- uncompressed_name = savenstr (file, strlen(file) - compr->sufflen - 1);
+ uncompressed_name = savenstr (file, ext - file);
}
+
+ /* If the canonicalised uncompressed name has already be dealt with,
+ skip it silently, else add it to the list. */
+ {
+ typedef struct processed_file
+ {
+ char *filename;
+ struct processed_file *next;
+ } processed_file;
+ static processed_file *pf_head = NULL;
+ register processed_file *fnp;
+
+ for (fnp = pf_head; fnp != NULL; fnp = fnp->next)
+ if (streq (uncompressed_name, fnp->filename))
+ goto exit;
+ fnp = pf_head;
+ pf_head = xnew (1, struct processed_file);
+ pf_head->filename = savestr (uncompressed_name);
+ pf_head->next = fnp;
+ }
+
if (stat (real_name, &stat_buf) != 0)
{
/* Reset real_name and try with a different name. */
{
compressed_name = concat (file, ".", compr->suffix);
if (stat (compressed_name, &stat_buf) != 0)
- free (compressed_name);
+ {
+#ifdef MSDOS
+ char *suf = compressed_name + strlen (file);
+ size_t suflen = strlen (compr->suffix) + 1;
+ for ( ; suf[1]; suf++, suflen--)
+ {
+ memmove (suf, suf + 1, suflen);
+ if (stat (compressed_name, &stat_buf) == 0)
+ {
+ real_name = compressed_name;
+ break;
+ }
+ }
+ if (real_name != NULL)
+ break;
+#endif
+ free (compressed_name);
+ compressed_name = NULL;
+ }
else
{
real_name = compressed_name;
inf = popen (cmd, "r");
free (cmd);
}
- else
+ else
inf = fopen (real_name, "r");
if (inf == NULL)
{
named = FALSE; /* use unnamed tag */
}
}
-
+
if (named)
name = savenstr (name, namelen);
else
}
/* Length of a number's decimal representation. */
-int
+static int
number_len (num)
long num;
{
st_C_ignore,
st_C_javastruct,
st_C_operator,
- st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
};
/* Feed stuff between (but not including) %[ and %] lines to:
%[
struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
%%
+if, 0, st_C_ignore
+for, 0, st_C_ignore
+while, 0, st_C_ignore
+switch, 0, st_C_ignore
+return, 0, st_C_ignore
@interface, 0, st_C_objprot
@protocol, 0, st_C_objprot
@implementation,0, st_C_objimpl
domain, C_STAR, st_C_struct
union, 0, st_C_struct
struct, 0, st_C_struct
+extern, 0, st_C_extern
enum, 0, st_C_enum
typedef, 0, st_C_typedef
define, 0, st_C_define
unsigned, 0, st_C_typespec
auto, 0, st_C_typespec
void, 0, st_C_typespec
-extern, 0, st_C_typespec
static, 0, st_C_typespec
const, 0, st_C_typespec
volatile, 0, st_C_typespec
%]
and replace lines between %< and %> with its output. */
/*%<*/
-/* C code produced by gperf version 2.5 (GNU C++ version) */
+/* C code produced by gperf version 2.7.1 (19981006 egcs) */
/* Command-line: gperf -c -k 1,3 -o -p -r -t */
struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
-#define TOTAL_KEYWORDS 41
-#define MIN_WORD_LENGTH 3
+#define TOTAL_KEYWORDS 46
+#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 15
-#define MIN_HASH_VALUE 20
-#define MAX_HASH_VALUE 136
-/* maximum key range = 117, duplicates = 0 */
+#define MIN_HASH_VALUE 13
+#define MAX_HASH_VALUE 123
+/* maximum key range = 111, duplicates = 0 */
+#ifdef __GNUC__
+__inline
+#endif
static unsigned int
hash (str, len)
- register char *str;
- register int unsigned len;
+ register const char *str;
+ register unsigned int len;
{
static unsigned char asso_values[] =
{
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 58, 137, 137, 137, 38, 37,
- 45, 137, 137, 137, 137, 137, 137, 137, 137, 137,
- 62, 137, 137, 14, 16, 137, 137, 137, 137, 137,
- 137, 137, 137, 137, 137, 137, 137, 26, 16, 51,
- 18, 61, 5, 19, 137, 23, 137, 137, 32, 63,
- 54, 10, 26, 137, 24, 42, 30, 18, 46, 137,
- 137, 137, 137, 137, 137, 137, 137, 137,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 3, 124, 124, 124, 43, 6,
+ 11, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 11, 124, 124, 58, 7, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 57, 7, 42,
+ 4, 14, 52, 0, 124, 53, 124, 124, 29, 11,
+ 6, 35, 32, 124, 29, 34, 59, 58, 51, 24,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124
};
- return len + asso_values[str[2]] + asso_values[str[0]];
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
}
-struct C_stab_entry *
+#ifdef __GNUC__
+__inline
+#endif
+static struct C_stab_entry *
in_word_set (str, len)
- register char *str;
+ register const char *str;
register unsigned int len;
{
static struct C_stab_entry wordlist[] =
{
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",},
- {"float", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"define", 0, st_C_define},
- {"bool", C_PLPL, st_C_typespec},
- {"",}, {"",}, {"",},
- {"friend", C_PLPL, st_C_ignore},
- {"SYSCALL", 0, st_C_gnumacro},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"double", 0, st_C_typespec},
- {"",}, {"",}, {"",},
- {"union", 0, st_C_struct},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"import", C_JAVA, st_C_ignore},
- {"int", 0, st_C_typespec},
- {"short", 0, st_C_typespec},
- {"ENTRY", 0, st_C_gnumacro},
- {"implements", C_JAVA, st_C_javastruct},
- {"auto", 0, st_C_typespec},
- {"",},
- {"interface", C_JAVA, st_C_struct},
- {"typedef", 0, st_C_typedef},
- {"typename", C_PLPL, st_C_typespec},
- {"",}, {"",},
- {"signed", 0, st_C_typespec},
- {"unsigned", 0, st_C_typespec},
- {"",}, {"",}, {"",},
- {"struct", 0, st_C_struct},
- {"void", 0, st_C_typespec},
- {"static", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",},
- {"operator", C_PLPL, st_C_operator},
- {"",},
- {"char", 0, st_C_typespec},
- {"class", C_PLPL, st_C_struct},
- {"enum", 0, st_C_enum},
- {"package", C_JAVA, st_C_ignore},
- {"",},
- {"volatile", 0, st_C_typespec},
- {"domain", C_STAR, st_C_struct},
- {"DEFUN", 0, st_C_gnumacro},
- {"",},
- {"long", 0, st_C_typespec},
- {"@protocol", 0, st_C_objprot},
- {"",}, {"",}, {"",},
- {"explicit", C_PLPL, st_C_typespec},
- {"",},
- {"extern", 0, st_C_typespec},
- {"extends", C_JAVA, st_C_javastruct},
- {"",},
- {"mutable", C_PLPL, st_C_typespec},
- {"",}, {"",}, {"",}, {"",},
- {"PSEUDO", 0, st_C_gnumacro},
- {"",}, {"",}, {"",}, {"",},
- {"const", 0, st_C_typespec},
- {"",}, {"",}, {"",}, {"",}, {"",},
- {"@end", 0, st_C_objend},
- {"",}, {"",}, {"",}, {"",}, {"",},
- {"@interface", 0, st_C_objprot},
- {"",}, {"",}, {"",},
- {"namespace", C_PLPL, st_C_struct},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"@implementation", 0, st_C_objimpl},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""},
+ {"@end", 0, st_C_objend},
+ {""}, {""}, {""}, {""},
+ {"ENTRY", 0, st_C_gnumacro},
+ {"@interface", 0, st_C_objprot},
+ {""},
+ {"domain", C_STAR, st_C_struct},
+ {""},
+ {"PSEUDO", 0, st_C_gnumacro},
+ {""}, {""},
+ {"namespace", C_PLPL, st_C_struct},
+ {""}, {""},
+ {"@implementation",0, st_C_objimpl},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"long", 0, st_C_typespec},
+ {"signed", 0, st_C_typespec},
+ {"@protocol", 0, st_C_objprot},
+ {""}, {""}, {""}, {""},
+ {"bool", C_PLPL, st_C_typespec},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"const", 0, st_C_typespec},
+ {"explicit", C_PLPL, st_C_typespec},
+ {"if", 0, st_C_ignore},
+ {""},
+ {"operator", C_PLPL, st_C_operator},
+ {""},
+ {"DEFUN", 0, st_C_gnumacro},
+ {""}, {""},
+ {"define", 0, st_C_define},
+ {""}, {""}, {""}, {""}, {""},
+ {"double", 0, st_C_typespec},
+ {"struct", 0, st_C_struct},
+ {""}, {""}, {""}, {""},
+ {"short", 0, st_C_typespec},
+ {""},
+ {"enum", 0, st_C_enum},
+ {"mutable", C_PLPL, st_C_typespec},
+ {""},
+ {"extern", 0, st_C_extern},
+ {"extends", C_JAVA, st_C_javastruct},
+ {"package", C_JAVA, st_C_ignore},
+ {"while", 0, st_C_ignore},
+ {""},
+ {"for", 0, st_C_ignore},
+ {""}, {""}, {""},
+ {"volatile", 0, st_C_typespec},
+ {""}, {""},
+ {"import", C_JAVA, st_C_ignore},
+ {"float", 0, st_C_typespec},
+ {"switch", 0, st_C_ignore},
+ {"return", 0, st_C_ignore},
+ {"implements", C_JAVA, st_C_javastruct},
+ {""},
+ {"static", 0, st_C_typespec},
+ {"typedef", 0, st_C_typedef},
+ {"typename", C_PLPL, st_C_typespec},
+ {"unsigned", 0, st_C_typespec},
+ {""}, {""},
+ {"char", 0, st_C_typespec},
+ {"class", C_PLPL, st_C_struct},
+ {""}, {""}, {""},
+ {"void", 0, st_C_typespec},
+ {""}, {""},
+ {"friend", C_PLPL, st_C_ignore},
+ {""}, {""}, {""},
+ {"int", 0, st_C_typespec},
+ {"union", 0, st_C_struct},
+ {""}, {""}, {""},
+ {"auto", 0, st_C_typespec},
+ {"interface", C_JAVA, st_C_struct},
+ {""},
+ {"SYSCALL", 0, st_C_gnumacro}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
if (key <= MAX_HASH_VALUE && key >= 0)
{
- register char *s = wordlist[key].name;
+ register const char *s = wordlist[key].name;
- if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
}
/*%>*/
-enum sym_type
+static enum sym_type
C_symtype (str, len, c_ext)
char *str;
int len;
vignore /* var-like: ignore until ';' */
} fvdef;
+bool fvextern; /* func or var: extern keyword seen; */
/*
* typedefs are recognized using a simple finite automaton.
enum
{
tnone, /* nothing seen */
- ttypedseen, /* typedef keyword seen */
+ tkeyseen, /* typedef keyword seen */
+ ttypeseen, /* defined type seen */
tinbody, /* inside typedef body */
tend, /* just before typedef tag */
tignore /* junk after typedef tag */
* next_token_is_func IN OUT
*/
-bool
+static bool
consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
register char *str; /* IN: token pointer */
register int len; /* IN: token length */
if (toktype == st_C_typedef)
{
if (typedefs)
- typdef = ttypedseen;
+ typdef = tkeyseen;
+ fvextern = FALSE;
fvdef = fvnone;
return FALSE;
}
break;
- case ttypedseen:
+ case tkeyseen:
switch (toktype)
{
case st_none:
case st_C_typespec:
- typdef = tend;
- break;
case st_C_struct:
case st_C_enum:
+ typdef = ttypeseen;
break;
}
/* Do not return here, so the structdef stuff has a chance. */
return FALSE;
case st_C_struct:
case st_C_enum:
- if (typdef == ttypedseen
+ if (typdef == tkeyseen
|| (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
{
structdef = skeyseen;
return TRUE;
}
- /* Avoid entering fvdef stuff if typdef is going on. */
if (typdef != tnone)
- {
- definedef = dnone;
- return FALSE;
- }
+ definedef = dnone;
/* Detect GNU macros.
- DEFUN note for writers of emacs C code:
+ Writers of emacs code are recommended to put the
+ first two args of a DEFUN on the same line.
+
The DEFUN macro, used in emacs C source code, has a first arg
that is a string (the lisp function name), and a second arg that
is a C function name. Since etags skips strings, the second arg
removing the initial 'F' character and substituting '-' for '_'.
Anyway, this assumes that the conventions of naming lisp
functions will never change. Currently, this method is not
- implemented, so writers of emacs code are recommended to put the
- first two args of a DEFUN on the same line. */
+ implemented. */
if (definedef == dnone && toktype == st_C_gnumacro)
{
next_token_is_func = TRUE;
/* A function, variable or enum constant? */
switch (toktype)
{
+ case st_C_extern:
+ fvextern = TRUE;
+ /* FALLTHRU */
case st_C_typespec:
- if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
- fvdef = fvnone; /* should be useless */
+ if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
+ fvdef = fvnone; /* should be useless */
return FALSE;
case st_C_ignore:
+ fvextern = FALSE;
fvdef = vignore;
return FALSE;
case st_C_operator:
*is_func_or_var = TRUE;
return TRUE;
case st_none:
+ if ((c_ext & C_PLPL) && strneq (str+len-10, "::operator", 10))
+ {
+ fvdef = foperator;
+ *is_func_or_var = TRUE;
+ return TRUE;
+ }
if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
return TRUE;
if (fvdef == fvnone)
*is_func_or_var = TRUE;
return TRUE;
}
+ break;
}
return FALSE;
* C_entries ()
* This routine finds functions, variables, typedefs,
* #define's, enum constants and struct/union/enum definitions in
- * #C syntax and adds them to the list.
+ * C syntax and adds them to the list.
*/
#define current_lb_is_new (newndx == curndx)
#define switch_line_buffers() (curndx = 1 - curndx)
} while (0)
-void
+static void
make_C_tag (isfun)
bool isfun;
{
int cblev; /* current curly brace level */
int parlev; /* current parenthesis level */
bool incomm, inquote, inchar, quotednl, midtoken;
- bool cplpl, cjava;
+ bool purec, cplpl, cjava;
token savetok; /* token saved during preprocessor handling */
lp = curlb.buffer;
*lp = 0;
- fvdef = fvnone; typdef = tnone; structdef = snone;
- definedef = dnone; objdef = onone;
+ fvdef = fvnone; fvextern = FALSE; typdef = tnone;
+ structdef = snone; definedef = dnone; objdef = onone;
next_token_is_func = yacc_rules = FALSE;
midtoken = inquote = inchar = incomm = quotednl = FALSE;
tok.valid = savetok.valid = FALSE;
cblev = 0;
parlev = 0;
+ purec = !(c_ext & ~YACC); /* no extensions (apart from possibly yacc) */
cplpl = (c_ext & C_PLPL) == C_PLPL;
cjava = (c_ext & C_JAVA) == C_JAVA;
if (cjava)
case '"':
inquote = TRUE;
if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
- fvdef = fvnone;
+ {
+ fvextern = FALSE;
+ fvdef = fvnone;
+ }
continue;
case '\'':
inchar = TRUE;
if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
- fvdef = fvnone;
+ {
+ fvextern = FALSE;
+ fvdef = fvnone;
+ }
continue;
case '/':
if (*lp == '*')
{
/* entering or exiting rules section in yacc file */
lp++;
- definedef = dnone; fvdef = fvnone;
+ definedef = dnone; fvdef = fvnone; fvextern = FALSE;
typdef = tnone; structdef = snone;
next_token_is_func = FALSE;
midtoken = inquote = inchar = incomm = quotednl = FALSE;
if ((definedef != dnone
|| (cblev == 0 && structdef != scolonseen)
|| (cblev == 1 && cplpl && structdef == sinbody)
- || (structdef == sinbody && structtype == st_C_enum))
+ || (structdef == sinbody && purec))
&& typdef != tignore
&& definedef != dignorerest
&& fvdef != finlist)
{
if (endtoken (c))
{
- if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
+ bool funorvar = FALSE;
+
+ if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1]))
{
/*
* This handles :: in the middle, but not at the
- * beginning of an identifier.
+ * beginning of an identifier. Also, space-separated
+ * :: is not recognised.
*/
lp += 2;
- toklen += 3;
+ toklen += 2;
+ c = lp[-1];
+ goto intok;
}
else
{
- bool funorvar = FALSE;
-
if (yacc_rules
|| consider_token (newlb.buffer + tokoff, toklen, c,
c_ext, cblev, parlev, &funorvar))
{
+ if (fvdef == foperator)
+ {
+ char *oldlp = lp;
+ lp = skip_spaces (lp-1);
+ if (*lp != '\0')
+ lp += 1;
+ while (*lp != '\0'
+ && !isspace (*lp) && *lp != '(')
+ lp += 1;
+ c = *lp++;
+ toklen += lp - oldlp;
+ }
tok.named = FALSE;
- if (structdef == sinbody
+ if (!purec
+ && funorvar
&& definedef == dnone
- && funorvar)
+ && structdef == sinbody)
/* function or var defined in C++ class body */
{
- int len;
- if (fvdef == foperator)
- {
- char *oldlp = lp;
- lp = skip_spaces (lp-1);
- while (*lp != '\0'
- && !isspace (*lp) && *lp != '(')
- lp += 1;
- c = *lp++;
- toklen += lp - oldlp;
- }
-
- len = strlen (structtag) + qlen + toklen;
+ int len = strlen (structtag) + qlen + toklen;
grow_linebuffer (&token_name, len + 1);
strcpy (token_name.buffer, structtag);
strcat (token_name.buffer, qualifier);
newlb.buffer + tokoff, toklen);
token_name.buffer[toklen] = '\0';
token_name.len = toklen;
- /* Name macros. */
+ /* Name macros and members. */
tok.named = (structdef == stagseen
+ || typdef == ttypeseen
|| typdef == tend
|| (funorvar
- && definedef == dignorerest));
+ && definedef == dignorerest)
+ || (funorvar
+ && definedef == dnone
+ && structdef == sinbody));
}
tok.lineno = lineno;
tok.linelen = tokoff + toklen + 1;
}
} /* if (endtoken (c)) */
else if (intoken (c))
+ intok:
{
toklen++;
continue;
}
break;
case fstartlist:
+ fvextern = FALSE;
fvdef = fvnone;
break;
}
case fignore:
break;
case fvnameseen:
- if ((globals && cblev == 0) || (members && cblev == 1))
+ if ((members && cblev == 1)
+ || (globals && cblev == 0 && (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
+ fvextern = FALSE;
+ fvdef = fvnone;
+ tok.valid = FALSE;
+ break;
+ case flistseen:
+ if (declarations && (cblev == 0 || cblev == 1))
+ make_C_tag (TRUE); /* a function declaration */
/* FALLTHRU */
default:
+ fvextern = FALSE;
fvdef = fvnone;
/* The following instruction invalidates the token.
Probably the token should be invalidated in all
case vignore:
break;
case fvnameseen:
- if ((globals && cblev == 0) || (members && cblev == 1))
+ if ((members && cblev == 1)
+ || (globals && cblev == 0 && (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
break;
default:
case vignore:
break;
case fvnameseen:
- if ((globals && cblev == 0) || (members && cblev == 1))
+ if ((members && cblev == 1)
+ || (globals && cblev == 0 && (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
/* FALLTHRU */
default:
objdef = oparenseen;
switch (fvdef)
{
- case fvnone:
- switch (typdef)
- {
- case ttypedseen:
- case tend:
- if (tok.valid && *lp != '*')
- {
- /* This handles constructs like:
- typedef void OperatorFun (int fun); */
- make_C_tag (FALSE);
- typdef = tignore;
- }
- break;
- } /* switch (typdef) */
- break;
- case foperator: /* operator() is not handled */
case fvnameseen:
+ if (typdef == ttypeseen
+ && tok.valid
+ && *lp != '*'
+ && structdef != sinbody)
+ {
+ /* This handles constructs like:
+ typedef void OperatorFun (int fun); */
+ make_C_tag (FALSE);
+ typdef = tignore;
+ }
+ /* FALLTHRU */
+ case foperator:
fvdef = fstartlist;
break;
case flistseen:
fvdef = flistseen;
break;
}
- if (cblev == 0 && typdef == tend)
+ if (cblev == 0 && (typdef == tend))
{
typdef = tignore;
make_C_tag (FALSE); /* a typedef */
case '{':
if (definedef != dnone)
break;
- if (typdef == ttypedseen)
+ if (typdef == ttypeseen)
typdef = tinbody;
switch (structdef)
{
case vignore:
break;
case fvnameseen:
- if ((globals && cblev == 0) || (members && cblev == 1))
+ if ((members && cblev == 1)
+ || (globals && cblev == 0 && (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
/* FALLTHRU */
default:
C_entries (YACC, inf);
}
\f
-/* A useful macro. */
+/* A useful macro. */
#define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
for (lineno = charno = 0; /* loop initialization */ \
!feof (file_pointer) /* loop test */ \
\f
/* Fortran parsing */
-bool
+static bool
tail (cp)
char *cp;
{
register int len = 0;
- while (*cp && lowcase(*cp) == lowcase(dbp[len]))
+ while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len]))
cp++, len++;
- if (*cp == '\0' && !intoken(dbp[len]))
+ if (*cp == '\0' && !intoken (dbp[len]))
{
dbp += len;
return TRUE;
while (isdigit (*dbp));
}
-void
+static void
getit (inf)
FILE *inf;
{
dbp += 6;
dbp = skip_spaces (dbp);
}
- if (!isalpha (*dbp)
- && *dbp != '_'
- && *dbp != '$')
+ if (!isalpha (*dbp) && *dbp != '_' && *dbp != '$')
return;
- for (cp = dbp + 1; *cp && intoken (*cp); cp++)
+ for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++)
continue;
pfnote (savenstr (dbp, cp-dbp), TRUE,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
if (tail ("entry"))
getit (inf);
continue;
- case 'p':
- if (tail ("program") || tail ("procedure"))
- getit (inf);
- continue;
case 'b':
if (tail ("blockdata") || tail ("block data"))
{
}
\f
/*
+ * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be>, 1998-04-24
+ * Ada parsing
+ */
+/* Once we are positioned after an "interesting" keyword, let's get
+ the real tag value necessary. */
+static void
+adagetit (inf, name_qualifier)
+ FILE *inf;
+ char *name_qualifier;
+{
+ register char *cp;
+ char *name;
+ char c;
+
+ while (!feof (inf))
+ {
+ dbp = skip_spaces (dbp);
+ if (*dbp == '\0'
+ || (dbp[0] == '-' && dbp[1] == '-'))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, inf);
+ dbp = lb.buffer;
+ }
+ switch (*dbp)
+ {
+ case 'b':
+ case 'B':
+ if (tail ("body"))
+ {
+ /* Skipping body of procedure body or package body or ....
+ resetting qualifier to body instead of spec. */
+ name_qualifier = "/b";
+ continue;
+ }
+ break;
+ case 't':
+ case 'T':
+ /* Skipping type of task type or protected type ... */
+ if (tail ("type"))
+ continue;
+ break;
+ }
+ if (*dbp == '"')
+ {
+ dbp += 1;
+ for (cp = dbp; *cp != '\0' && *cp != '"'; cp++)
+ continue;
+ }
+ else
+ {
+ dbp = skip_spaces (dbp);
+ for (cp = dbp;
+ (*cp != '\0'
+ && (isalpha (*cp) || isdigit (*cp) || *cp == '_' || *cp == '.'));
+ cp++)
+ continue;
+ if (cp == dbp)
+ return;
+ }
+ c = *cp;
+ *cp = '\0';
+ name = concat (dbp, name_qualifier, "");
+ *cp = c;
+ pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ if (c == '"')
+ dbp = cp + 1;
+ return;
+ }
+}
+
+void
+Ada_funcs (inf)
+ FILE *inf;
+{
+ bool inquote = FALSE;
+
+ LOOP_ON_INPUT_LINES (inf, lb, dbp)
+ {
+ while (*dbp != '\0')
+ {
+ /* Skip a string i.e. "abcd". */
+ if (inquote || (*dbp == '"'))
+ {
+ dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"');
+ if (dbp != NULL)
+ {
+ inquote = FALSE;
+ dbp += 1;
+ continue; /* advance char */
+ }
+ else
+ {
+ inquote = TRUE;
+ break; /* advance line */
+ }
+ }
+
+ /* Skip comments. */
+ if (dbp[0] == '-' && dbp[1] == '-')
+ break; /* advance line */
+
+ /* Skip character enclosed in single quote i.e. 'a'
+ and skip single quote starting an attribute i.e. 'Image. */
+ if (*dbp == '\'')
+ {
+ dbp++ ;
+ if (*dbp != '\0')
+ dbp++;
+ continue;
+ }
+
+ /* Search for beginning of a token. */
+ if (!begtoken (*dbp))
+ {
+ dbp++;
+ continue; /* advance char */
+ }
+
+ /* We are at the beginning of a token. */
+ switch (*dbp)
+ {
+ case 'f':
+ case 'F':
+ if (!packages_only && tail ("function"))
+ adagetit (inf, "/f");
+ else
+ break; /* from switch */
+ continue; /* advance char */
+ case 'p':
+ case 'P':
+ if (!packages_only && tail ("procedure"))
+ adagetit (inf, "/p");
+ else if (tail ("package"))
+ adagetit (inf, "/s");
+ else if (tail ("protected")) /* protected type */
+ adagetit (inf, "/t");
+ else
+ break; /* from switch */
+ continue; /* advance char */
+ case 't':
+ case 'T':
+ if (!packages_only && tail ("task"))
+ adagetit (inf, "/k");
+ else if (typedefs && !packages_only && tail ("type"))
+ {
+ adagetit (inf, "/t");
+ while (*dbp != '\0')
+ dbp += 1;
+ }
+ else
+ break; /* from switch */
+ continue; /* advance char */
+ }
+
+ /* Look for the end of the token. */
+ while (!endtoken (*dbp))
+ dbp++;
+
+ } /* advance char */
+ } /* advance line */
+}
+\f
+/*
* Bob Weiner, Motorola Inc., 4/3/94
* Unix and microcontroller assembly tag handling
* look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
if (*cp == ':' || isspace (*cp))
{
/* Found end of label, so copy it and add it to the table. */
- pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
+ pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}
}
cp++;
pfnote (savenstr (sp, cp-sp), TRUE,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
- }
+ }
}
else if (globals /* only if tagging global vars is enabled */
&& ((cp = lb.buffer,
while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
cp++;
}
-
+
/* Perhaps I should back cp up one character, so the TAGS table
doesn't mention (and so depend upon) the following char. */
pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
inparms = FALSE; /* found '(' after "proc" */
verify_tag = FALSE; /* check if "extern" is ahead */
-
- while (!feof (inf)) /* long main loop to get next char */
+
+ while (!feof (inf)) /* long main loop to get next char */
{
c = *dbp++;
if (c == '\0') /* if end of line */
* lisp tag functions
* look for (def or (DEF, quote or QUOTE
*/
-int
+static int
L_isdef (strp)
register char *strp;
{
&& (strp[3] == 'f' || strp[3] == 'F'));
}
-int
+static int
L_isquote (strp)
register char *strp;
{
&& isspace (*++strp));
}
-void
+static void
L_getit ()
{
register char *cp;
}
for (cp = dbp /*+1*/;
- *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
+ *cp != '\0' && *cp != '(' && !isspace(*cp) && *cp != ')';
cp++)
continue;
if (cp == dbp)
* Postscript tag functions
* Just look for lines where the first character is '/'
* Richard Mlynarik <mly@adoc.xerox.com>
+ * Also look at "defineps" for PSWrap
+ * suggested by Masatake YAMATO <masata-y@is.aist-nara.ac.jp>
*/
-void
+void
Postscript_functions (inf)
FILE *inf;
{
*ep != '\0' && *ep != ' ' && *ep != '{';
ep++)
continue;
- pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
+ pfnote (savenstr (bp, ep-bp), TRUE,
lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
}
+ else if (strneq (bp, "defineps", 8))
+ {
+ bp = skip_non_spaces (bp);
+ bp = skip_spaces (bp);
+ get_tag (bp);
+ }
}
}
* look for (set! xyzzy
*/
-void get_scheme ();
-
void
Scheme_functions (inf)
FILE *inf;
{
- LOOP_ON_INPUT_LINES (inf, lb, dbp)
+ register char *bp;
+
+ LOOP_ON_INPUT_LINES (inf, lb, bp)
{
- if (dbp[0] == '('
- && (dbp[1] == 'D' || dbp[1] == 'd')
- && (dbp[2] == 'E' || dbp[2] == 'e')
- && (dbp[3] == 'F' || dbp[3] == 'f'))
+ if (bp[0] == '('
+ && (bp[1] == 'D' || bp[1] == 'd')
+ && (bp[2] == 'E' || bp[2] == 'e')
+ && (bp[3] == 'F' || bp[3] == 'f'))
{
- dbp = skip_non_spaces (dbp);
+ bp = skip_non_spaces (bp);
/* Skip over open parens and white space */
- while (isspace (*dbp) || *dbp == '(')
- dbp++;
- get_scheme ();
+ while (isspace (*bp) || *bp == '(')
+ bp++;
+ get_tag (bp);
}
- if (dbp[0] == '('
- && (dbp[1] == 'S' || dbp[1] == 's')
- && (dbp[2] == 'E' || dbp[2] == 'e')
- && (dbp[3] == 'T' || dbp[3] == 't')
- && (dbp[4] == '!' || dbp[4] == '!')
- && (isspace (dbp[5])))
+ if (bp[0] == '('
+ && (bp[1] == 'S' || bp[1] == 's')
+ && (bp[2] == 'E' || bp[2] == 'e')
+ && (bp[3] == 'T' || bp[3] == 't')
+ && (bp[4] == '!' || bp[4] == '!')
+ && (isspace (bp[5])))
{
- dbp = skip_non_spaces (dbp);
- dbp = skip_spaces (dbp);
- get_scheme ();
+ bp = skip_non_spaces (bp);
+ bp = skip_spaces (bp);
+ get_tag (bp);
}
}
}
-
-void
-get_scheme ()
-{
- register char *cp;
-
- if (*dbp == '\0')
- return;
- /* Go till you get to white space or a syntactic break */
- for (cp = dbp + 1;
- *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
- cp++)
- continue;
- pfnote (savenstr (dbp, cp-dbp), TRUE,
- lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
-}
\f
/* Find tags in TeX and LaTeX input files. */
:chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
:part:appendix:entry:index";
-void TEX_mode ();
-struct TEX_tabent *TEX_decode_env ();
-int TEX_Token ();
+void TEX_mode (FILE *inf);
+struct TEX_tabent *TEX_decode_env (char *evarname, char *defenv);
+int TEX_Token (char *cp);
char TEX_esc = '\\';
char TEX_opgrp = '{';
* Prolog support (rewritten) by Anders Lindgren, Mar. 96
*
* Assumes that the predicate starts at column 0.
- * Only the first clause of a predicate is added.
+ * Only the first clause of a predicate is added.
*/
-int prolog_pred ();
-void prolog_skip_comment ();
-int prolog_atom ();
+int prolog_pred (char *s, char *last);
+void prolog_skip_comment (linebuffer *plb, FILE *inf);
+int prolog_atom (char *s, int pos);
void
Prolog_functions (inf)
|| len != (int)strlen (last)
|| !strneq (s, last, len))
{
- pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
- s, pos, lineno, linecharno);
+ pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
return len;
}
}
{
pos++;
- while (1)
+ while (1)
{
if (s[pos] == '\'')
{
return -1;
}
\f
-/*
+/*
* Support for Erlang -- Anders Lindgren, Feb 1996.
*
* Generates tags for functions, defines, and records.
*
* Assumes that Erlang functions start at column 0.
*/
-int erlang_func ();
-void erlang_attribute ();
-int erlang_atom ();
+int erlang_func (char *s, char *last);
+void erlang_attribute (char *s);
+int erlang_atom (char *s, int pos);
void
Erlang_functions (inf)
}
else if ((len = erlang_func (cp, last)) > 0)
{
- /*
+ /*
* Function. Store the function name so that we only
* generates a tag for the first clause.
*/
|| len != (int)strlen (last)
|| !strneq (s, last, len)))
{
- pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
- s, pos, lineno, linecharno);
+ pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
return len;
}
/*
- * Handle attributes. Currently, tags are generated for defines
+ * Handle attributes. Currently, tags are generated for defines
* and records.
*
* They are on the form:
if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
{
pos = skip_spaces (s + 7) - s;
- if (s[pos++] == '(')
+ if (s[pos++] == '(')
{
pos = skip_spaces (s + pos) - s;
len = erlang_atom (s, pos);
if (len != 0)
- pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
+ pfnote (savenstr (& s[pos], len), TRUE,
s, pos + len, lineno, linecharno);
}
}
{
pos++;
- while (1)
+ while (1)
{
if (s[pos] == '\'')
{
an unquoted separator. Also turns "\t" into a Tab character.
Returns pointer to terminating separator. Works in place. Null
terminates name string. */
-char *
+static char *
scan_separators (name)
char *name;
{
/* Look at the argument of --regex or --no-regex and do the right
thing. Same for each line of a regexp file. */
void
-analyse_regex (regex_arg)
+analyse_regex (regex_arg, ignore_case)
char *regex_arg;
+ bool ignore_case;
{
if (regex_arg == NULL)
free_patterns (); /* --no-regex: remove existing regexps */
}
initbuffer (®exbuf);
while (readline_internal (®exbuf, regexfp) > 0)
- analyse_regex (regexbuf.buffer);
+ analyse_regex (regexbuf.buffer, ignore_case);
free (regexbuf.buffer);
fclose (regexfp);
}
lang = get_language_from_name (lang_name);
if (lang == NULL)
return;
- add_regex (cp + 1, lang);
+ add_regex (cp + 1, ignore_case, lang);
}
break;
/* Regexp to be used for any language. */
default:
- add_regex (regex_arg, NULL);
+ add_regex (regex_arg, ignore_case, NULL);
break;
}
}
/* Turn a name, which is an ed-style (but Emacs syntax) regular
expression, into a real regular expression by compiling it. */
void
-add_regex (regexp_pattern, lang)
+add_regex (regexp_pattern, ignore_case, lang)
char *regexp_pattern;
+ bool ignore_case;
language *lang;
{
char *name;
(void) scan_separators (name);
patbuf = xnew (1, struct re_pattern_buffer);
- patbuf->translate = NULL;
+ /* Translation table to fold case if appropriate. */
+ patbuf->translate = (ignore_case) ? lc_trans : NULL;
patbuf->fastmap = NULL;
patbuf->buffer = NULL;
patbuf->allocated = 0;
* Do the substitutions indicated by the regular expression and
* arguments.
*/
-char *
+static char *
substitute (in, out, regs)
char *in, *out;
struct re_registers *regs;
return;
}
\f
+void
+get_tag (bp)
+ register char *bp;
+{
+ register char *cp;
+
+ if (*bp == '\0')
+ return;
+ /* Go till you get to white space or a syntactic break */
+ for (cp = bp + 1;
+ *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
+ cp++)
+ continue;
+ pfnote (savenstr (bp, cp-bp), TRUE,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+}
+
#endif /* ETAGS_REGEXPS */
/* Initialize a linebuffer for use */
void
}
}
#endif /* ETAGS_REGEXPS */
-
+
return result;
}
\f
/*
* Return the ptr in sp at which the character c last
* appears; NULL if not found
- *
- * Identical to System V strrchr, included for portability.
*/
char *
etags_strrchr (sp, c)
- register char *sp, c;
+ const char *sp;
+ int c;
{
- register char *r;
+ register const char *r;
r = NULL;
do
if (*sp == c)
r = sp;
} while (*sp++);
- return r;
+ return (char *) r;
}
/*
* Return the ptr in sp at which the character c first
* appears; NULL if not found
- *
- * Identical to System V strchr, included for portability.
*/
char *
etags_strchr (sp, c)
- register char *sp, c;
+ const char *sp;
+ int c;
{
do
{
if (*sp == c)
- return sp;
+ return (char *) sp;
} while (*sp++);
return NULL;
}
/* Print error message. `s1' is printf control string, `s2' is arg for it. */
void
error (s1, s2)
- char *s1, *s2;
+ const char *s1, *s2;
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, s1, s2);
while (*fp++ == *dp++)
continue;
fp--, dp--; /* back to the first differing char */
+#ifdef DOS_NT
+ if (fp == afn && afn[0] != '/') /* cannot build a relative name */
+ return afn;
+#endif
do /* look at the equal chars until '/' */
fp--, dp--;
while (*fp != '/');
slashp = etags_strchr (slashp + 1, '/');
}
-
+
if (res[0] == '\0')
return savestr ("/");
else
register char *fn;
{
#ifdef DOS_NT
+ /* Canonicalize drive letter case. */
+ if (islower (fn[0]))
+ fn[0] = toupper (fn[0]);
+ /* Convert backslashes to slashes. */
for (; *fn != '\0'; fn++)
if (*fn == '\\')
*fn = '/';