Mercurial > emacs
changeset 57084:cdba91059d7d
[EXIT_SUCCESS, EXIT_FAILURE]: Define them when no
<stdlib.h> is available.
(enum sym_type): New st_C_attribute value for parsing
gcc's __attribute__. Deleted st_C_typespec value.
(gperf, in_word_set): Use gperf 3, options changed. Added the
__attribute__ keyword, removed all the st_C_typespec keywords,
changed attribute for Java to (C_JAVA & !C_PLPL).
(inattribute): New global bool, part of the C state machine.
(cblev): Identifier renamed to bracelev throughout.
(consider_token, C_entries): Numerous changes for making the
parser more robust and adding support for __attribute__.
Tiny change by David A. Capello <dacap@users.sourceforge.net> -
(Lua_suffixes, Lua_help, lang_names, Lua_functions):
Support the Lua scripting language <http://www.lua.org>.
author | Francesco Potortì <pot@gnu.org> |
---|---|
date | Mon, 13 Sep 2004 13:30:23 +0000 |
parents | a74474ba690a |
children | 4408e76f8d90 |
files | lib-src/etags.c |
diffstat | 1 files changed, 635 insertions(+), 576 deletions(-) [+] |
line wrap: on
line diff
--- a/lib-src/etags.c Mon Sep 13 08:18:22 2004 +0000 +++ b/lib-src/etags.c Mon Sep 13 13:30:23 2004 +0000 @@ -32,10 +32,15 @@ * 2002 #line directives by Francesco Potort́. * * Francesco Potort́ <pot@gnu.org> has maintained and improved it since 1993. - * */ -char pot_etags_version[] = "@(#) pot revision number is 16.58"; +/* + * If you want to add support for a new language, start by looking at the LUA + * language, which is the simplest. Alternatively, consider shipping a + * configuration file containing regexp definitions for etags. + */ + +char pot_etags_version[] = "@(#) pot revision number is 17.4"; #define TRUE 1 #define FALSE 0 @@ -61,11 +66,11 @@ # ifndef __P /* for Xemacs */ # define __P(args) args # endif -#else +#else /* no config.h */ # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C)) # define __P(args) args /* use prototypes */ # define PTR void * /* for generic pointers */ -# else +# else /* not standard C */ # define __P(args) () /* no prototypes */ # define const /* remove const for old compilers' sake */ # define PTR long * /* don't use void* */ @@ -118,12 +123,19 @@ # ifndef HAVE_GETCWD # define HAVE_GETCWD # endif /* undef HAVE_GETCWD */ -#else /* !WINDOWSNT */ +#else /* not WINDOWSNT */ # ifdef STDC_HEADERS # include <stdlib.h> # include <string.h> -# else +# else /* no standard C headers */ extern char *getenv (); +# ifdef VMS +# define EXIT_SUCCESS 1 +# define EXIT_FAILURE 0 +# else /* no VMS */ +# define EXIT_SUCCESS 0 +# define EXIT_FAILURE 1 +# endif # endif #endif /* !WINDOWSNT */ @@ -333,6 +345,7 @@ static void Fortran_functions __P((FILE *)); static void HTML_labels __P((FILE *)); static void Lisp_functions __P((FILE *)); +static void Lua_functions __P((FILE *)); static void Makefile_targets __P((FILE *)); static void Pascal_functions __P((FILE *)); static void Perl_functions __P((FILE *)); @@ -637,6 +650,11 @@ argument of any expression that starts with `(def' in column zero\n\ is a tag."; +static char *Lua_suffixes [] = + { "lua", "LUA", NULL }; +static char Lua_help [] = +"In Lua scripts, all functions are tags."; + static char *Makefile_filenames [] = { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL}; static char Makefile_help [] = @@ -763,6 +781,7 @@ { "html", HTML_help, HTML_labels, HTML_suffixes }, { "java", Cjava_help, Cjava_entries, Cjava_suffixes }, { "lisp", Lisp_help, Lisp_functions, Lisp_suffixes }, + { "lua", Lua_help, Lua_functions, Lua_suffixes }, { "makefile", Makefile_help,Makefile_targets,NULL,Makefile_filenames}, { "objc", Objc_help, plain_C_entries, Objc_suffixes }, { "pascal", Pascal_help, Pascal_functions, Pascal_suffixes }, @@ -2373,11 +2392,11 @@ st_none, st_C_objprot, st_C_objimpl, st_C_objend, st_C_gnumacro, - st_C_ignore, + st_C_ignore, st_C_attribute, st_C_javastruct, st_C_operator, st_C_class, st_C_template, - st_C_struct, st_C_extern, 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 }; static unsigned int hash __P((const char *, unsigned int)); @@ -2385,79 +2404,67 @@ static enum sym_type C_symtype __P((char *, int, int)); /* Feed stuff between (but not including) %[ and %] lines to: - gperf -c -k 1,3 -o -p -r -t + gperf -m 5 %[ +%compare-strncmp +%enum +%struct-type 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 -@end, 0, st_C_objend -import, C_JAVA, st_C_ignore -package, C_JAVA, st_C_ignore -friend, C_PLPL, st_C_ignore -extends, C_JAVA, st_C_javastruct -implements, C_JAVA, st_C_javastruct -interface, C_JAVA, st_C_struct -class, 0, st_C_class -namespace, C_PLPL, st_C_struct -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 -operator, C_PLPL, st_C_operator -template, 0, st_C_template -bool, C_PLPL, st_C_typespec -long, 0, st_C_typespec -short, 0, st_C_typespec -int, 0, st_C_typespec -char, 0, st_C_typespec -float, 0, st_C_typespec -double, 0, st_C_typespec -signed, 0, st_C_typespec -unsigned, 0, st_C_typespec -auto, 0, st_C_typespec -void, 0, st_C_typespec -static, 0, st_C_typespec -const, 0, st_C_typespec -volatile, 0, st_C_typespec -explicit, C_PLPL, st_C_typespec -mutable, C_PLPL, st_C_typespec -typename, C_PLPL, st_C_typespec +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 +__attribute__, 0, st_C_attribute +@interface, 0, st_C_objprot +@protocol, 0, st_C_objprot +@implementation,0, st_C_objimpl +@end, 0, st_C_objend +import, (C_JAVA & !C_PLPL), st_C_ignore +package, (C_JAVA & !C_PLPL), st_C_ignore +friend, C_PLPL, st_C_ignore +extends, (C_JAVA & !C_PLPL), st_C_javastruct +implements, (C_JAVA & !C_PLPL), st_C_javastruct +interface, (C_JAVA & !C_PLPL), st_C_struct +class, 0, st_C_class +namespace, C_PLPL, st_C_struct +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 +operator, C_PLPL, st_C_operator +template, 0, st_C_template # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach). -DEFUN, 0, st_C_gnumacro -SYSCALL, 0, st_C_gnumacro -ENTRY, 0, st_C_gnumacro -PSEUDO, 0, st_C_gnumacro +DEFUN, 0, st_C_gnumacro +SYSCALL, 0, st_C_gnumacro +ENTRY, 0, st_C_gnumacro +PSEUDO, 0, st_C_gnumacro # These are defined inside C functions, so currently they are not met. # EXFUN used in glibc, DEFVAR_* in emacs. -#EXFUN, 0, st_C_gnumacro -#DEFVAR_, 0, st_C_gnumacro +#EXFUN, 0, st_C_gnumacro +#DEFVAR_, 0, st_C_gnumacro %] -and replace lines between %< and %> with its output, -then make in_word_set and C_stab_entry static. */ +and replace lines between %< and %> with its output, then: + - remove the #if characterset check + - make in_word_set static and not inline. */ /*%<*/ -/* C code produced by gperf version 2.7.1 (19981006 egcs) */ -/* Command-line: gperf -c -k 1,3 -o -p -r -t */ +/* C code produced by gperf version 3.0.1 */ +/* Command-line: gperf -m 5 */ +/* Computed positions: -k'1-2' */ + struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; - -#define TOTAL_KEYWORDS 47 -#define MIN_WORD_LENGTH 2 -#define MAX_WORD_LENGTH 15 -#define MIN_HASH_VALUE 18 -#define MAX_HASH_VALUE 138 -/* maximum key range = 121, duplicates = 0 */ +/* maximum key range = 31, duplicates = 0 */ #ifdef __GNUC__ __inline +#else +#ifdef __cplusplus +inline +#endif #endif static unsigned int hash (str, len) @@ -2466,132 +2473,84 @@ { static unsigned char asso_values[] = { - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 63, 139, 139, 139, 33, 44, - 62, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 42, 139, 139, 12, 32, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 34, 59, 37, - 24, 58, 33, 3, 139, 16, 139, 139, 42, 60, - 18, 11, 39, 139, 23, 57, 4, 63, 6, 20, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139 + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 1, 34, 34, 34, 14, 14, + 34, 34, 34, 34, 34, 34, 34, 34, 13, 34, + 13, 34, 34, 12, 34, 34, 34, 34, 34, 11, + 34, 34, 34, 34, 34, 8, 34, 11, 34, 12, + 11, 0, 1, 34, 7, 0, 34, 34, 11, 9, + 0, 4, 0, 34, 7, 4, 14, 21, 34, 15, + 0, 2, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34 }; - 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; + return len + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]]; } -#ifdef __GNUC__ -__inline -#endif static struct C_stab_entry * in_word_set (str, len) register const char *str; register unsigned int len; { + enum + { + TOTAL_KEYWORDS = 31, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 15, + MIN_HASH_VALUE = 3, + MAX_HASH_VALUE = 33 + }; + static struct C_stab_entry wordlist[] = { - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {"if", 0, st_C_ignore}, - {""}, {""}, {""}, {""}, - {"int", 0, st_C_typespec}, - {""}, {""}, - {"void", 0, st_C_typespec}, - {""}, {""}, - {"interface", C_JAVA, st_C_struct}, - {""}, - {"SYSCALL", 0, st_C_gnumacro}, - {""}, - {"return", 0, st_C_ignore}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {"while", 0, st_C_ignore}, - {"auto", 0, st_C_typespec}, - {""}, {""}, {""}, {""}, {""}, {""}, - {"float", 0, st_C_typespec}, - {"typedef", 0, st_C_typedef}, - {"typename", C_PLPL, st_C_typespec}, {""}, {""}, {""}, - {"friend", C_PLPL, st_C_ignore}, - {"volatile", 0, st_C_typespec}, - {""}, {""}, - {"for", 0, st_C_ignore}, - {"const", 0, st_C_typespec}, - {"import", C_JAVA, st_C_ignore}, - {""}, - {"define", 0, st_C_define}, - {"long", 0, st_C_typespec}, - {"implements", C_JAVA, st_C_javastruct}, - {"signed", 0, st_C_typespec}, - {""}, - {"extern", 0, st_C_extern}, - {"extends", C_JAVA, st_C_javastruct}, - {""}, - {"mutable", C_PLPL, st_C_typespec}, - {"template", 0, st_C_template}, - {"short", 0, st_C_typespec}, - {"bool", C_PLPL, st_C_typespec}, - {"char", 0, st_C_typespec}, - {"class", 0, st_C_class}, - {"operator", C_PLPL, st_C_operator}, - {""}, - {"switch", 0, st_C_ignore}, - {""}, - {"ENTRY", 0, st_C_gnumacro}, - {""}, - {"package", C_JAVA, st_C_ignore}, - {"union", 0, st_C_struct}, - {"@end", 0, st_C_objend}, - {"struct", 0, st_C_struct}, - {"namespace", C_PLPL, st_C_struct}, - {""}, {""}, - {"domain", C_STAR, st_C_struct}, - {"@interface", 0, st_C_objprot}, - {"PSEUDO", 0, st_C_gnumacro}, - {"double", 0, st_C_typespec}, - {""}, - {"@protocol", 0, st_C_objprot}, - {""}, - {"static", 0, st_C_typespec}, - {""}, {""}, - {"DEFUN", 0, st_C_gnumacro}, - {""}, {""}, {""}, {""}, - {"explicit", C_PLPL, st_C_typespec}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {""}, - {"enum", 0, st_C_enum}, - {""}, {""}, - {"unsigned", 0, st_C_typespec}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, - {"@implementation",0, st_C_objimpl} + {"if", 0, st_C_ignore}, + {"enum", 0, st_C_enum}, + {"@end", 0, st_C_objend}, + {"extern", 0, st_C_extern}, + {"extends", (C_JAVA & !C_PLPL), st_C_javastruct}, + {"for", 0, st_C_ignore}, + {"interface", (C_JAVA & !C_PLPL), st_C_struct}, + {"@protocol", 0, st_C_objprot}, + {"@interface", 0, st_C_objprot}, + {"operator", C_PLPL, st_C_operator}, + {"return", 0, st_C_ignore}, + {"friend", C_PLPL, st_C_ignore}, + {"import", (C_JAVA & !C_PLPL), st_C_ignore}, + {"@implementation",0, st_C_objimpl}, + {"define", 0, st_C_define}, + {"package", (C_JAVA & !C_PLPL), st_C_ignore}, + {"implements", (C_JAVA & !C_PLPL), st_C_javastruct}, + {"namespace", C_PLPL, st_C_struct}, + {"domain", C_STAR, st_C_struct}, + {"template", 0, st_C_template}, + {"typedef", 0, st_C_typedef}, + {"struct", 0, st_C_struct}, + {"switch", 0, st_C_ignore}, + {"union", 0, st_C_struct}, + {"while", 0, st_C_ignore}, + {"class", 0, st_C_class}, + {"__attribute__", 0, st_C_attribute}, + {"SYSCALL", 0, st_C_gnumacro}, + {"PSEUDO", 0, st_C_gnumacro}, + {"ENTRY", 0, st_C_gnumacro}, + {"DEFUN", 0, st_C_gnumacro} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -2602,7 +2561,7 @@ { register const char *s = wordlist[key].name; - if (*str == *s && !strncmp (str + 1, s + 1, len - 1)) + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist[key]; } } @@ -2625,6 +2584,11 @@ /* + * Ignoring __attribute__ ((list)) + */ +static bool inattribute; /* looking at an __attribute__ construct */ + +/* * C functions and variables are recognized using a simple * finite automaton. fvdef is its state variable. */ @@ -2666,10 +2630,9 @@ static enum { snone, /* nothing seen yet, - or in struct body if cblev > 0 */ + or in struct body if bracelev > 0 */ skeyseen, /* struct-like keyword seen */ stagseen, /* struct-like tag seen */ - sintemplate, /* inside template (ignore) */ scolonseen /* colon seen after struct-like tag */ } structdef; @@ -2743,7 +2706,7 @@ static struct { char **cname; /* nested class names */ - int *cblev; /* nested class curly brace level */ + int *bracelev; /* nested class brace level */ int nl; /* class nesting level (elements used) */ int size; /* length of the array */ } cstack; /* stack for nested declaration tags */ @@ -2751,38 +2714,38 @@ #define nestlev (cstack.nl) /* After struct keyword or in struct body, not inside a nested function. */ #define instruct (structdef == snone && nestlev > 0 \ - && cblev == cstack.cblev[nestlev-1] + 1) + && bracelev == cstack.bracelev[nestlev-1] + 1) static void -pushclass_above (cblev, str, len) - int cblev; +pushclass_above (bracelev, str, len) + int bracelev; char *str; int len; { int nl; - popclass_above (cblev); + popclass_above (bracelev); nl = cstack.nl; if (nl >= cstack.size) { int size = cstack.size *= 2; xrnew (cstack.cname, size, char *); - xrnew (cstack.cblev, size, int); + xrnew (cstack.bracelev, size, int); } - assert (nl == 0 || cstack.cblev[nl-1] < cblev); + assert (nl == 0 || cstack.bracelev[nl-1] < bracelev); cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len); - cstack.cblev[nl] = cblev; + cstack.bracelev[nl] = bracelev; cstack.nl = nl + 1; } static void -popclass_above (cblev) - int cblev; +popclass_above (bracelev) + int bracelev; { int nl; for (nl = cstack.nl - 1; - nl >= 0 && cstack.cblev[nl] >= cblev; + nl >= 0 && cstack.bracelev[nl] >= bracelev; nl--) { if (cstack.cname[nl] != NULL) @@ -2849,269 +2812,286 @@ */ static bool -consider_token (str, len, c, c_extp, cblev, parlev, is_func_or_var) +consider_token (str, len, c, c_extp, bracelev, parlev, is_func_or_var) register char *str; /* IN: token pointer */ register int len; /* IN: token length */ register int c; /* IN: first char after the token */ int *c_extp; /* IN, OUT: C extensions mask */ - int cblev; /* IN: curly brace level */ + int bracelev; /* IN: brace level */ int parlev; /* IN: parenthesis level */ bool *is_func_or_var; /* OUT: function or variable found */ { - /* When structdef is stagseen, scolonseen, or snone with cblev > 0, + /* When structdef is stagseen, scolonseen, or snone with bracelev > 0, structtype is the type of the preceding struct-like keyword, and - structcblev is the curly brace level where it has been seen. */ + structbracelev is the brace level where it has been seen. */ static enum sym_type structtype; - static int structcblev; + static int structbracelev; static enum sym_type toktype; toktype = C_symtype (str, len, *c_extp); /* - * Advance the definedef state machine. - */ - switch (definedef) - { - case dnone: - /* We're not on a preprocessor line. */ - if (toktype == st_C_gnumacro) - { - fvdef = fdefunkey; - return FALSE; - } - break; - case dsharpseen: - if (toktype == st_C_define) - { - definedef = ddefineseen; - } - else - { - definedef = dignorerest; - } - return FALSE; - case ddefineseen: - /* - * Make a tag for any macro, unless it is a constant - * and constantypedefs is FALSE. - */ - definedef = dignorerest; - *is_func_or_var = (c == '('); - if (!*is_func_or_var && !constantypedefs) - return FALSE; - else - return TRUE; - case dignorerest: - return FALSE; - default: - error ("internal error: definedef value.", (char *)NULL); - } - - /* - * Now typedefs + * Skip __attribute__ */ - switch (typdef) - { - case tnone: - if (toktype == st_C_typedef) - { - if (typedefs) - typdef = tkeyseen; - fvextern = FALSE; - fvdef = fvnone; - return FALSE; - } - break; - case tkeyseen: - switch (toktype) - { - case st_none: - case st_C_typespec: - case st_C_class: - case st_C_struct: - case st_C_enum: - typdef = ttypeseen; - break; - } - break; - case ttypeseen: - if (structdef == snone && fvdef == fvnone) - { - fvdef = fvnameseen; - return TRUE; - } - break; - case tend: - switch (toktype) - { - case st_C_typespec: - case st_C_class: - case st_C_struct: - case st_C_enum: - return FALSE; - } - return TRUE; - } - - /* - * This structdef business is NOT invoked when we are ctags and the - * file is plain C. This is because a struct tag may have the same - * name as another tag, and this loses with ctags. - */ - switch (toktype) - { - case st_C_javastruct: - if (structdef == stagseen) - structdef = scolonseen; - return FALSE; - case st_C_template: - case st_C_class: - if ((*c_extp & C_AUTO) /* automatic detection of C++ language */ - && cblev == 0 - && definedef == dnone && structdef == snone - && typdef == tnone && fvdef == fvnone) - *c_extp = (*c_extp | C_PLPL) & ~C_AUTO; - if (toktype == st_C_template) - break; - /* FALLTHRU */ - case st_C_struct: - case st_C_enum: - if (parlev == 0 - && fvdef != vignore - && (typdef == tkeyseen - || (typedefs_or_cplusplus && structdef == snone))) - { - structdef = skeyseen; - structtype = toktype; - structcblev = cblev; - } - return FALSE; - } - - if (structdef == skeyseen) + if (toktype == st_C_attribute) { - structdef = stagseen; - return TRUE; - } - - if (typdef != tnone) - definedef = dnone; - - /* Detect Objective C constructs. */ - switch (objdef) - { - case onone: - switch (toktype) - { - case st_C_objprot: - objdef = oprotocol; - return FALSE; - case st_C_objimpl: - objdef = oimplementation; - return FALSE; - } - break; - case oimplementation: - /* Save the class tag for functions or variables defined inside. */ - objtag = savenstr (str, len); - objdef = oinbody; - return FALSE; - case oprotocol: - /* Save the class tag for categories. */ - objtag = savenstr (str, len); - objdef = otagseen; - *is_func_or_var = TRUE; - return TRUE; - case oparenseen: - objdef = ocatseen; - *is_func_or_var = TRUE; - return TRUE; - case oinbody: - break; - case omethodsign: - if (parlev == 0) - { - objdef = omethodtag; - linebuffer_setlen (&token_name, len); - strncpy (token_name.buffer, str, len); - token_name.buffer[len] = '\0'; - return TRUE; - } - return FALSE; - case omethodcolon: - if (parlev == 0) - objdef = omethodparm; - return FALSE; - case omethodparm: - if (parlev == 0) - { - objdef = omethodtag; - linebuffer_setlen (&token_name, token_name.len + len); - strncat (token_name.buffer, str, len); - return TRUE; - } + inattribute = TRUE; return FALSE; - case oignore: - if (toktype == st_C_objend) - { - /* Memory leakage here: the string pointed by objtag is - never released, because many tests would be needed to - avoid breaking on incorrect input code. The amount of - memory leaked here is the sum of the lengths of the - class tags. - free (objtag); */ - objdef = onone; - } - return FALSE; - } - - /* A function, variable or enum constant? */ - switch (toktype) - { - case st_C_extern: - fvextern = TRUE; - /* FALLTHRU */ - case st_C_typespec: - switch (fvdef) - { - case finlist: - case flistseen: - case fignore: - case vignore: - break; - default: - fvdef = fvnone; - } - return FALSE; - case st_C_ignore: - fvextern = FALSE; - fvdef = vignore; - return FALSE; - case st_C_operator: - fvdef = foperator; - *is_func_or_var = TRUE; - return TRUE; - case st_none: - if (constantypedefs - && structdef == snone - && structtype == st_C_enum && cblev > structcblev) - return TRUE; /* enum constant */ - switch (fvdef) - { - case fdefunkey: - if (cblev > 0) - break; - fvdef = fdefunname; /* GNU macro */ - *is_func_or_var = TRUE; - return TRUE; - case fvnone: - if ((strneq (str, "asm", 3) && endtoken (str[3])) - || (strneq (str, "__asm__", 7) && endtoken (str[7]))) - { - fvdef = vignore; - return FALSE; - } + } + + /* + * Advance the definedef state machine. + */ + switch (definedef) + { + case dnone: + /* We're not on a preprocessor line. */ + if (toktype == st_C_gnumacro) + { + fvdef = fdefunkey; + return FALSE; + } + break; + case dsharpseen: + if (toktype == st_C_define) + { + definedef = ddefineseen; + } + else + { + definedef = dignorerest; + } + return FALSE; + case ddefineseen: + /* + * Make a tag for any macro, unless it is a constant + * and constantypedefs is FALSE. + */ + definedef = dignorerest; + *is_func_or_var = (c == '('); + if (!*is_func_or_var && !constantypedefs) + return FALSE; + else + return TRUE; + case dignorerest: + return FALSE; + default: + error ("internal error: definedef value.", (char *)NULL); + } + + /* + * Now typedefs + */ + switch (typdef) + { + case tnone: + if (toktype == st_C_typedef) + { + if (typedefs) + typdef = tkeyseen; + fvextern = FALSE; + fvdef = fvnone; + return FALSE; + } + break; + case tkeyseen: + switch (toktype) + { + case st_none: + case st_C_class: + case st_C_struct: + case st_C_enum: + typdef = ttypeseen; + } + break; + case ttypeseen: + if (structdef == snone && fvdef == fvnone) + { + fvdef = fvnameseen; + return TRUE; + } + break; + case tend: + switch (toktype) + { + case st_C_class: + case st_C_struct: + case st_C_enum: + return FALSE; + } + return TRUE; + } + + /* + * This structdef business is NOT invoked when we are ctags and the + * file is plain C. This is because a struct tag may have the same + * name as another tag, and this loses with ctags. + */ + switch (toktype) + { + case st_C_javastruct: + if (structdef == stagseen) + structdef = scolonseen; + return FALSE; + case st_C_template: + case st_C_class: + if ((*c_extp & C_AUTO) /* automatic detection of C++ language */ + && bracelev == 0 + && definedef == dnone && structdef == snone + && typdef == tnone && fvdef == fvnone) + *c_extp = (*c_extp | C_PLPL) & ~C_AUTO; + if (toktype == st_C_template) + break; + /* FALLTHRU */ + case st_C_struct: + case st_C_enum: + if (parlev == 0 + && fvdef != vignore + && (typdef == tkeyseen + || (typedefs_or_cplusplus && structdef == snone))) + { + structdef = skeyseen; + structtype = toktype; + structbracelev = bracelev; + if (fvdef == fvnameseen) + fvdef = fvnone; + } + return FALSE; + } + + if (structdef == skeyseen) + { + structdef = stagseen; + return TRUE; + } + + if (typdef != tnone) + definedef = dnone; + + /* Detect Objective C constructs. */ + switch (objdef) + { + case onone: + switch (toktype) + { + case st_C_objprot: + objdef = oprotocol; + return FALSE; + case st_C_objimpl: + objdef = oimplementation; + return FALSE; + } + break; + case oimplementation: + /* Save the class tag for functions or variables defined inside. */ + objtag = savenstr (str, len); + objdef = oinbody; + return FALSE; + case oprotocol: + /* Save the class tag for categories. */ + objtag = savenstr (str, len); + objdef = otagseen; + *is_func_or_var = TRUE; + return TRUE; + case oparenseen: + objdef = ocatseen; + *is_func_or_var = TRUE; + return TRUE; + case oinbody: + break; + case omethodsign: + if (parlev == 0) + { + fvdef = fvnone; + objdef = omethodtag; + linebuffer_setlen (&token_name, len); + strncpy (token_name.buffer, str, len); + token_name.buffer[len] = '\0'; + return TRUE; + } + return FALSE; + case omethodcolon: + if (parlev == 0) + objdef = omethodparm; + return FALSE; + case omethodparm: + if (parlev == 0) + { + fvdef = fvnone; + objdef = omethodtag; + linebuffer_setlen (&token_name, token_name.len + len); + strncat (token_name.buffer, str, len); + return TRUE; + } + return FALSE; + case oignore: + if (toktype == st_C_objend) + { + /* Memory leakage here: the string pointed by objtag is + never released, because many tests would be needed to + avoid breaking on incorrect input code. The amount of + memory leaked here is the sum of the lengths of the + class tags. + free (objtag); */ + objdef = onone; + } + return FALSE; + } + + /* A function, variable or enum constant? */ + switch (toktype) + { + case st_C_extern: + fvextern = TRUE; + switch (fvdef) + { + case finlist: + case flistseen: + case fignore: + case vignore: + break; + default: + fvdef = fvnone; + } + return FALSE; + case st_C_ignore: + fvextern = FALSE; + fvdef = vignore; + return FALSE; + case st_C_operator: + fvdef = foperator; + *is_func_or_var = TRUE; + return TRUE; + case st_none: + if (constantypedefs + && structdef == snone + && structtype == st_C_enum && bracelev > structbracelev) + return TRUE; /* enum constant */ + switch (fvdef) + { + case fdefunkey: + if (bracelev > 0) + break; + fvdef = fdefunname; /* GNU macro */ + *is_func_or_var = TRUE; + return TRUE; + case fvnone: + switch (typdef) + { + case ttypeseen: + return FALSE; + case tnone: + if ((strneq (str, "asm", 3) && endtoken (str[3])) + || (strneq (str, "__asm__", 7) && endtoken (str[7]))) + { + fvdef = vignore; + return FALSE; + } + break; + } + /* FALLTHRU */ + case fvnameseen: if (len >= 10 && strneq (str+len-10, "::operator", 10)) { if (*c_extp & C_AUTO) /* automatic detection of C++ */ @@ -3120,7 +3100,7 @@ *is_func_or_var = TRUE; return TRUE; } - if (cblev > 0 && !instruct) + if (bracelev > 0 && !instruct) break; fvdef = fvnameseen; /* function or variable */ *is_func_or_var = TRUE; @@ -3216,9 +3196,12 @@ register int toklen; /* length of current token */ char *qualifier; /* string used to qualify names */ int qlen; /* length of qualifier */ - int cblev; /* current curly brace level */ + int bracelev; /* current brace level */ + int bracketlev; /* current bracket level */ int parlev; /* current parenthesis level */ - int typdefcblev; /* cblev where a typedef struct body begun */ + int attrparlev; /* __attribute__ parenthesis level */ + int templatelev; /* current template level */ + int typdefbracelev; /* bracelev where a typedef struct body begun */ bool incomm, inquote, inchar, quotednl, midtoken; bool yacc_rules; /* in the rules part of a yacc file */ struct tok savetoken; /* token saved during preprocessor handling */ @@ -3231,10 +3214,10 @@ cstack.size = (DEBUG) ? 1 : 4; cstack.nl = 0; cstack.cname = xnew (cstack.size, char *); - cstack.cblev = xnew (cstack.size, int); + cstack.bracelev = xnew (cstack.size, int); } - tokoff = toklen = typdefcblev = 0; /* keep compiler quiet */ + tokoff = toklen = typdefbracelev = 0; /* keep compiler quiet */ curndx = newndx = 0; lp = curlb.buffer; *lp = 0; @@ -3244,8 +3227,7 @@ yacc_rules = FALSE; midtoken = inquote = inchar = incomm = quotednl = FALSE; token.valid = savetoken.valid = FALSE; - cblev = 0; - parlev = 0; + bracelev = bracketlev = parlev = attrparlev = templatelev = 0; if (cjava) { qualifier = "."; qlen = 1; } else @@ -3257,8 +3239,8 @@ c = *lp++; if (c == '\\') { - /* If we're at the end of the line, the next character is a - '\0'; don't skip it, because it's the thing that tells us + /* If we are at the end of the line, the next character is a + '\0'; do not skip it, because it is what tells us to read the next line. */ if (*lp == '\0') { @@ -3317,95 +3299,115 @@ } continue; } - else - switch (c) - { - case '"': - inquote = TRUE; - switch (fvdef) - { - case fdefunkey: - case fstartlist: - case finlist: - case fignore: - case vignore: - break; - default: - fvextern = FALSE; - fvdef = fvnone; - } - continue; - case '\'': - inchar = TRUE; - if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) - { - fvextern = FALSE; - fvdef = fvnone; - } - continue; - case '/': - if (*lp == '*') - { - lp++; - incomm = TRUE; + else if (bracketlev > 0) + { + switch (c) + { + case ']': + if (--bracketlev > 0) continue; - } - else if (/* cplpl && */ *lp == '/') - { - c = '\0'; - break; - } - else + break; + case '\0': + CNL_SAVE_DEFINEDEF (); + break; + } + continue; + } + else switch (c) + { + case '"': + inquote = TRUE; + if (inattribute) + break; + switch (fvdef) + { + case fdefunkey: + case fstartlist: + case finlist: + case fignore: + case vignore: break; - case '%': - if ((c_ext & YACC) && *lp == '%') - { - /* Entering or exiting rules section in yacc file. */ - lp++; - definedef = dnone; fvdef = fvnone; fvextern = FALSE; - typdef = tnone; structdef = snone; - midtoken = inquote = inchar = incomm = quotednl = FALSE; - cblev = 0; - yacc_rules = !yacc_rules; - continue; - } - else + default: + fvextern = FALSE; + fvdef = fvnone; + } + continue; + case '\'': + inchar = TRUE; + if (inattribute) + break; + if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) + { + fvextern = FALSE; + fvdef = fvnone; + } + continue; + case '/': + if (*lp == '*') + { + lp++; + incomm = TRUE; + continue; + } + else if (/* cplpl && */ *lp == '/') + { + c = '\0'; break; - case '#': - if (definedef == dnone) - { - char *cp; - bool cpptoken = TRUE; - - /* Look back on this line. If all blanks, or nonblanks - followed by an end of comment, this is a preprocessor - token. */ - for (cp = newlb.buffer; cp < lp-1; cp++) - if (!iswhite (*cp)) - { - if (*cp == '*' && *(cp+1) == '/') - { - cp++; - cpptoken = TRUE; - } - else - cpptoken = FALSE; - } - if (cpptoken) - definedef = dsharpseen; - } /* if (definedef == dnone) */ - + } + else + break; + case '%': + if ((c_ext & YACC) && *lp == '%') + { + /* Entering or exiting rules section in yacc file. */ + lp++; + definedef = dnone; fvdef = fvnone; fvextern = FALSE; + typdef = tnone; structdef = snone; + midtoken = inquote = inchar = incomm = quotednl = FALSE; + bracelev = 0; + yacc_rules = !yacc_rules; + continue; + } + else + break; + case '#': + if (definedef == dnone) + { + char *cp; + bool cpptoken = TRUE; + + /* Look back on this line. If all blanks, or nonblanks + followed by an end of comment, this is a preprocessor + token. */ + for (cp = newlb.buffer; cp < lp-1; cp++) + if (!iswhite (*cp)) + { + if (*cp == '*' && *(cp+1) == '/') + { + cp++; + cpptoken = TRUE; + } + else + cpptoken = FALSE; + } + if (cpptoken) + definedef = dsharpseen; + } /* if (definedef == dnone) */ + continue; + case '[': + bracketlev++; continue; - } /* switch (c) */ + } /* switch (c) */ /* Consider token only if some involved conditions are satisfied. */ if (typdef != tignore && definedef != dignorerest && fvdef != finlist - && structdef != sintemplate + && templatelev == 0 && (definedef != dnone - || structdef != scolonseen)) + || structdef != scolonseen) + && !inattribute) { if (midtoken) { @@ -3429,7 +3431,8 @@ if (yacc_rules || consider_token (newlb.buffer + tokoff, toklen, c, - &c_ext, cblev, parlev, &funorvar)) + &c_ext, bracelev, parlev, + &funorvar)) { if (fvdef == foperator) { @@ -3514,7 +3517,7 @@ || (funorvar && definedef == dnone && structdef == snone - && cblev > 0)); + && bracelev > 0)); } token.lineno = lineno; token.offset = tokoff; @@ -3539,6 +3542,16 @@ || instruct) make_C_tag (funorvar); } + else /* not yacc and consider_token failed */ + { + if (inattribute && fvdef == fignore) + { + /* We have just met __attribute__ after a + function parameter list: do not tag the + function again. */ + fvdef = fvnone; + } + } midtoken = FALSE; } } /* if (endtoken (c)) */ @@ -3557,6 +3570,9 @@ switch (fvdef) { case fstartlist: + /* This prevents tagging fb in + void (__attribute__((noreturn)) *fb) (void); + Fixing this is not easy and not very important. */ fvdef = finlist; continue; case flistseen: @@ -3566,13 +3582,10 @@ fvdef = fignore; } break; - case fvnameseen: - fvdef = fvnone; - break; } if (structdef == stagseen && !cjava) { - popclass_above (cblev); + popclass_above (bracelev); structdef = snone; } break; @@ -3596,6 +3609,8 @@ switch (c) { case ':': + if (inattribute) + break; if (yacc_rules && token.offset == 0 && token.valid) { make_C_tag (FALSE); /* a yacc function */ @@ -3630,7 +3645,7 @@ } break; case ';': - if (definedef != dnone) + if (definedef != dnone || inattribute) break; switch (typdef) { @@ -3650,7 +3665,7 @@ fvdef = fvnone; break; case fvnameseen: - if ((globals && cblev == 0 && (!fvextern || declarations)) + if ((globals && bracelev == 0 && (!fvextern || declarations)) || (members && instruct)) make_C_tag (FALSE); /* a variable */ fvextern = FALSE; @@ -3658,9 +3673,12 @@ token.valid = FALSE; break; case flistseen: - if (declarations - && (typdef == tnone || (typdef != tignore && instruct))) - make_C_tag (TRUE); /* a function declaration */ + if ((declarations + && (cplpl || !instruct) + && (typdef == tnone || (typdef != tignore && instruct))) + || (members + && plainc && instruct)) + make_C_tag (TRUE); /* a function */ /* FALLTHRU */ default: fvextern = FALSE; @@ -3680,7 +3698,7 @@ structdef = snone; break; case ',': - if (definedef != dnone) + if (definedef != dnone || inattribute) break; switch (objdef) { @@ -3702,16 +3720,20 @@ case fdefunname: fvdef = fignore; break; - case fvnameseen: /* a variable */ - if ((globals && cblev == 0 && (!fvextern || declarations)) - || (members && instruct)) - make_C_tag (FALSE); + case fvnameseen: + if (parlev == 0 + && ((globals + && bracelev == 0 + && templatelev == 0 + && (!fvextern || declarations)) + || (members && instruct))) + make_C_tag (FALSE); /* a variable */ break; - case flistseen: /* a function */ + case flistseen: if ((declarations && typdef == tnone && !instruct) || (members && typdef != tignore && instruct)) { - make_C_tag (TRUE); /* a function declaration */ + make_C_tag (TRUE); /* a function */ fvdef = fvnameseen; } else if (!declarations) @@ -3724,8 +3746,8 @@ if (structdef == stagseen) structdef = snone; break; - case '[': - if (definedef != dnone) + case ']': + if (definedef != dnone || inattribute) break; if (structdef == stagseen) structdef = snone; @@ -3746,8 +3768,8 @@ case vignore: break; case fvnameseen: - if ((members && cblev == 1) - || (globals && cblev == 0 + if ((members && bracelev == 1) + || (globals && bracelev == 0 && (!fvextern || declarations))) make_C_tag (FALSE); /* a variable */ /* FALLTHRU */ @@ -3758,6 +3780,11 @@ } break; case '(': + if (inattribute) + { + attrparlev++; + break; + } if (definedef != dnone) break; if (objdef == otagseen && parlev == 0) @@ -3787,6 +3814,12 @@ parlev++; break; case ')': + if (inattribute) + { + if (--attrparlev == 0) + inattribute = FALSE; + break; + } if (definedef != dnone) break; if (objdef == ocatseen && parlev == 1) @@ -3820,9 +3853,9 @@ if (typdef == ttypeseen) { /* Whenever typdef is set to tinbody (currently only - here), typdefcblev should be set to cblev. */ + here), typdefbracelev should be set to bracelev. */ typdef = tinbody; - typdefcblev = cblev; + typdefbracelev = bracelev; } switch (fvdef) { @@ -3846,26 +3879,26 @@ break; default: /* Neutralize `extern "C" {' grot. */ - if (cblev == 0 && structdef == snone && nestlev == 0 + if (bracelev == 0 && structdef == snone && nestlev == 0 && typdef == tnone) - cblev = -1; + bracelev = -1; } break; } switch (structdef) { case skeyseen: /* unnamed struct */ - pushclass_above (cblev, NULL, 0); + pushclass_above (bracelev, NULL, 0); structdef = snone; break; case stagseen: /* named struct or enum */ case scolonseen: /* a class */ - pushclass_above (cblev, token.line+token.offset, token.length); + pushclass_above (bracelev,token.line+token.offset, token.length); structdef = snone; make_C_tag (FALSE); /* a struct or enum */ break; } - cblev++; + bracelev++; break; case '*': if (definedef != dnone) @@ -3881,21 +3914,21 @@ break; if (!ignoreindent && lp == newlb.buffer + 1) { - if (cblev != 0) + if (bracelev != 0) token.valid = FALSE; - cblev = 0; /* reset curly brace level if first column */ + bracelev = 0; /* reset brace level if first column */ parlev = 0; /* also reset paren level, just in case... */ } - else if (cblev > 0) - cblev--; + else if (bracelev > 0) + bracelev--; else token.valid = FALSE; /* something gone amiss, token unreliable */ - popclass_above (cblev); + popclass_above (bracelev); structdef = snone; - /* Only if typdef == tinbody is typdefcblev significant. */ - if (typdef == tinbody && cblev <= typdefcblev) + /* Only if typdef == tinbody is typdefbracelev significant. */ + if (typdef == tinbody && bracelev <= typdefbracelev) { - assert (cblev == typdefcblev); + assert (bracelev == typdefbracelev); typdef = tend; } break; @@ -3910,8 +3943,8 @@ case vignore: break; case fvnameseen: - if ((members && cblev == 1) - || (globals && cblev == 0 && (!fvextern || declarations))) + if ((members && bracelev == 1) + || (globals && bracelev == 0 && (!fvextern || declarations))) make_C_tag (FALSE); /* a variable */ /* FALLTHRU */ default: @@ -3919,30 +3952,31 @@ } break; case '<': - if (cplpl && structdef == stagseen) + if (cplpl + && (structdef == stagseen || fvdef == fvnameseen)) { - structdef = sintemplate; + templatelev++; break; } goto resetfvdef; case '>': - if (structdef == sintemplate) + if (templatelev > 0) { - structdef = stagseen; + templatelev--; break; } goto resetfvdef; case '+': case '-': - if (objdef == oinbody && cblev == 0) + if (objdef == oinbody && bracelev == 0) { objdef = omethodsign; break; } /* FALLTHRU */ resetfvdef: - case '#': case '~': case '&': case '%': case '/': case '|': - case '^': case '!': case '.': case '?': case ']': + case '#': case '~': case '&': case '%': case '/': + case '|': case '^': case '!': case '.': case '?': if (definedef != dnone) break; /* These surely cannot follow a function tag in C. */ @@ -4894,6 +4928,31 @@ /* + * Lua script language parsing + * Original code by David A. Capello <dacap@users.sourceforge.net> (2004) + * + * "function" and "local function" are tags if they start at column 1. + */ +static void +Lua_functions (inf) + FILE *inf; +{ + register char *bp; + + LOOP_ON_INPUT_LINES (inf, lb, bp) + { + if (bp[0] != 'f' && bp[0] != 'l') + continue; + + LOOKING_AT (bp, "local"); /* skip possible "local" */ + + if (LOOKING_AT (bp, "function")) + get_tag (bp, NULL); + } +} + + +/* * Postscript tag functions * Just look for lines where the first character is '/' * Also look at "defineps" for PSWrap