1 /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*-
2 Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of GNU Emacs.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Line-by-line regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
32 * 2002 #line directives by Francesco Potortì.
34 * Francesco Potortì <pot@gnu.org> has maintained and improved it since 1993.
38 * If you want to add support for a new language, start by looking at the LUA
39 * language, which is the simplest. Alternatively, consider shipping a
40 * configuration file containing regexp definitions for etags.
43 char pot_etags_version
[] = "@(#) pot revision number is 17.5";
53 # define NDEBUG /* disable assert */
58 /* On some systems, Emacs defines static as nothing for the sake
59 of unexec. We don't want that here since we don't use unexec. */
61 # define ETAGS_REGEXPS /* use the regexp features */
62 # define LONG_OPTIONS /* accept long options */
63 # ifndef PTR /* for Xemacs */
66 # ifndef __P /* for Xemacs */
67 # define __P(args) args
69 #else /* no config.h */
70 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
71 # define __P(args) args /* use prototypes */
72 # define PTR void * /* for generic pointers */
73 # else /* not standard C */
74 # define __P(args) () /* no prototypes */
75 # define const /* remove const for old compilers' sake */
76 # define PTR long * /* don't use void* */
78 #endif /* !HAVE_CONFIG_H */
81 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
86 # define LONG_OPTIONS TRUE
88 # define LONG_OPTIONS FALSE
91 /* WIN32_NATIVE is for Xemacs.
92 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
97 #endif /* WIN32_NATIVE */
103 # include <sys/param.h>
105 # ifndef HAVE_CONFIG_H
107 # include <sys/config.h>
119 # define MAXPATHLEN _MAX_PATH
125 # endif /* undef HAVE_GETCWD */
126 #else /* not WINDOWSNT */
130 # else /* no standard C headers */
131 extern char *getenv ();
133 # define EXIT_SUCCESS 1
134 # define EXIT_FAILURE 0
136 # define EXIT_SUCCESS 0
137 # define EXIT_FAILURE 1
140 #endif /* !WINDOWSNT */
145 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
146 extern char *getcwd (char *buf
, size_t size
);
148 #endif /* HAVE_UNISTD_H */
156 #include <sys/types.h>
157 #include <sys/stat.h>
161 # undef assert /* some systems have a buggy assert.h */
162 # define assert(x) ((void) 0)
165 #if !defined (S_ISREG) && defined (S_IFREG)
166 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
172 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
174 extern int optind
, opterr
;
175 #endif /* LONG_OPTIONS */
178 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
179 # ifdef __CYGWIN__ /* compiling on Cygwin */
181 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
182 If you want regular expression support
, you should
delete this notice
and
183 arrange to use the GNU regex
.h
and regex
.c
.
187 #endif /* ETAGS_REGEXPS */
189 /* Define CTAGS to make the program "ctags" compatible with the usual one.
190 Leave it undefined to make the program "etags", which makes emacs-style
191 tag tables and tags typedefs, #defines and struct/union/enum by default. */
199 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
200 #define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
201 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
202 #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
204 #define CHARS 256 /* 2^sizeof(char) */
205 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
206 #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
207 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
208 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
209 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
210 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
212 #define ISALNUM(c) isalnum (CHAR(c))
213 #define ISALPHA(c) isalpha (CHAR(c))
214 #define ISDIGIT(c) isdigit (CHAR(c))
215 #define ISLOWER(c) islower (CHAR(c))
217 #define lowcase(c) tolower (CHAR(c))
218 #define upcase(c) toupper (CHAR(c))
222 * xnew, xrnew -- allocate, reallocate storage
224 * SYNOPSIS: Type *xnew (int n, Type);
225 * void xrnew (OldPointer, int n, Type);
228 # include "chkmalloc.h"
229 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
230 (n) * sizeof (Type)))
231 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
232 (char *) (op), (n) * sizeof (Type)))
234 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
235 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
236 (char *) (op), (n) * sizeof (Type)))
241 typedef void Lang_function
__P((FILE *));
245 char *suffix
; /* file name suffix for this compressor */
246 char *command
; /* takes one arg and decompresses to stdout */
251 char *name
; /* language name */
252 char *help
; /* detailed help for the language */
253 Lang_function
*function
; /* parse function */
254 char **suffixes
; /* name suffixes of this language's files */
255 char **filenames
; /* names of this language's files */
256 char **interpreters
; /* interpreters for this language */
257 bool metasource
; /* source used to generate other sources */
262 struct fdesc
*next
; /* for the linked list */
263 char *infname
; /* uncompressed input file name */
264 char *infabsname
; /* absolute uncompressed input file name */
265 char *infabsdir
; /* absolute dir of input file */
266 char *taggedfname
; /* file name to write in tagfile */
267 language
*lang
; /* language of file */
268 char *prop
; /* file properties to write in tagfile */
269 bool usecharno
; /* etags tags shall contain char number */
270 bool written
; /* entry written in the tags file */
273 typedef struct node_st
274 { /* sorting structure */
275 struct node_st
*left
, *right
; /* left and right sons */
276 fdesc
*fdp
; /* description of file to whom tag belongs */
277 char *name
; /* tag name */
278 char *regex
; /* search regexp */
279 bool valid
; /* write this tag on the tag file */
280 bool is_func
; /* function tag: use regexp in CTAGS mode */
281 bool been_warned
; /* warning already given for duplicated tag */
282 int lno
; /* line number tag is on */
283 long cno
; /* character number line starts on */
287 * A `linebuffer' is a structure which holds a line of text.
288 * `readline_internal' reads a line from a stream into a linebuffer
289 * and works regardless of the length of the line.
290 * SIZE is the size of BUFFER, LEN is the length of the string in
291 * BUFFER after readline reads it.
300 /* Used to support mixing of --lang and file names. */
304 at_language
, /* a language specification */
305 at_regexp
, /* a regular expression */
306 at_filename
, /* a file name */
307 at_stdin
, /* read from stdin here */
308 at_end
/* stop parsing the list */
309 } arg_type
; /* argument type */
310 language
*lang
; /* language associated with the argument */
311 char *what
; /* the argument itself */
315 /* Structure defining a regular expression. */
316 typedef struct regexp
318 struct regexp
*p_next
; /* pointer to next in list */
319 language
*lang
; /* if set, use only for this language */
320 char *pattern
; /* the regexp pattern */
321 char *name
; /* tag name */
322 struct re_pattern_buffer
*pat
; /* the compiled pattern */
323 struct re_registers regs
; /* re registers */
324 bool error_signaled
; /* already signaled for this regexp */
325 bool force_explicit_name
; /* do not allow implict tag name */
326 bool ignore_case
; /* ignore case when matching */
327 bool multi_line
; /* do a multi-line match on the whole file */
329 #endif /* ETAGS_REGEXPS */
332 /* Many compilers barf on this:
333 Lang_function Ada_funcs;
334 so let's write it this way */
335 static void Ada_funcs
__P((FILE *));
336 static void Asm_labels
__P((FILE *));
337 static void C_entries
__P((int c_ext
, FILE *));
338 static void default_C_entries
__P((FILE *));
339 static void plain_C_entries
__P((FILE *));
340 static void Cjava_entries
__P((FILE *));
341 static void Cobol_paragraphs
__P((FILE *));
342 static void Cplusplus_entries
__P((FILE *));
343 static void Cstar_entries
__P((FILE *));
344 static void Erlang_functions
__P((FILE *));
345 static void Fortran_functions
__P((FILE *));
346 static void HTML_labels
__P((FILE *));
347 static void Lisp_functions
__P((FILE *));
348 static void Lua_functions
__P((FILE *));
349 static void Makefile_targets
__P((FILE *));
350 static void Pascal_functions
__P((FILE *));
351 static void Perl_functions
__P((FILE *));
352 static void PHP_functions
__P((FILE *));
353 static void PS_functions
__P((FILE *));
354 static void Prolog_functions
__P((FILE *));
355 static void Python_functions
__P((FILE *));
356 static void Scheme_functions
__P((FILE *));
357 static void TeX_commands
__P((FILE *));
358 static void Texinfo_nodes
__P((FILE *));
359 static void Yacc_entries
__P((FILE *));
360 static void just_read_file
__P((FILE *));
362 static void print_language_names
__P((void));
363 static void print_version
__P((void));
364 static void print_help
__P((argument
*));
365 int main
__P((int, char **));
367 static compressor
*get_compressor_from_suffix
__P((char *, char **));
368 static language
*get_language_from_langname
__P((const char *));
369 static language
*get_language_from_interpreter
__P((char *));
370 static language
*get_language_from_filename
__P((char *, bool));
371 static void readline
__P((linebuffer
*, FILE *));
372 static long readline_internal
__P((linebuffer
*, FILE *));
373 static bool nocase_tail
__P((char *));
374 static void get_tag
__P((char *, char **));
377 static void analyse_regex
__P((char *));
378 static void free_regexps
__P((void));
379 static void regex_tag_multiline
__P((void));
380 #endif /* ETAGS_REGEXPS */
381 static void error
__P((const char *, const char *));
382 static void suggest_asking_for_help
__P((void));
383 void fatal
__P((char *, char *));
384 static void pfatal
__P((char *));
385 static void add_node
__P((node
*, node
**));
387 static void init
__P((void));
388 static void process_file_name
__P((char *, language
*));
389 static void process_file
__P((FILE *, char *, language
*));
390 static void find_entries
__P((FILE *));
391 static void free_tree
__P((node
*));
392 static void free_fdesc
__P((fdesc
*));
393 static void pfnote
__P((char *, bool, char *, int, int, long));
394 static void make_tag
__P((char *, int, bool, char *, int, int, long));
395 static void invalidate_nodes
__P((fdesc
*, node
**));
396 static void put_entries
__P((node
*));
398 static char *concat
__P((char *, char *, char *));
399 static char *skip_spaces
__P((char *));
400 static char *skip_non_spaces
__P((char *));
401 static char *savenstr
__P((char *, int));
402 static char *savestr
__P((char *));
403 static char *etags_strchr
__P((const char *, int));
404 static char *etags_strrchr
__P((const char *, int));
405 static int etags_strcasecmp
__P((const char *, const char *));
406 static int etags_strncasecmp
__P((const char *, const char *, int));
407 static char *etags_getcwd
__P((void));
408 static char *relative_filename
__P((char *, char *));
409 static char *absolute_filename
__P((char *, char *));
410 static char *absolute_dirname
__P((char *, char *));
411 static bool filename_is_absolute
__P((char *f
));
412 static void canonicalize_filename
__P((char *));
413 static void linebuffer_init
__P((linebuffer
*));
414 static void linebuffer_setlen
__P((linebuffer
*, int));
415 static PTR xmalloc
__P((unsigned int));
416 static PTR xrealloc
__P((char *, unsigned int));
419 static char searchar
= '/'; /* use /.../ searches */
421 static char *tagfile
; /* output file */
422 static char *progname
; /* name this program was invoked with */
423 static char *cwd
; /* current working directory */
424 static char *tagfiledir
; /* directory of tagfile */
425 static FILE *tagf
; /* ioptr for tags file */
427 static fdesc
*fdhead
; /* head of file description list */
428 static fdesc
*curfdp
; /* current file description */
429 static int lineno
; /* line number of current line */
430 static long charno
; /* current character number */
431 static long linecharno
; /* charno of start of current line */
432 static char *dbp
; /* pointer to start of current tag */
434 static const int invalidcharno
= -1;
436 static node
*nodehead
; /* the head of the binary tree of tags */
437 static node
*last_node
; /* the last node created */
439 static linebuffer lb
; /* the current line */
440 static linebuffer filebuf
; /* a buffer containing the whole file */
441 static linebuffer token_name
; /* a buffer containing a tag name */
443 /* boolean "functions" (see init) */
444 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
447 *white
= " \f\t\n\r\v",
449 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
450 /* token ending chars */
451 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
452 /* token starting chars */
453 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
454 /* valid in-token chars */
455 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
457 static bool append_to_tagfile
; /* -a: append to tags */
458 /* The next four default to TRUE for etags, but to FALSE for ctags. */
459 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
460 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
461 /* 0 struct/enum/union decls, and C++ */
462 /* member functions. */
463 static bool constantypedefs
; /* -d: create tags for C #define, enum */
464 /* constants and variables. */
465 /* -D: opposite of -d. Default under ctags. */
466 static bool globals
; /* create tags for global variables */
467 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
468 static bool members
; /* create tags for C member variables */
469 static bool no_line_directive
; /* ignore #line directives (undocumented) */
470 static bool update
; /* -u: update tags */
471 static bool vgrind_style
; /* -v: create vgrind style index output */
472 static bool no_warnings
; /* -w: suppress warnings */
473 static bool cxref_style
; /* -x: create cxref style output */
474 static bool cplusplus
; /* .[hc] means C++, not C */
475 static bool ignoreindent
; /* -I: ignore indentation in C */
476 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
478 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
479 static bool parsing_stdin
; /* --parse-stdin used */
482 static regexp
*p_head
; /* list of all regexps */
483 static bool need_filebuf
; /* some regexes are multi-line */
485 # define need_filebuf FALSE
486 #endif /* ETAGS_REGEXPS */
489 static struct option longopts
[] =
491 { "packages-only", no_argument
, &packages_only
, TRUE
},
492 { "c++", no_argument
, NULL
, 'C' },
493 { "declarations", no_argument
, &declarations
, TRUE
},
494 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
495 { "help", no_argument
, NULL
, 'h' },
496 { "help", no_argument
, NULL
, 'H' },
497 { "ignore-indentation", no_argument
, NULL
, 'I' },
498 { "language", required_argument
, NULL
, 'l' },
499 { "members", no_argument
, &members
, TRUE
},
500 { "no-members", no_argument
, &members
, FALSE
},
501 { "output", required_argument
, NULL
, 'o' },
503 { "regex", required_argument
, NULL
, 'r' },
504 { "no-regex", no_argument
, NULL
, 'R' },
505 { "ignore-case-regex", required_argument
, NULL
, 'c' },
506 #endif /* ETAGS_REGEXPS */
507 { "parse-stdin", required_argument
, NULL
, STDIN
},
508 { "version", no_argument
, NULL
, 'V' },
510 #if CTAGS /* Etags options */
511 { "backward-search", no_argument
, NULL
, 'B' },
512 { "cxref", no_argument
, NULL
, 'x' },
513 { "defines", no_argument
, NULL
, 'd' },
514 { "globals", no_argument
, &globals
, TRUE
},
515 { "typedefs", no_argument
, NULL
, 't' },
516 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
517 { "update", no_argument
, NULL
, 'u' },
518 { "vgrind", no_argument
, NULL
, 'v' },
519 { "no-warn", no_argument
, NULL
, 'w' },
521 #else /* Ctags options */
522 { "append", no_argument
, NULL
, 'a' },
523 { "no-defines", no_argument
, NULL
, 'D' },
524 { "no-globals", no_argument
, &globals
, FALSE
},
525 { "include", required_argument
, NULL
, 'i' },
529 #endif /* LONG_OPTIONS */
531 static compressor compressors
[] =
533 { "z", "gzip -d -c"},
534 { "Z", "gzip -d -c"},
535 { "gz", "gzip -d -c"},
536 { "GZ", "gzip -d -c"},
537 { "bz2", "bzip2 -d -c" },
546 static char *Ada_suffixes
[] =
547 { "ads", "adb", "ada", NULL
};
548 static char Ada_help
[] =
549 "In Ada code, functions, procedures, packages, tasks and types are\n\
550 tags. Use the `--packages-only' option to create tags for\n\
552 Ada tag names have suffixes indicating the type of entity:\n\
553 Entity type: Qualifier:\n\
554 ------------ ----------\n\
561 Thus, `M-x find-tag <RET> bidule/b <RET>' will go directly to the\n\
562 body of the package `bidule', while `M-x find-tag <RET> bidule <RET>'\n\
563 will just search for any tag `bidule'.";
566 static char *Asm_suffixes
[] =
567 { "a", /* Unix assembler */
568 "asm", /* Microcontroller assembly */
569 "def", /* BSO/Tasking definition includes */
570 "inc", /* Microcontroller include files */
571 "ins", /* Microcontroller include files */
572 "s", "sa", /* Unix assembler */
573 "S", /* cpp-processed Unix assembler */
574 "src", /* BSO/Tasking C compiler output */
577 static char Asm_help
[] =
578 "In assembler code, labels appearing at the beginning of a line,\n\
579 followed by a colon, are tags.";
582 /* Note that .c and .h can be considered C++, if the --c++ flag was
583 given, or if the `class' or `template' keyowrds are met inside the file.
584 That is why default_C_entries is called for these. */
585 static char *default_C_suffixes
[] =
587 static char default_C_help
[] =
588 "In C code, any C function or typedef is a tag, and so are\n\
589 definitions of `struct', `union' and `enum'. `#define' macro\n\
590 definitions and `enum' constants are tags unless you specify\n\
591 `--no-defines'. Global variables are tags unless you specify\n\
592 `--no-globals'. Use of `--no-globals' and `--no-defines'\n\
593 can make the tags table file much smaller.\n\
594 You can tag function declarations and external variables by\n\
595 using `--declarations', and struct members by using `--members'.";
597 static char *Cplusplus_suffixes
[] =
598 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
599 "M", /* Objective C++ */
600 "pdb", /* Postscript with C syntax */
602 static char Cplusplus_help
[] =
603 "In C++ code, all the tag constructs of C code are tagged. (Use\n\
604 --help --lang=c --lang=c++ for full help.)\n\
605 In addition to C tags, member functions are also recognized, and\n\
606 optionally member variables if you use the `--members' option.\n\
607 Tags for variables and functions in classes are named `CLASS::VARIABLE'\n\
608 and `CLASS::FUNCTION'. `operator' definitions have tag names like\n\
611 static char *Cjava_suffixes
[] =
613 static char Cjava_help
[] =
614 "In Java code, all the tags constructs of C and C++ code are\n\
615 tagged. (Use --help --lang=c --lang=c++ --lang=java for full help.)";
618 static char *Cobol_suffixes
[] =
619 { "COB", "cob", NULL
};
620 static char Cobol_help
[] =
621 "In Cobol code, tags are paragraph names; that is, any word\n\
622 starting in column 8 and followed by a period.";
624 static char *Cstar_suffixes
[] =
625 { "cs", "hs", NULL
};
627 static char *Erlang_suffixes
[] =
628 { "erl", "hrl", NULL
};
629 static char Erlang_help
[] =
630 "In Erlang code, the tags are the functions, records and macros\n\
631 defined in the file.";
633 static char *Fortran_suffixes
[] =
634 { "F", "f", "f90", "for", NULL
};
635 static char Fortran_help
[] =
636 "In Fortran code, functions, subroutines and block data are tags.";
638 static char *HTML_suffixes
[] =
639 { "htm", "html", "shtml", NULL
};
640 static char HTML_help
[] =
641 "In HTML input files, the tags are the `title' and the `h1', `h2',\n\
642 `h3' headers. Also, tags are `name=' in anchors and all\n\
643 occurrences of `id='.";
645 static char *Lisp_suffixes
[] =
646 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
647 static char Lisp_help
[] =
648 "In Lisp code, any function defined with `defun', any variable\n\
649 defined with `defvar' or `defconst', and in general the first\n\
650 argument of any expression that starts with `(def' in column zero\n\
653 static char *Lua_suffixes
[] =
654 { "lua", "LUA", NULL
};
655 static char Lua_help
[] =
656 "In Lua scripts, all functions are tags.";
658 static char *Makefile_filenames
[] =
659 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
660 static char Makefile_help
[] =
661 "In makefiles, targets are tags; additionally, variables are tags\n\
662 unless you specify `--no-globals'.";
664 static char *Objc_suffixes
[] =
665 { "lm", /* Objective lex file */
666 "m", /* Objective C file */
668 static char Objc_help
[] =
669 "In Objective C code, tags include Objective C definitions for classes,\n\
670 class categories, methods and protocols. Tags for variables and\n\
671 functions in classes are named `CLASS::VARIABLE' and `CLASS::FUNCTION'.";
673 static char *Pascal_suffixes
[] =
674 { "p", "pas", NULL
};
675 static char Pascal_help
[] =
676 "In Pascal code, the tags are the functions and procedures defined\n\
679 static char *Perl_suffixes
[] =
680 { "pl", "pm", NULL
};
681 static char *Perl_interpreters
[] =
682 { "perl", "@PERL@", NULL
};
683 static char Perl_help
[] =
684 "In Perl code, the tags are the packages, subroutines and variables\n\
685 defined by the `package', `sub', `my' and `local' keywords. Use\n\
686 `--globals' if you want to tag global variables. Tags for\n\
687 subroutines are named `PACKAGE::SUB'. The name for subroutines\n\
688 defined in the default package is `main::SUB'.";
690 static char *PHP_suffixes
[] =
691 { "php", "php3", "php4", NULL
};
692 static char PHP_help
[] =
693 "In PHP code, tags are functions, classes and defines. When using\n\
694 the `--members' option, vars are tags too.";
696 static char *plain_C_suffixes
[] =
697 { "pc", /* Pro*C file */
700 static char *PS_suffixes
[] =
701 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
702 static char PS_help
[] =
703 "In PostScript code, the tags are the functions.";
705 static char *Prolog_suffixes
[] =
707 static char Prolog_help
[] =
708 "In Prolog code, tags are predicates and rules at the beginning of\n\
711 static char *Python_suffixes
[] =
713 static char Python_help
[] =
714 "In Python code, `def' or `class' at the beginning of a line\n\
717 /* Can't do the `SCM' or `scm' prefix with a version number. */
718 static char *Scheme_suffixes
[] =
719 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
720 static char Scheme_help
[] =
721 "In Scheme code, tags include anything defined with `def' or with a\n\
722 construct whose name starts with `def'. They also include\n\
723 variables set with `set!' at top level in the file.";
725 static char *TeX_suffixes
[] =
726 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
727 static char TeX_help
[] =
728 "In LaTeX text, the argument of any of the commands `\\chapter',\n\
729 `\\section', `\\subsection', `\\subsubsection', `\\eqno', `\\label',\n\
730 `\\ref', `\\cite', `\\bibitem', `\\part', `\\appendix', `\\entry',\n\
731 `\\index', `\\def', `\\newcommand', `\\renewcommand',\n\
732 `\\newenvironment' or `\\renewenvironment' is a tag.\n\
734 Other commands can be specified by setting the environment variable\n\
735 `TEXTAGS' to a colon-separated list like, for example,\n\
736 TEXTAGS=\"mycommand:myothercommand\".";
739 static char *Texinfo_suffixes
[] =
740 { "texi", "texinfo", "txi", NULL
};
741 static char Texinfo_help
[] =
742 "for texinfo files, lines starting with @node are tagged.";
744 static char *Yacc_suffixes
[] =
745 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
746 static char Yacc_help
[] =
747 "In Bison or Yacc input files, each rule defines as a tag the\n\
748 nonterminal it constructs. The portions of the file that contain\n\
749 C code are parsed as C code (use --help --lang=c --lang=yacc\n\
752 static char auto_help
[] =
753 "`auto' is not a real language, it indicates to use\n\
754 a default language for files base on file name suffix and file contents.";
756 static char none_help
[] =
757 "`none' is not a real language, it indicates to only do\n\
758 regexp processing on files.";
760 static char no_lang_help
[] =
761 "No detailed help available for this language.";
765 * Table of languages.
767 * It is ok for a given function to be listed under more than one
768 * name. I just didn't.
771 static language lang_names
[] =
773 { "ada", Ada_help
, Ada_funcs
, Ada_suffixes
},
774 { "asm", Asm_help
, Asm_labels
, Asm_suffixes
},
775 { "c", default_C_help
, default_C_entries
, default_C_suffixes
},
776 { "c++", Cplusplus_help
, Cplusplus_entries
, Cplusplus_suffixes
},
777 { "c*", no_lang_help
, Cstar_entries
, Cstar_suffixes
},
778 { "cobol", Cobol_help
, Cobol_paragraphs
, Cobol_suffixes
},
779 { "erlang", Erlang_help
, Erlang_functions
, Erlang_suffixes
},
780 { "fortran", Fortran_help
, Fortran_functions
, Fortran_suffixes
},
781 { "html", HTML_help
, HTML_labels
, HTML_suffixes
},
782 { "java", Cjava_help
, Cjava_entries
, Cjava_suffixes
},
783 { "lisp", Lisp_help
, Lisp_functions
, Lisp_suffixes
},
784 { "lua", Lua_help
, Lua_functions
, Lua_suffixes
},
785 { "makefile", Makefile_help
,Makefile_targets
,NULL
,Makefile_filenames
},
786 { "objc", Objc_help
, plain_C_entries
, Objc_suffixes
},
787 { "pascal", Pascal_help
, Pascal_functions
, Pascal_suffixes
},
788 { "perl",Perl_help
,Perl_functions
,Perl_suffixes
,NULL
,Perl_interpreters
},
789 { "php", PHP_help
, PHP_functions
, PHP_suffixes
},
790 { "postscript",PS_help
, PS_functions
, PS_suffixes
},
791 { "proc", no_lang_help
, plain_C_entries
, plain_C_suffixes
},
792 { "prolog", Prolog_help
, Prolog_functions
, Prolog_suffixes
},
793 { "python", Python_help
, Python_functions
, Python_suffixes
},
794 { "scheme", Scheme_help
, Scheme_functions
, Scheme_suffixes
},
795 { "tex", TeX_help
, TeX_commands
, TeX_suffixes
},
796 { "texinfo", Texinfo_help
, Texinfo_nodes
, Texinfo_suffixes
},
797 { "yacc", Yacc_help
,Yacc_entries
,Yacc_suffixes
,NULL
,NULL
,TRUE
},
798 { "auto", auto_help
}, /* default guessing scheme */
799 { "none", none_help
, just_read_file
}, /* regexp matching only */
800 { NULL
} /* end of list */
805 print_language_names ()
810 puts ("\nThese are the currently supported languages, along with the\n\
811 default file names and dot suffixes:");
812 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
814 printf (" %-*s", 10, lang
->name
);
815 if (lang
->filenames
!= NULL
)
816 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
817 printf (" %s", *name
);
818 if (lang
->suffixes
!= NULL
)
819 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
820 printf (" .%s", *ext
);
823 puts ("where `auto' means use default language for files based on file\n\
824 name suffix, and `none' means only do regexp processing on files.\n\
825 If no language is specified and no matching suffix is found,\n\
826 the first line of the file is read for a sharp-bang (#!) sequence\n\
827 followed by the name of an interpreter. If no such sequence is found,\n\
828 Fortran is tried first; if no tags are found, C is tried next.\n\
829 When parsing any C file, a \"class\" or \"template\" keyword\n\
831 puts ("Compressed files are supported using gzip and bzip2.\n\
833 For detailed help on a given language use, for example,\n\
834 etags --help --lang=ada.");
838 # define EMACS_NAME "standalone"
841 # define VERSION "version"
846 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
847 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
848 puts ("This program is distributed under the same terms as Emacs");
854 print_help (argbuffer
)
857 bool help_for_lang
= FALSE
;
859 for (; argbuffer
->arg_type
!= at_end
; argbuffer
++)
860 if (argbuffer
->arg_type
== at_language
)
864 puts (argbuffer
->lang
->help
);
865 help_for_lang
= TRUE
;
871 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
873 These are the options accepted by %s.\n", progname
, progname
);
875 puts ("You may use unambiguous abbreviations for the long option names.");
877 puts ("Long option names do not work with this executable, as it is not\n\
878 linked with GNU getopt.");
879 puts (" A - as file name means read names from stdin (one per line).\n\
880 Absolute names are stored in the output file as they are.\n\
881 Relative ones are stored relative to the output file's directory.\n");
884 puts ("-a, --append\n\
885 Append tag entries to existing tags file.");
887 puts ("--packages-only\n\
888 For Ada files, only generate tags for packages.");
891 puts ("-B, --backward-search\n\
892 Write the search commands for the tag entries using '?', the\n\
893 backward-search command instead of '/', the forward-search command.");
895 /* This option is mostly obsolete, because etags can now automatically
896 detect C++. Retained for backward compatibility and for debugging and
897 experimentation. In principle, we could want to tag as C++ even
898 before any "class" or "template" keyword.
900 Treat files whose name suffix defaults to C language as C++ files.");
903 puts ("--declarations\n\
904 In C and derived languages, create tags for function declarations,");
906 puts ("\tand create tags for extern variables if --globals is used.");
909 ("\tand create tags for extern variables unless --no-globals is used.");
912 puts ("-d, --defines\n\
913 Create tag entries for C #define constants and enum constants, too.");
915 puts ("-D, --no-defines\n\
916 Don't create tag entries for C #define constants and enum constants.\n\
917 This makes the tags file smaller.");
920 puts ("-i FILE, --include=FILE\n\
921 Include a note in tag file indicating that, when searching for\n\
922 a tag, one should also consult the tags file FILE after\n\
923 checking the current file.");
925 puts ("-l LANG, --language=LANG\n\
926 Force the following files to be considered as written in the\n\
927 named language up to the next --language=LANG option.");
931 Create tag entries for global variables in some languages.");
933 puts ("--no-globals\n\
934 Do not create tag entries for global variables in some\n\
935 languages. This makes the tags file smaller.");
937 Create tag entries for members of structures in some languages.");
940 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
941 Make a tag for each line matching a regular expression pattern\n\
942 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
943 files only. REGEXFILE is a file containing one REGEXP per line.\n\
944 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
945 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
946 puts (" If TAGNAME/ is present, the tags created are named.\n\
947 For example Tcl named tags can be created with:\n\
948 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
949 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
950 `m' means to allow multi-line matches, `s' implies `m' and\n\
951 causes dot to match any character, including newline.");
952 puts ("-R, --no-regex\n\
953 Don't create tags from regexps for the following files.");
954 #endif /* ETAGS_REGEXPS */
955 puts ("-I, --ignore-indentation\n\
956 In C and C++ do not assume that a closing brace in the first\n\
957 column is the final brace of a function or structure definition.");
958 puts ("-o FILE, --output=FILE\n\
959 Write the tags to FILE.");
960 puts ("--parse-stdin=NAME\n\
961 Read from standard input and record tags as belonging to file NAME.");
965 puts ("-t, --typedefs\n\
966 Generate tag entries for C and Ada typedefs.");
967 puts ("-T, --typedefs-and-c++\n\
968 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
969 and C++ member functions.");
973 puts ("-u, --update\n\
974 Update the tag entries for the given files, leaving tag\n\
975 entries for other files in place. Currently, this is\n\
976 implemented by deleting the existing entries for the given\n\
977 files and then rewriting the new entries at the end of the\n\
978 tags file. It is often faster to simply rebuild the entire\n\
979 tag file than to use this.");
983 puts ("-v, --vgrind\n\
984 Generates an index of items intended for human consumption,\n\
985 similar to the output of vgrind. The index is sorted, and\n\
986 gives the page number of each item.");
987 puts ("-w, --no-warn\n\
988 Suppress warning messages about entries defined in multiple\n\
990 puts ("-x, --cxref\n\
991 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
992 The output uses line numbers instead of page numbers, but\n\
993 beyond that the differences are cosmetic; try both to see\n\
997 puts ("-V, --version\n\
998 Print the version of the program.\n\
1000 Print this help message.\n\
1001 Followed by one or more `--language' options prints detailed\n\
1002 help about tag generation for the specified languages.");
1004 print_language_names ();
1007 puts ("Report bugs to bug-gnu-emacs@gnu.org");
1009 exit (EXIT_SUCCESS
);
1013 #ifdef VMS /* VMS specific functions */
1017 /* This is a BUG! ANY arbitrary limit is a BUG!
1018 Won't someone please fix this? */
1019 #define MAX_FILE_SPEC_LEN 255
1022 char body
[MAX_FILE_SPEC_LEN
+ 1];
1026 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
1027 returning in each successive call the next file name matching the input
1028 spec. The function expects that each in_spec passed
1029 to it will be processed to completion; in particular, up to and
1030 including the call following that in which the last matching name
1031 is returned, the function ignores the value of in_spec, and will
1032 only start processing a new spec with the following call.
1033 If an error occurs, on return out_spec contains the value
1034 of in_spec when the error occurred.
1036 With each successive file name returned in out_spec, the
1037 function's return value is one. When there are no more matching
1038 names the function returns zero. If on the first call no file
1039 matches in_spec, or there is any other error, -1 is returned.
1043 #include <descrip.h>
1044 #define OUTSIZE MAX_FILE_SPEC_LEN
1050 static long context
= 0;
1051 static struct dsc$descriptor_s o
;
1052 static struct dsc$descriptor_s i
;
1053 static bool pass1
= TRUE
;
1060 o
.dsc$a_pointer
= (char *) out
;
1061 o
.dsc$w_length
= (short)OUTSIZE
;
1062 i
.dsc$a_pointer
= in
;
1063 i
.dsc$w_length
= (short)strlen(in
);
1064 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
1065 i
.dsc$b_class
= DSC$K_CLASS_S
;
1066 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
1067 o
.dsc$b_class
= DSC$K_CLASS_VS
;
1069 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
1071 out
->body
[out
->curlen
] = EOS
;
1074 else if (status
== RMS$_NMF
)
1078 strcpy(out
->body
, in
);
1081 lib$
find_file_end(&context
);
1087 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
1088 name of each file specified by the provided arg expanding wildcards.
1091 gfnames (arg
, p_error
)
1095 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
1097 switch (fn_exp (&filename
, arg
))
1101 return filename
.body
;
1107 return filename
.body
;
1111 #ifndef OLD /* Newer versions of VMS do provide `system'. */
1115 error ("%s", "system() function not implemented under VMS");
1119 #define VERSION_DELIM ';'
1120 char *massage_name (s
)
1126 if (*s
== VERSION_DELIM
)
1144 unsigned int nincluded_files
;
1145 char **included_files
;
1146 argument
*argbuffer
;
1147 int current_arg
, file_count
;
1148 linebuffer filename_lb
;
1149 bool help_asked
= FALSE
;
1158 _fmode
= O_BINARY
; /* all of files are treated as binary files */
1162 nincluded_files
= 0;
1163 included_files
= xnew (argc
, char *);
1167 /* Allocate enough no matter what happens. Overkill, but each one
1169 argbuffer
= xnew (argc
, argument
);
1172 * If etags, always find typedefs and structure tags. Why not?
1173 * Also default to find macro constants, enum constants and
1178 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1183 #ifdef ETAGS_REGEXPS
1184 optstring
= "-r:Rc:";
1185 #endif /* ETAGS_REGEXPS */
1188 optstring
= concat (optstring
,
1190 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1192 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0)) != EOF
)
1196 /* If getopt returns 0, then it has already processed a
1197 long-named option. We should do nothing. */
1201 /* This means that a file name has been seen. Record it. */
1202 argbuffer
[current_arg
].arg_type
= at_filename
;
1203 argbuffer
[current_arg
].what
= optarg
;
1209 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1210 argbuffer
[current_arg
].arg_type
= at_stdin
;
1211 argbuffer
[current_arg
].what
= optarg
;
1215 fatal ("cannot parse standard input more than once", (char *)NULL
);
1216 parsing_stdin
= TRUE
;
1219 /* Common options. */
1220 case 'C': cplusplus
= TRUE
; break;
1221 case 'f': /* for compatibility with old makefiles */
1225 error ("-o option may only be given once.", (char *)NULL
);
1226 suggest_asking_for_help ();
1232 case 'S': /* for backward compatibility */
1233 ignoreindent
= TRUE
;
1237 language
*lang
= get_language_from_langname (optarg
);
1240 argbuffer
[current_arg
].lang
= lang
;
1241 argbuffer
[current_arg
].arg_type
= at_language
;
1247 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1248 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1251 argbuffer
[current_arg
].arg_type
= at_regexp
;
1252 argbuffer
[current_arg
].what
= optarg
;
1256 argbuffer
[current_arg
].arg_type
= at_regexp
;
1257 argbuffer
[current_arg
].what
= NULL
;
1269 case 'a': append_to_tagfile
= TRUE
; break;
1270 case 'D': constantypedefs
= FALSE
; break;
1271 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1273 /* Ctags options. */
1274 case 'B': searchar
= '?'; break;
1275 case 'd': constantypedefs
= TRUE
; break;
1276 case 't': typedefs
= TRUE
; break;
1277 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1278 case 'u': update
= TRUE
; break;
1279 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1280 case 'x': cxref_style
= TRUE
; break;
1281 case 'w': no_warnings
= TRUE
; break;
1283 suggest_asking_for_help ();
1287 for (; optind
< argc
; optind
++)
1289 argbuffer
[current_arg
].arg_type
= at_filename
;
1290 argbuffer
[current_arg
].what
= argv
[optind
];
1295 argbuffer
[current_arg
].arg_type
= at_end
;
1298 print_help (argbuffer
);
1301 if (nincluded_files
== 0 && file_count
== 0)
1303 error ("no input files specified.", (char *)NULL
);
1304 suggest_asking_for_help ();
1308 if (tagfile
== NULL
)
1309 tagfile
= CTAGS
? "tags" : "TAGS";
1310 cwd
= etags_getcwd (); /* the current working directory */
1311 if (cwd
[strlen (cwd
) - 1] != '/')
1314 cwd
= concat (oldcwd
, "/", "");
1317 /* Relative file names are made relative to the current directory. */
1318 if (streq (tagfile
, "-")
1319 || strneq (tagfile
, "/dev/", 5))
1322 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1324 init (); /* set up boolean "functions" */
1326 linebuffer_init (&lb
);
1327 linebuffer_init (&filename_lb
);
1328 linebuffer_init (&filebuf
);
1329 linebuffer_init (&token_name
);
1333 if (streq (tagfile
, "-"))
1337 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1338 doesn't take effect until after `stdout' is already open). */
1339 if (!isatty (fileno (stdout
)))
1340 setmode (fileno (stdout
), O_BINARY
);
1344 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1350 * Loop through files finding functions.
1352 for (i
= 0; i
< current_arg
; i
++)
1354 static language
*lang
; /* non-NULL if language is forced */
1357 switch (argbuffer
[i
].arg_type
)
1360 lang
= argbuffer
[i
].lang
;
1362 #ifdef ETAGS_REGEXPS
1364 analyse_regex (argbuffer
[i
].what
);
1369 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1373 error ("can't find file %s\n", this_file
);
1378 this_file
= massage_name (this_file
);
1381 this_file
= argbuffer
[i
].what
;
1383 /* Input file named "-" means read file names from stdin
1384 (one per line) and use them. */
1385 if (streq (this_file
, "-"))
1388 fatal ("cannot parse standard input AND read file names from it",
1390 while (readline_internal (&filename_lb
, stdin
) > 0)
1391 process_file_name (filename_lb
.buffer
, lang
);
1394 process_file_name (this_file
, lang
);
1400 this_file
= argbuffer
[i
].what
;
1401 process_file (stdin
, this_file
, lang
);
1408 #ifdef ETAGS_REGEXPS
1410 #endif /* ETAGS_REGEXPS */
1412 free (filebuf
.buffer
);
1413 free (token_name
.buffer
);
1415 if (!CTAGS
|| cxref_style
)
1417 put_entries (nodehead
); /* write the remainig tags (ETAGS) */
1418 free_tree (nodehead
);
1424 /* Output file entries that have no tags. */
1425 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1427 fprintf (tagf
, "\f\n%s,0\n", fdp
->taggedfname
);
1429 while (nincluded_files
-- > 0)
1430 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1433 if (fclose (tagf
) == EOF
)
1435 exit (EXIT_SUCCESS
);
1441 for (i
= 0; i
< current_arg
; ++i
)
1443 switch (argbuffer
[i
].arg_type
)
1449 continue; /* the for loop */
1452 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1453 tagfile
, argbuffer
[i
].what
, tagfile
);
1454 if (system (cmd
) != EXIT_SUCCESS
)
1455 fatal ("failed to execute shell command", (char *)NULL
);
1457 append_to_tagfile
= TRUE
;
1460 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1463 put_entries (nodehead
); /* write all the tags (CTAGS) */
1464 free_tree (nodehead
);
1466 if (fclose (tagf
) == EOF
)
1471 char cmd
[2*BUFSIZ
+10];
1472 sprintf (cmd
, "sort -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1473 exit (system (cmd
));
1475 return EXIT_SUCCESS
;
1480 * Return a compressor given the file name. If EXTPTR is non-zero,
1481 * return a pointer into FILE where the compressor-specific
1482 * extension begins. If no compressor is found, NULL is returned
1483 * and EXTPTR is not significant.
1484 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1487 get_compressor_from_suffix (file
, extptr
)
1492 char *slash
, *suffix
;
1494 /* This relies on FN to be after canonicalize_filename,
1495 so we don't need to consider backslashes on DOS_NT. */
1496 slash
= etags_strrchr (file
, '/');
1497 suffix
= etags_strrchr (file
, '.');
1498 if (suffix
== NULL
|| suffix
< slash
)
1503 /* Let those poor souls who live with DOS 8+3 file name limits get
1504 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1505 Only the first do loop is run if not MSDOS */
1508 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1509 if (streq (compr
->suffix
, suffix
))
1512 break; /* do it only once: not really a loop */
1515 } while (*suffix
!= '\0');
1522 * Return a language given the name.
1525 get_language_from_langname (name
)
1531 error ("empty language name", (char *)NULL
);
1534 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1535 if (streq (name
, lang
->name
))
1537 error ("unknown language \"%s\"", name
);
1545 * Return a language given the interpreter name.
1548 get_language_from_interpreter (interpreter
)
1554 if (interpreter
== NULL
)
1556 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1557 if (lang
->interpreters
!= NULL
)
1558 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1559 if (streq (*iname
, interpreter
))
1568 * Return a language given the file name.
1571 get_language_from_filename (file
, case_sensitive
)
1573 bool case_sensitive
;
1576 char **name
, **ext
, *suffix
;
1578 /* Try whole file name first. */
1579 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1580 if (lang
->filenames
!= NULL
)
1581 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1582 if ((case_sensitive
)
1583 ? streq (*name
, file
)
1584 : strcaseeq (*name
, file
))
1587 /* If not found, try suffix after last dot. */
1588 suffix
= etags_strrchr (file
, '.');
1592 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1593 if (lang
->suffixes
!= NULL
)
1594 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1595 if ((case_sensitive
)
1596 ? streq (*ext
, suffix
)
1597 : strcaseeq (*ext
, suffix
))
1604 * This routine is called on each file argument.
1607 process_file_name (file
, lang
)
1611 struct stat stat_buf
;
1615 char *compressed_name
, *uncompressed_name
;
1616 char *ext
, *real_name
;
1619 canonicalize_filename (file
);
1620 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1622 error ("skipping inclusion of %s in self.", file
);
1625 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1627 compressed_name
= NULL
;
1628 real_name
= uncompressed_name
= savestr (file
);
1632 real_name
= compressed_name
= savestr (file
);
1633 uncompressed_name
= savenstr (file
, ext
- file
);
1636 /* If the canonicalized uncompressed name
1637 has already been dealt with, skip it silently. */
1638 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1640 assert (fdp
->infname
!= NULL
);
1641 if (streq (uncompressed_name
, fdp
->infname
))
1645 if (stat (real_name
, &stat_buf
) != 0)
1647 /* Reset real_name and try with a different name. */
1649 if (compressed_name
!= NULL
) /* try with the given suffix */
1651 if (stat (uncompressed_name
, &stat_buf
) == 0)
1652 real_name
= uncompressed_name
;
1654 else /* try all possible suffixes */
1656 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1658 compressed_name
= concat (file
, ".", compr
->suffix
);
1659 if (stat (compressed_name
, &stat_buf
) != 0)
1663 char *suf
= compressed_name
+ strlen (file
);
1664 size_t suflen
= strlen (compr
->suffix
) + 1;
1665 for ( ; suf
[1]; suf
++, suflen
--)
1667 memmove (suf
, suf
+ 1, suflen
);
1668 if (stat (compressed_name
, &stat_buf
) == 0)
1670 real_name
= compressed_name
;
1674 if (real_name
!= NULL
)
1677 free (compressed_name
);
1678 compressed_name
= NULL
;
1682 real_name
= compressed_name
;
1687 if (real_name
== NULL
)
1692 } /* try with a different name */
1694 if (!S_ISREG (stat_buf
.st_mode
))
1696 error ("skipping %s: it is not a regular file.", real_name
);
1699 if (real_name
== compressed_name
)
1701 char *cmd
= concat (compr
->command
, " ", real_name
);
1702 inf
= (FILE *) popen (cmd
, "r");
1706 inf
= fopen (real_name
, "r");
1713 process_file (inf
, uncompressed_name
, lang
);
1715 if (real_name
== compressed_name
)
1716 retval
= pclose (inf
);
1718 retval
= fclose (inf
);
1723 if (compressed_name
) free (compressed_name
);
1724 if (uncompressed_name
) free (uncompressed_name
);
1731 process_file (fh
, fn
, lang
)
1736 static const fdesc emptyfdesc
;
1739 /* Create a new input file description entry. */
1740 fdp
= xnew (1, fdesc
);
1743 fdp
->infname
= savestr (fn
);
1745 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1746 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1747 if (filename_is_absolute (fn
))
1749 /* An absolute file name. Canonicalize it. */
1750 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1754 /* A file name relative to cwd. Make it relative
1755 to the directory of the tags file. */
1756 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1758 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1760 fdp
->written
= FALSE
; /* not written on tags file yet */
1763 curfdp
= fdhead
; /* the current file description */
1767 /* If not Ctags, and if this is not metasource and if it contained no #line
1768 directives, we can write the tags and free all nodes pointing to
1771 && curfdp
->usecharno
/* no #line directives in this file */
1772 && !curfdp
->lang
->metasource
)
1776 /* Look for the head of the sublist relative to this file. See add_node
1777 for the structure of the node tree. */
1779 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1780 if (np
->fdp
== curfdp
)
1783 /* If we generated tags for this file, write and delete them. */
1786 /* This is the head of the last sublist, if any. The following
1787 instructions depend on this being true. */
1788 assert (np
->left
== NULL
);
1790 assert (fdhead
== curfdp
);
1791 assert (last_node
->fdp
== curfdp
);
1792 put_entries (np
); /* write tags for file curfdp->taggedfname */
1793 free_tree (np
); /* remove the written nodes */
1795 nodehead
= NULL
; /* no nodes left */
1797 prev
->left
= NULL
; /* delete the pointer to the sublist */
1803 * This routine sets up the boolean pseudo-functions which work
1804 * by setting boolean flags dependent upon the corresponding character.
1805 * Every char which is NOT in that string is not a white char. Therefore,
1806 * all of the array "_wht" is set to FALSE, and then the elements
1807 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1808 * of a char is TRUE if it is the string "white", else FALSE.
1816 for (i
= 0; i
< CHARS
; i
++)
1817 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1818 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1819 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1820 notinname('\0') = notinname('\n');
1821 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1822 begtoken('\0') = begtoken('\n');
1823 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1824 intoken('\0') = intoken('\n');
1825 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1826 endtoken('\0') = endtoken('\n');
1830 * This routine opens the specified file and calls the function
1831 * which finds the function and type definitions.
1838 language
*lang
= curfdp
->lang
;
1839 Lang_function
*parser
= NULL
;
1841 /* If user specified a language, use it. */
1842 if (lang
!= NULL
&& lang
->function
!= NULL
)
1844 parser
= lang
->function
;
1847 /* Else try to guess the language given the file name. */
1850 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1851 if (lang
!= NULL
&& lang
->function
!= NULL
)
1853 curfdp
->lang
= lang
;
1854 parser
= lang
->function
;
1858 /* Else look for sharp-bang as the first two characters. */
1860 && readline_internal (&lb
, inf
) > 0
1862 && lb
.buffer
[0] == '#'
1863 && lb
.buffer
[1] == '!')
1867 /* Set lp to point at the first char after the last slash in the
1868 line or, if no slashes, at the first nonblank. Then set cp to
1869 the first successive blank and terminate the string. */
1870 lp
= etags_strrchr (lb
.buffer
+2, '/');
1874 lp
= skip_spaces (lb
.buffer
+ 2);
1875 cp
= skip_non_spaces (lp
);
1878 if (strlen (lp
) > 0)
1880 lang
= get_language_from_interpreter (lp
);
1881 if (lang
!= NULL
&& lang
->function
!= NULL
)
1883 curfdp
->lang
= lang
;
1884 parser
= lang
->function
;
1889 /* We rewind here, even if inf may be a pipe. We fail if the
1890 length of the first line is longer than the pipe block size,
1891 which is unlikely. */
1894 /* Else try to guess the language given the case insensitive file name. */
1897 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1898 if (lang
!= NULL
&& lang
->function
!= NULL
)
1900 curfdp
->lang
= lang
;
1901 parser
= lang
->function
;
1905 /* Else try Fortran or C. */
1908 node
*old_last_node
= last_node
;
1910 curfdp
->lang
= get_language_from_langname ("fortran");
1913 if (old_last_node
== last_node
)
1914 /* No Fortran entries found. Try C. */
1916 /* We do not tag if rewind fails.
1917 Only the file name will be recorded in the tags file. */
1919 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1925 if (!no_line_directive
1926 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1927 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1928 file, or anyway we parsed a file that is automatically generated from
1929 this one. If this is the case, the bingo.c file contained #line
1930 directives that generated tags pointing to this file. Let's delete
1931 them all before parsing this file, which is the real source. */
1933 fdesc
**fdpp
= &fdhead
;
1934 while (*fdpp
!= NULL
)
1936 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1937 /* We found one of those! We must delete both the file description
1938 and all tags referring to it. */
1940 fdesc
*badfdp
= *fdpp
;
1942 /* Delete the tags referring to badfdp->taggedfname
1943 that were obtained from badfdp->infname. */
1944 invalidate_nodes (badfdp
, &nodehead
);
1946 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1947 free_fdesc (badfdp
);
1950 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1953 assert (parser
!= NULL
);
1955 /* Generic initialisations before reading from file. */
1956 linebuffer_setlen (&filebuf
, 0); /* reset the file buffer */
1958 /* Generic initialisations before parsing file with readline. */
1959 lineno
= 0; /* reset global line number */
1960 charno
= 0; /* reset global char number */
1961 linecharno
= 0; /* reset global char number of line start */
1965 #ifdef ETAGS_REGEXPS
1966 regex_tag_multiline ();
1967 #endif /* ETAGS_REGEXPS */
1972 * Check whether an implicitly named tag should be created,
1973 * then call `pfnote'.
1974 * NAME is a string that is internally copied by this function.
1976 * TAGS format specification
1977 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1978 * The following is explained in some more detail in etc/ETAGS.EBNF.
1980 * make_tag creates tags with "implicit tag names" (unnamed tags)
1981 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
1982 * 1. NAME does not contain any of the characters in NONAM;
1983 * 2. LINESTART contains name as either a rightmost, or rightmost but
1984 * one character, substring;
1985 * 3. the character, if any, immediately before NAME in LINESTART must
1986 * be a character in NONAM;
1987 * 4. the character, if any, immediately after NAME in LINESTART must
1988 * also be a character in NONAM.
1990 * The implementation uses the notinname() macro, which recognises the
1991 * characters stored in the string `nonam'.
1992 * etags.el needs to use the same characters that are in NONAM.
1995 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1996 char *name
; /* tag name, or NULL if unnamed */
1997 int namelen
; /* tag length */
1998 bool is_func
; /* tag is a function */
1999 char *linestart
; /* start of the line where tag is */
2000 int linelen
; /* length of the line where tag is */
2001 int lno
; /* line number */
2002 long cno
; /* character number */
2004 bool named
= (name
!= NULL
&& namelen
> 0);
2006 if (!CTAGS
&& named
) /* maybe set named to false */
2007 /* Let's try to make an implicit tag name, that is, create an unnamed tag
2008 such that etags.el can guess a name from it. */
2011 register char *cp
= name
;
2013 for (i
= 0; i
< namelen
; i
++)
2014 if (notinname (*cp
++))
2016 if (i
== namelen
) /* rule #1 */
2018 cp
= linestart
+ linelen
- namelen
;
2019 if (notinname (linestart
[linelen
-1]))
2020 cp
-= 1; /* rule #4 */
2021 if (cp
>= linestart
/* rule #2 */
2023 || notinname (cp
[-1])) /* rule #3 */
2024 && strneq (name
, cp
, namelen
)) /* rule #2 */
2025 named
= FALSE
; /* use implicit tag name */
2030 name
= savenstr (name
, namelen
);
2033 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
2038 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
2039 char *name
; /* tag name, or NULL if unnamed */
2040 bool is_func
; /* tag is a function */
2041 char *linestart
; /* start of the line where tag is */
2042 int linelen
; /* length of the line where tag is */
2043 int lno
; /* line number */
2044 long cno
; /* character number */
2048 assert (name
== NULL
|| name
[0] != '\0');
2049 if (CTAGS
&& name
== NULL
)
2052 np
= xnew (1, node
);
2054 /* If ctags mode, change name "main" to M<thisfilename>. */
2055 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
2057 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
2058 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
2059 fp
= etags_strrchr (np
->name
, '.');
2060 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
2066 np
->been_warned
= FALSE
;
2068 np
->is_func
= is_func
;
2070 if (np
->fdp
->usecharno
)
2071 /* Our char numbers are 0-base, because of C language tradition?
2072 ctags compatibility? old versions compatibility? I don't know.
2073 Anyway, since emacs's are 1-base we expect etags.el to take care
2074 of the difference. If we wanted to have 1-based numbers, we would
2075 uncomment the +1 below. */
2076 np
->cno
= cno
/* + 1 */ ;
2078 np
->cno
= invalidcharno
;
2079 np
->left
= np
->right
= NULL
;
2080 if (CTAGS
&& !cxref_style
)
2082 if (strlen (linestart
) < 50)
2083 np
->regex
= concat (linestart
, "$", "");
2085 np
->regex
= savenstr (linestart
, 50);
2088 np
->regex
= savenstr (linestart
, linelen
);
2090 add_node (np
, &nodehead
);
2095 * recurse on left children, iterate on right children.
2103 register node
*node_right
= np
->right
;
2104 free_tree (np
->left
);
2105 if (np
->name
!= NULL
)
2115 * delete a file description
2119 register fdesc
*fdp
;
2121 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
2122 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
2123 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
2124 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
2125 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
2131 * Adds a node to the tree of nodes. In etags mode, sort by file
2132 * name. In ctags mode, sort by tag name. Make no attempt at
2135 * add_node is the only function allowed to add nodes, so it can
2139 add_node (np
, cur_node_p
)
2140 node
*np
, **cur_node_p
;
2143 register node
*cur_node
= *cur_node_p
;
2145 if (cur_node
== NULL
)
2155 /* For each file name, tags are in a linked sublist on the right
2156 pointer. The first tags of different files are a linked list
2157 on the left pointer. last_node points to the end of the last
2159 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
2161 /* Let's use the same sublist as the last added node. */
2162 assert (last_node
->right
== NULL
);
2163 last_node
->right
= np
;
2166 else if (cur_node
->fdp
== np
->fdp
)
2168 /* Scanning the list we found the head of a sublist which is
2169 good for us. Let's scan this sublist. */
2170 add_node (np
, &cur_node
->right
);
2173 /* The head of this sublist is not good for us. Let's try the
2175 add_node (np
, &cur_node
->left
);
2176 } /* if ETAGS mode */
2181 dif
= strcmp (np
->name
, cur_node
->name
);
2184 * If this tag name matches an existing one, then
2185 * do not add the node, but maybe print a warning.
2189 if (np
->fdp
== cur_node
->fdp
)
2193 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
2194 np
->fdp
->infname
, lineno
, np
->name
);
2195 fprintf (stderr
, "Second entry ignored\n");
2198 else if (!cur_node
->been_warned
&& !no_warnings
)
2202 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2203 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2204 cur_node
->been_warned
= TRUE
;
2209 /* Actually add the node */
2210 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2211 } /* if CTAGS mode */
2215 * invalidate_nodes ()
2216 * Scan the node tree and invalidate all nodes pointing to the
2217 * given file description (CTAGS case) or free them (ETAGS case).
2220 invalidate_nodes (badfdp
, npp
)
2231 if (np
->left
!= NULL
)
2232 invalidate_nodes (badfdp
, &np
->left
);
2233 if (np
->fdp
== badfdp
)
2235 if (np
->right
!= NULL
)
2236 invalidate_nodes (badfdp
, &np
->right
);
2240 assert (np
->fdp
!= NULL
);
2241 if (np
->fdp
== badfdp
)
2243 *npp
= np
->left
; /* detach the sublist from the list */
2244 np
->left
= NULL
; /* isolate it */
2245 free_tree (np
); /* free it */
2246 invalidate_nodes (badfdp
, npp
);
2249 invalidate_nodes (badfdp
, &np
->left
);
2254 static int total_size_of_entries
__P((node
*));
2255 static int number_len
__P((long));
2257 /* Length of a non-negative number's decimal representation. */
2263 while ((num
/= 10) > 0)
2269 * Return total number of characters that put_entries will output for
2270 * the nodes in the linked list at the right of the specified node.
2271 * This count is irrelevant with etags.el since emacs 19.34 at least,
2272 * but is still supplied for backward compatibility.
2275 total_size_of_entries (np
)
2278 register int total
= 0;
2280 for (; np
!= NULL
; np
= np
->right
)
2283 total
+= strlen (np
->regex
) + 1; /* pat\177 */
2284 if (np
->name
!= NULL
)
2285 total
+= strlen (np
->name
) + 1; /* name\001 */
2286 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2287 if (np
->cno
!= invalidcharno
) /* cno */
2288 total
+= number_len (np
->cno
);
2289 total
+= 1; /* newline */
2300 static fdesc
*fdp
= NULL
;
2305 /* Output subentries that precede this one */
2307 put_entries (np
->left
);
2309 /* Output this entry */
2318 fprintf (tagf
, "\f\n%s,%d\n",
2319 fdp
->taggedfname
, total_size_of_entries (np
));
2320 fdp
->written
= TRUE
;
2322 fputs (np
->regex
, tagf
);
2323 fputc ('\177', tagf
);
2324 if (np
->name
!= NULL
)
2326 fputs (np
->name
, tagf
);
2327 fputc ('\001', tagf
);
2329 fprintf (tagf
, "%d,", np
->lno
);
2330 if (np
->cno
!= invalidcharno
)
2331 fprintf (tagf
, "%ld", np
->cno
);
2337 if (np
->name
== NULL
)
2338 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2343 fprintf (stdout
, "%s %s %d\n",
2344 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2346 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2347 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->regex
);
2351 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2354 { /* function or #define macro with args */
2355 putc (searchar
, tagf
);
2358 for (sp
= np
->regex
; *sp
; sp
++)
2360 if (*sp
== '\\' || *sp
== searchar
)
2364 putc (searchar
, tagf
);
2367 { /* anything else; text pattern inadequate */
2368 fprintf (tagf
, "%d", np
->lno
);
2373 } /* if this node contains a valid tag */
2375 /* Output subentries that follow this one */
2376 put_entries (np
->right
);
2378 put_entries (np
->left
);
2383 #define C_EXT 0x00fff /* C extensions */
2384 #define C_PLAIN 0x00000 /* C */
2385 #define C_PLPL 0x00001 /* C++ */
2386 #define C_STAR 0x00003 /* C* */
2387 #define C_JAVA 0x00005 /* JAVA */
2388 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2389 #define YACC 0x10000 /* yacc file */
2392 * The C symbol tables.
2397 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2399 st_C_ignore
, st_C_attribute
,
2402 st_C_class
, st_C_template
,
2403 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
2406 static unsigned int hash
__P((const char *, unsigned int));
2407 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2408 static enum sym_type C_symtype
__P((char *, int, int));
2410 /* Feed stuff between (but not including) %[ and %] lines to:
2416 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2420 while, 0, st_C_ignore
2421 switch, 0, st_C_ignore
2422 return, 0, st_C_ignore
2423 __attribute__, 0, st_C_attribute
2424 @interface, 0, st_C_objprot
2425 @protocol, 0, st_C_objprot
2426 @implementation,0, st_C_objimpl
2427 @end, 0, st_C_objend
2428 import, (C_JAVA & !C_PLPL), st_C_ignore
2429 package, (C_JAVA & !C_PLPL), st_C_ignore
2430 friend, C_PLPL, st_C_ignore
2431 extends, (C_JAVA & !C_PLPL), st_C_javastruct
2432 implements, (C_JAVA & !C_PLPL), st_C_javastruct
2433 interface, (C_JAVA & !C_PLPL), st_C_struct
2434 class, 0, st_C_class
2435 namespace, C_PLPL, st_C_struct
2436 domain, C_STAR, st_C_struct
2437 union, 0, st_C_struct
2438 struct, 0, st_C_struct
2439 extern, 0, st_C_extern
2441 typedef, 0, st_C_typedef
2442 define, 0, st_C_define
2443 operator, C_PLPL, st_C_operator
2444 template, 0, st_C_template
2445 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2446 DEFUN, 0, st_C_gnumacro
2447 SYSCALL, 0, st_C_gnumacro
2448 ENTRY, 0, st_C_gnumacro
2449 PSEUDO, 0, st_C_gnumacro
2450 # These are defined inside C functions, so currently they are not met.
2451 # EXFUN used in glibc, DEFVAR_* in emacs.
2452 #EXFUN, 0, st_C_gnumacro
2453 #DEFVAR_, 0, st_C_gnumacro
2455 and replace lines between %< and %> with its output, then:
2456 - remove the #if characterset check
2457 - make in_word_set static and not inline. */
2459 /* C code produced by gperf version 3.0.1 */
2460 /* Command-line: gperf -m 5 */
2461 /* Computed positions: -k'1-2' */
2463 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2464 /* maximum key range = 31, duplicates = 0 */
2475 register const char *str
;
2476 register unsigned int len
;
2478 static unsigned char asso_values
[] =
2480 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2481 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2482 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2483 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2484 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2485 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2486 34, 34, 34, 34, 1, 34, 34, 34, 14, 14,
2487 34, 34, 34, 34, 34, 34, 34, 34, 13, 34,
2488 13, 34, 34, 12, 34, 34, 34, 34, 34, 11,
2489 34, 34, 34, 34, 34, 8, 34, 11, 34, 12,
2490 11, 0, 1, 34, 7, 0, 34, 34, 11, 9,
2491 0, 4, 0, 34, 7, 4, 14, 21, 34, 15,
2492 0, 2, 34, 34, 34, 34, 34, 34, 34, 34,
2493 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2494 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2495 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2496 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2497 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2498 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2499 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2500 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2501 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2502 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2503 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2504 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
2505 34, 34, 34, 34, 34, 34
2507 return len
+ asso_values
[(unsigned char)str
[1]] + asso_values
[(unsigned char)str
[0]];
2510 static struct C_stab_entry
*
2511 in_word_set (str
, len
)
2512 register const char *str
;
2513 register unsigned int len
;
2517 TOTAL_KEYWORDS
= 31,
2518 MIN_WORD_LENGTH
= 2,
2519 MAX_WORD_LENGTH
= 15,
2524 static struct C_stab_entry wordlist
[] =
2527 {"if", 0, st_C_ignore
},
2528 {"enum", 0, st_C_enum
},
2529 {"@end", 0, st_C_objend
},
2530 {"extern", 0, st_C_extern
},
2531 {"extends", (C_JAVA
& !C_PLPL
), st_C_javastruct
},
2532 {"for", 0, st_C_ignore
},
2533 {"interface", (C_JAVA
& !C_PLPL
), st_C_struct
},
2534 {"@protocol", 0, st_C_objprot
},
2535 {"@interface", 0, st_C_objprot
},
2536 {"operator", C_PLPL
, st_C_operator
},
2537 {"return", 0, st_C_ignore
},
2538 {"friend", C_PLPL
, st_C_ignore
},
2539 {"import", (C_JAVA
& !C_PLPL
), st_C_ignore
},
2540 {"@implementation",0, st_C_objimpl
},
2541 {"define", 0, st_C_define
},
2542 {"package", (C_JAVA
& !C_PLPL
), st_C_ignore
},
2543 {"implements", (C_JAVA
& !C_PLPL
), st_C_javastruct
},
2544 {"namespace", C_PLPL
, st_C_struct
},
2545 {"domain", C_STAR
, st_C_struct
},
2546 {"template", 0, st_C_template
},
2547 {"typedef", 0, st_C_typedef
},
2548 {"struct", 0, st_C_struct
},
2549 {"switch", 0, st_C_ignore
},
2550 {"union", 0, st_C_struct
},
2551 {"while", 0, st_C_ignore
},
2552 {"class", 0, st_C_class
},
2553 {"__attribute__", 0, st_C_attribute
},
2554 {"SYSCALL", 0, st_C_gnumacro
},
2555 {"PSEUDO", 0, st_C_gnumacro
},
2556 {"ENTRY", 0, st_C_gnumacro
},
2557 {"DEFUN", 0, st_C_gnumacro
}
2560 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2562 register int key
= hash (str
, len
);
2564 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2566 register const char *s
= wordlist
[key
].name
;
2568 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1) && s
[len
] == '\0')
2569 return &wordlist
[key
];
2576 static enum sym_type
2577 C_symtype (str
, len
, c_ext
)
2582 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2584 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2591 * Ignoring __attribute__ ((list))
2593 static bool inattribute
; /* looking at an __attribute__ construct */
2596 * C functions and variables are recognized using a simple
2597 * finite automaton. fvdef is its state variable.
2601 fvnone
, /* nothing seen */
2602 fdefunkey
, /* Emacs DEFUN keyword seen */
2603 fdefunname
, /* Emacs DEFUN name seen */
2604 foperator
, /* func: operator keyword seen (cplpl) */
2605 fvnameseen
, /* function or variable name seen */
2606 fstartlist
, /* func: just after open parenthesis */
2607 finlist
, /* func: in parameter list */
2608 flistseen
, /* func: after parameter list */
2609 fignore
, /* func: before open brace */
2610 vignore
/* var-like: ignore until ';' */
2613 static bool fvextern
; /* func or var: extern keyword seen; */
2616 * typedefs are recognized using a simple finite automaton.
2617 * typdef is its state variable.
2621 tnone
, /* nothing seen */
2622 tkeyseen
, /* typedef keyword seen */
2623 ttypeseen
, /* defined type seen */
2624 tinbody
, /* inside typedef body */
2625 tend
, /* just before typedef tag */
2626 tignore
/* junk after typedef tag */
2630 * struct-like structures (enum, struct and union) are recognized
2631 * using another simple finite automaton. `structdef' is its state
2636 snone
, /* nothing seen yet,
2637 or in struct body if bracelev > 0 */
2638 skeyseen
, /* struct-like keyword seen */
2639 stagseen
, /* struct-like tag seen */
2640 scolonseen
/* colon seen after struct-like tag */
2644 * When objdef is different from onone, objtag is the name of the class.
2646 static char *objtag
= "<uninited>";
2649 * Yet another little state machine to deal with preprocessor lines.
2653 dnone
, /* nothing seen */
2654 dsharpseen
, /* '#' seen as first char on line */
2655 ddefineseen
, /* '#' and 'define' seen */
2656 dignorerest
/* ignore rest of line */
2660 * State machine for Objective C protocols and implementations.
2661 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2665 onone
, /* nothing seen */
2666 oprotocol
, /* @interface or @protocol seen */
2667 oimplementation
, /* @implementations seen */
2668 otagseen
, /* class name seen */
2669 oparenseen
, /* parenthesis before category seen */
2670 ocatseen
, /* category name seen */
2671 oinbody
, /* in @implementation body */
2672 omethodsign
, /* in @implementation body, after +/- */
2673 omethodtag
, /* after method name */
2674 omethodcolon
, /* after method colon */
2675 omethodparm
, /* after method parameter */
2676 oignore
/* wait for @end */
2681 * Use this structure to keep info about the token read, and how it
2682 * should be tagged. Used by the make_C_tag function to build a tag.
2686 char *line
; /* string containing the token */
2687 int offset
; /* where the token starts in LINE */
2688 int length
; /* token length */
2690 The previous members can be used to pass strings around for generic
2691 purposes. The following ones specifically refer to creating tags. In this
2692 case the token contained here is the pattern that will be used to create a
2695 bool valid
; /* do not create a tag; the token should be
2696 invalidated whenever a state machine is
2697 reset prematurely */
2698 bool named
; /* create a named tag */
2699 int lineno
; /* source line number of tag */
2700 long linepos
; /* source char number of tag */
2701 } token
; /* latest token read */
2704 * Variables and functions for dealing with nested structures.
2705 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2707 static void pushclass_above
__P((int, char *, int));
2708 static void popclass_above
__P((int));
2709 static void write_classname
__P((linebuffer
*, char *qualifier
));
2712 char **cname
; /* nested class names */
2713 int *bracelev
; /* nested class brace level */
2714 int nl
; /* class nesting level (elements used) */
2715 int size
; /* length of the array */
2716 } cstack
; /* stack for nested declaration tags */
2717 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2718 #define nestlev (cstack.nl)
2719 /* After struct keyword or in struct body, not inside a nested function. */
2720 #define instruct (structdef == snone && nestlev > 0 \
2721 && bracelev == cstack.bracelev[nestlev-1] + 1)
2724 pushclass_above (bracelev
, str
, len
)
2731 popclass_above (bracelev
);
2733 if (nl
>= cstack
.size
)
2735 int size
= cstack
.size
*= 2;
2736 xrnew (cstack
.cname
, size
, char *);
2737 xrnew (cstack
.bracelev
, size
, int);
2739 assert (nl
== 0 || cstack
.bracelev
[nl
-1] < bracelev
);
2740 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2741 cstack
.bracelev
[nl
] = bracelev
;
2746 popclass_above (bracelev
)
2751 for (nl
= cstack
.nl
- 1;
2752 nl
>= 0 && cstack
.bracelev
[nl
] >= bracelev
;
2755 if (cstack
.cname
[nl
] != NULL
)
2756 free (cstack
.cname
[nl
]);
2762 write_classname (cn
, qualifier
)
2767 int qlen
= strlen (qualifier
);
2769 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2773 cn
->buffer
[0] = '\0';
2777 len
= strlen (cstack
.cname
[0]);
2778 linebuffer_setlen (cn
, len
);
2779 strcpy (cn
->buffer
, cstack
.cname
[0]);
2781 for (i
= 1; i
< cstack
.nl
; i
++)
2786 s
= cstack
.cname
[i
];
2791 linebuffer_setlen (cn
, len
);
2792 strncat (cn
->buffer
, qualifier
, qlen
);
2793 strncat (cn
->buffer
, s
, slen
);
2798 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2799 static void make_C_tag
__P((bool));
2803 * checks to see if the current token is at the start of a
2804 * function or variable, or corresponds to a typedef, or
2805 * is a struct/union/enum tag, or #define, or an enum constant.
2807 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2808 * with args. C_EXTP points to which language we are looking at.
2819 consider_token (str
, len
, c
, c_extp
, bracelev
, parlev
, is_func_or_var
)
2820 register char *str
; /* IN: token pointer */
2821 register int len
; /* IN: token length */
2822 register int c
; /* IN: first char after the token */
2823 int *c_extp
; /* IN, OUT: C extensions mask */
2824 int bracelev
; /* IN: brace level */
2825 int parlev
; /* IN: parenthesis level */
2826 bool *is_func_or_var
; /* OUT: function or variable found */
2828 /* When structdef is stagseen, scolonseen, or snone with bracelev > 0,
2829 structtype is the type of the preceding struct-like keyword, and
2830 structbracelev is the brace level where it has been seen. */
2831 static enum sym_type structtype
;
2832 static int structbracelev
;
2833 static enum sym_type toktype
;
2836 toktype
= C_symtype (str
, len
, *c_extp
);
2839 * Skip __attribute__
2841 if (toktype
== st_C_attribute
)
2848 * Advance the definedef state machine.
2853 /* We're not on a preprocessor line. */
2854 if (toktype
== st_C_gnumacro
)
2861 if (toktype
== st_C_define
)
2863 definedef
= ddefineseen
;
2867 definedef
= dignorerest
;
2872 * Make a tag for any macro, unless it is a constant
2873 * and constantypedefs is FALSE.
2875 definedef
= dignorerest
;
2876 *is_func_or_var
= (c
== '(');
2877 if (!*is_func_or_var
&& !constantypedefs
)
2884 error ("internal error: definedef value.", (char *)NULL
);
2893 if (toktype
== st_C_typedef
)
2915 if (structdef
== snone
&& fvdef
== fvnone
)
2937 * This structdef business is NOT invoked when we are ctags and the
2938 * file is plain C. This is because a struct tag may have the same
2939 * name as another tag, and this loses with ctags.
2943 case st_C_javastruct
:
2944 if (structdef
== stagseen
)
2945 structdef
= scolonseen
;
2949 if ((*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2951 && definedef
== dnone
&& structdef
== snone
2952 && typdef
== tnone
&& fvdef
== fvnone
)
2953 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2954 if (toktype
== st_C_template
)
2961 && (typdef
== tkeyseen
2962 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2964 structdef
= skeyseen
;
2965 structtype
= toktype
;
2966 structbracelev
= bracelev
;
2967 if (fvdef
== fvnameseen
)
2975 if (structdef
== skeyseen
)
2977 structdef
= stagseen
;
2981 if (typdef
!= tnone
)
2984 /* Detect Objective C constructs. */
2994 objdef
= oimplementation
;
3000 case oimplementation
:
3001 /* Save the class tag for functions or variables defined inside. */
3002 objtag
= savenstr (str
, len
);
3006 /* Save the class tag for categories. */
3007 objtag
= savenstr (str
, len
);
3009 *is_func_or_var
= TRUE
;
3013 *is_func_or_var
= TRUE
;
3021 objdef
= omethodtag
;
3022 linebuffer_setlen (&token_name
, len
);
3023 strncpy (token_name
.buffer
, str
, len
);
3024 token_name
.buffer
[len
] = '\0';
3030 objdef
= omethodparm
;
3036 objdef
= omethodtag
;
3037 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
3038 strncat (token_name
.buffer
, str
, len
);
3043 if (toktype
== st_C_objend
)
3045 /* Memory leakage here: the string pointed by objtag is
3046 never released, because many tests would be needed to
3047 avoid breaking on incorrect input code. The amount of
3048 memory leaked here is the sum of the lengths of the
3058 /* A function, variable or enum constant? */
3080 *is_func_or_var
= TRUE
;
3084 && structdef
== snone
3085 && structtype
== st_C_enum
&& bracelev
> structbracelev
)
3086 return TRUE
; /* enum constant */
3092 fvdef
= fdefunname
; /* GNU macro */
3093 *is_func_or_var
= TRUE
;
3101 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
3102 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
3113 if (len
>= 10 && strneq (str
+len
-10, "::operator", 10))
3115 if (*c_extp
& C_AUTO
) /* automatic detection of C++ */
3116 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
3118 *is_func_or_var
= TRUE
;
3121 if (bracelev
> 0 && !instruct
)
3123 fvdef
= fvnameseen
; /* function or variable */
3124 *is_func_or_var
= TRUE
;
3139 * C_entries often keeps pointers to tokens or lines which are older than
3140 * the line currently read. By keeping two line buffers, and switching
3141 * them at end of line, it is possible to use those pointers.
3149 #define current_lb_is_new (newndx == curndx)
3150 #define switch_line_buffers() (curndx = 1 - curndx)
3152 #define curlb (lbs[curndx].lb)
3153 #define newlb (lbs[newndx].lb)
3154 #define curlinepos (lbs[curndx].linepos)
3155 #define newlinepos (lbs[newndx].linepos)
3157 #define plainc ((c_ext & C_EXT) == C_PLAIN)
3158 #define cplpl (c_ext & C_PLPL)
3159 #define cjava ((c_ext & C_JAVA) == C_JAVA)
3161 #define CNL_SAVE_DEFINEDEF() \
3163 curlinepos = charno; \
3164 readline (&curlb, inf); \
3165 lp = curlb.buffer; \
3172 CNL_SAVE_DEFINEDEF(); \
3173 if (savetoken.valid) \
3175 token = savetoken; \
3176 savetoken.valid = FALSE; \
3178 definedef = dnone; \
3186 /* This function should never be called when token.valid is FALSE, but
3187 we must protect against invalid input or internal errors. */
3188 if (!DEBUG
&& !token
.valid
)
3192 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3193 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3194 else /* this case is optimised away if !DEBUG */
3195 make_tag (concat ("INVALID TOKEN:-->", token_name
.buffer
, ""),
3196 token_name
.len
+ 17, isfun
, token
.line
,
3197 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3199 token
.valid
= FALSE
;
3205 * This routine finds functions, variables, typedefs,
3206 * #define's, enum constants and struct/union/enum definitions in
3207 * C syntax and adds them to the list.
3210 C_entries (c_ext
, inf
)
3211 int c_ext
; /* extension of C */
3212 FILE *inf
; /* input file */
3214 register char c
; /* latest char read; '\0' for end of line */
3215 register char *lp
; /* pointer one beyond the character `c' */
3216 int curndx
, newndx
; /* indices for current and new lb */
3217 register int tokoff
; /* offset in line of start of current token */
3218 register int toklen
; /* length of current token */
3219 char *qualifier
; /* string used to qualify names */
3220 int qlen
; /* length of qualifier */
3221 int bracelev
; /* current brace level */
3222 int bracketlev
; /* current bracket level */
3223 int parlev
; /* current parenthesis level */
3224 int attrparlev
; /* __attribute__ parenthesis level */
3225 int templatelev
; /* current template level */
3226 int typdefbracelev
; /* bracelev where a typedef struct body begun */
3227 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3228 bool yacc_rules
; /* in the rules part of a yacc file */
3229 struct tok savetoken
; /* token saved during preprocessor handling */
3232 linebuffer_init (&lbs
[0].lb
);
3233 linebuffer_init (&lbs
[1].lb
);
3234 if (cstack
.size
== 0)
3236 cstack
.size
= (DEBUG
) ? 1 : 4;
3238 cstack
.cname
= xnew (cstack
.size
, char *);
3239 cstack
.bracelev
= xnew (cstack
.size
, int);
3242 tokoff
= toklen
= typdefbracelev
= 0; /* keep compiler quiet */
3243 curndx
= newndx
= 0;
3247 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3248 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3250 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3251 token
.valid
= savetoken
.valid
= FALSE
;
3252 bracelev
= bracketlev
= parlev
= attrparlev
= templatelev
= 0;
3254 { qualifier
= "."; qlen
= 1; }
3256 { qualifier
= "::"; qlen
= 2; }
3264 /* If we are at the end of the line, the next character is a
3265 '\0'; do not skip it, because it is what tells us
3266 to read the next line. */
3287 /* Newlines inside comments do not end macro definitions in
3289 CNL_SAVE_DEFINEDEF ();
3302 /* Newlines inside strings do not end macro definitions
3303 in traditional cpp, even though compilers don't
3304 usually accept them. */
3305 CNL_SAVE_DEFINEDEF ();
3315 /* Hmmm, something went wrong. */
3324 else if (bracketlev
> 0)
3329 if (--bracketlev
> 0)
3333 CNL_SAVE_DEFINEDEF ();
3361 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3374 else if (/* cplpl && */ *lp
== '/')
3382 if ((c_ext
& YACC
) && *lp
== '%')
3384 /* Entering or exiting rules section in yacc file. */
3386 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3387 typdef
= tnone
; structdef
= snone
;
3388 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3390 yacc_rules
= !yacc_rules
;
3396 if (definedef
== dnone
)
3399 bool cpptoken
= TRUE
;
3401 /* Look back on this line. If all blanks, or nonblanks
3402 followed by an end of comment, this is a preprocessor
3404 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3407 if (*cp
== '*' && *(cp
+1) == '/')
3416 definedef
= dsharpseen
;
3417 } /* if (definedef == dnone) */
3425 /* Consider token only if some involved conditions are satisfied. */
3426 if (typdef
!= tignore
3427 && definedef
!= dignorerest
3430 && (definedef
!= dnone
3431 || structdef
!= scolonseen
)
3438 if (c
== ':' && *lp
== ':' && begtoken (lp
[1]))
3439 /* This handles :: in the middle,
3440 but not at the beginning of an identifier.
3441 Also, space-separated :: is not recognised. */
3443 if (c_ext
& C_AUTO
) /* automatic detection of C++ */
3444 c_ext
= (c_ext
| C_PLPL
) & ~C_AUTO
;
3448 goto still_in_token
;
3452 bool funorvar
= FALSE
;
3455 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3456 &c_ext
, bracelev
, parlev
,
3459 if (fvdef
== foperator
)
3462 lp
= skip_spaces (lp
-1);
3466 && !iswhite (*lp
) && *lp
!= '(')
3469 toklen
+= lp
- oldlp
;
3471 token
.named
= FALSE
;
3473 && nestlev
> 0 && definedef
== dnone
)
3474 /* in struct body */
3476 write_classname (&token_name
, qualifier
);
3477 linebuffer_setlen (&token_name
,
3478 token_name
.len
+qlen
+toklen
);
3479 strcat (token_name
.buffer
, qualifier
);
3480 strncat (token_name
.buffer
,
3481 newlb
.buffer
+ tokoff
, toklen
);
3484 else if (objdef
== ocatseen
)
3485 /* Objective C category */
3487 int len
= strlen (objtag
) + 2 + toklen
;
3488 linebuffer_setlen (&token_name
, len
);
3489 strcpy (token_name
.buffer
, objtag
);
3490 strcat (token_name
.buffer
, "(");
3491 strncat (token_name
.buffer
,
3492 newlb
.buffer
+ tokoff
, toklen
);
3493 strcat (token_name
.buffer
, ")");
3496 else if (objdef
== omethodtag
3497 || objdef
== omethodparm
)
3498 /* Objective C method */
3502 else if (fvdef
== fdefunname
)
3503 /* GNU DEFUN and similar macros */
3505 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3509 /* Rewrite the tag so that emacs lisp DEFUNs
3510 can be found by their elisp name */
3517 linebuffer_setlen (&token_name
, len
);
3518 strncpy (token_name
.buffer
,
3519 newlb
.buffer
+ off
, len
);
3520 token_name
.buffer
[len
] = '\0';
3523 if (token_name
.buffer
[len
] == '_')
3524 token_name
.buffer
[len
] = '-';
3525 token
.named
= defun
;
3529 linebuffer_setlen (&token_name
, toklen
);
3530 strncpy (token_name
.buffer
,
3531 newlb
.buffer
+ tokoff
, toklen
);
3532 token_name
.buffer
[toklen
] = '\0';
3533 /* Name macros and members. */
3534 token
.named
= (structdef
== stagseen
3535 || typdef
== ttypeseen
3538 && definedef
== dignorerest
)
3540 && definedef
== dnone
3541 && structdef
== snone
3544 token
.lineno
= lineno
;
3545 token
.offset
= tokoff
;
3546 token
.length
= toklen
;
3547 token
.line
= newlb
.buffer
;
3548 token
.linepos
= newlinepos
;
3551 if (definedef
== dnone
3552 && (fvdef
== fvnameseen
3553 || fvdef
== foperator
3554 || structdef
== stagseen
3556 || typdef
== ttypeseen
3557 || objdef
!= onone
))
3559 if (current_lb_is_new
)
3560 switch_line_buffers ();
3562 else if (definedef
!= dnone
3563 || fvdef
== fdefunname
3565 make_C_tag (funorvar
);
3567 else /* not yacc and consider_token failed */
3569 if (inattribute
&& fvdef
== fignore
)
3571 /* We have just met __attribute__ after a
3572 function parameter list: do not tag the
3579 } /* if (endtoken (c)) */
3580 else if (intoken (c
))
3586 } /* if (midtoken) */
3587 else if (begtoken (c
))
3595 /* This prevents tagging fb in
3596 void (__attribute__((noreturn)) *fb) (void);
3597 Fixing this is not easy and not very important. */
3601 if (plainc
|| declarations
)
3603 make_C_tag (TRUE
); /* a function */
3610 if (structdef
== stagseen
&& !cjava
)
3612 popclass_above (bracelev
);
3622 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3624 tokoff
= lp
- 1 - newlb
.buffer
;
3629 } /* if (begtoken) */
3630 } /* if must look at token */
3633 /* Detect end of line, colon, comma, semicolon and various braces
3634 after having handled a token.*/
3640 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3642 make_C_tag (FALSE
); /* a yacc function */
3645 if (definedef
!= dnone
)
3651 make_C_tag (TRUE
); /* an Objective C class */
3655 objdef
= omethodcolon
;
3656 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3657 strcat (token_name
.buffer
, ":");
3662 if (structdef
== stagseen
)
3664 structdef
= scolonseen
;
3667 /* Should be useless, but may be work as a safety net. */
3668 if (cplpl
&& fvdef
== flistseen
)
3670 make_C_tag (TRUE
); /* a function */
3676 if (definedef
!= dnone
|| inattribute
)
3682 make_C_tag (FALSE
); /* a typedef */
3692 if (typdef
== tignore
|| cplpl
)
3696 if ((globals
&& bracelev
== 0 && (!fvextern
|| declarations
))
3697 || (members
&& instruct
))
3698 make_C_tag (FALSE
); /* a variable */
3701 token
.valid
= FALSE
;
3705 && (cplpl
|| !instruct
)
3706 && (typdef
== tnone
|| (typdef
!= tignore
&& instruct
)))
3708 && plainc
&& instruct
))
3709 make_C_tag (TRUE
); /* a function */
3715 && cplpl
&& structdef
== stagseen
)
3716 make_C_tag (FALSE
); /* forward declaration */
3718 token
.valid
= FALSE
;
3719 } /* switch (fvdef) */
3725 if (structdef
== stagseen
)
3729 if (definedef
!= dnone
|| inattribute
)
3735 make_C_tag (TRUE
); /* an Objective C method */
3758 && (!fvextern
|| declarations
))
3759 || (members
&& instruct
)))
3760 make_C_tag (FALSE
); /* a variable */
3763 if ((declarations
&& typdef
== tnone
&& !instruct
)
3764 || (members
&& typdef
!= tignore
&& instruct
))
3766 make_C_tag (TRUE
); /* a function */
3769 else if (!declarations
)
3771 token
.valid
= FALSE
;
3776 if (structdef
== stagseen
)
3780 if (definedef
!= dnone
|| inattribute
)
3782 if (structdef
== stagseen
)
3789 make_C_tag (FALSE
); /* a typedef */
3801 if ((members
&& bracelev
== 1)
3802 || (globals
&& bracelev
== 0
3803 && (!fvextern
|| declarations
)))
3804 make_C_tag (FALSE
); /* a variable */
3820 if (definedef
!= dnone
)
3822 if (objdef
== otagseen
&& parlev
== 0)
3823 objdef
= oparenseen
;
3827 if (typdef
== ttypeseen
3831 /* This handles constructs like:
3832 typedef void OperatorFun (int fun); */
3853 if (--attrparlev
== 0)
3854 inattribute
= FALSE
;
3857 if (definedef
!= dnone
)
3859 if (objdef
== ocatseen
&& parlev
== 1)
3861 make_C_tag (TRUE
); /* an Objective C category */
3877 || typdef
== ttypeseen
))
3880 make_C_tag (FALSE
); /* a typedef */
3883 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3887 if (definedef
!= dnone
)
3889 if (typdef
== ttypeseen
)
3891 /* Whenever typdef is set to tinbody (currently only
3892 here), typdefbracelev should be set to bracelev. */
3894 typdefbracelev
= bracelev
;
3899 make_C_tag (TRUE
); /* a function */
3908 make_C_tag (TRUE
); /* an Objective C class */
3913 make_C_tag (TRUE
); /* an Objective C method */
3917 /* Neutralize `extern "C" {' grot. */
3918 if (bracelev
== 0 && structdef
== snone
&& nestlev
== 0
3928 case skeyseen
: /* unnamed struct */
3929 pushclass_above (bracelev
, NULL
, 0);
3932 case stagseen
: /* named struct or enum */
3933 case scolonseen
: /* a class */
3934 pushclass_above (bracelev
,token
.line
+token
.offset
, token
.length
);
3936 make_C_tag (FALSE
); /* a struct or enum */
3944 if (definedef
!= dnone
)
3946 if (fvdef
== fstartlist
)
3948 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3949 token
.valid
= FALSE
;
3953 if (definedef
!= dnone
)
3955 if (!ignoreindent
&& lp
== newlb
.buffer
+ 1)
3958 token
.valid
= FALSE
;
3959 bracelev
= 0; /* reset brace level if first column */
3960 parlev
= 0; /* also reset paren level, just in case... */
3962 else if (bracelev
> 0)
3965 token
.valid
= FALSE
; /* something gone amiss, token unreliable */
3966 popclass_above (bracelev
);
3968 /* Only if typdef == tinbody is typdefbracelev significant. */
3969 if (typdef
== tinbody
&& bracelev
<= typdefbracelev
)
3971 assert (bracelev
== typdefbracelev
);
3976 if (definedef
!= dnone
)
3986 if ((members
&& bracelev
== 1)
3987 || (globals
&& bracelev
== 0 && (!fvextern
|| declarations
)))
3988 make_C_tag (FALSE
); /* a variable */
3996 && (structdef
== stagseen
|| fvdef
== fvnameseen
))
4003 if (templatelev
> 0)
4011 if (objdef
== oinbody
&& bracelev
== 0)
4013 objdef
= omethodsign
;
4018 case '#': case '~': case '&': case '%': case '/':
4019 case '|': case '^': case '!': case '.': case '?':
4020 if (definedef
!= dnone
)
4022 /* These surely cannot follow a function tag in C. */
4035 if (objdef
== otagseen
)
4037 make_C_tag (TRUE
); /* an Objective C class */
4040 /* If a macro spans multiple lines don't reset its state. */
4042 CNL_SAVE_DEFINEDEF ();
4048 } /* while not eof */
4050 free (lbs
[0].lb
.buffer
);
4051 free (lbs
[1].lb
.buffer
);
4055 * Process either a C++ file or a C file depending on the setting
4059 default_C_entries (inf
)
4062 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
4065 /* Always do plain C. */
4067 plain_C_entries (inf
)
4073 /* Always do C++. */
4075 Cplusplus_entries (inf
)
4078 C_entries (C_PLPL
, inf
);
4081 /* Always do Java. */
4086 C_entries (C_JAVA
, inf
);
4094 C_entries (C_STAR
, inf
);
4097 /* Always do Yacc. */
4102 C_entries (YACC
, inf
);
4106 /* Useful macros. */
4107 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
4108 for (; /* loop initialization */ \
4109 !feof (file_pointer) /* loop test */ \
4110 && /* instructions at start of loop */ \
4111 (readline (&line_buffer, file_pointer), \
4112 char_pointer = line_buffer.buffer, \
4115 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
4116 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
4117 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
4118 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
4121 * Read a file, but do no processing. This is used to do regexp
4122 * matching on files that have no language defined.
4125 just_read_file (inf
)
4128 register char *dummy
;
4130 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
4135 /* Fortran parsing */
4137 static void F_takeprec
__P((void));
4138 static void F_getit
__P((FILE *));
4143 dbp
= skip_spaces (dbp
);
4147 dbp
= skip_spaces (dbp
);
4148 if (strneq (dbp
, "(*)", 3))
4153 if (!ISDIGIT (*dbp
))
4155 --dbp
; /* force failure */
4160 while (ISDIGIT (*dbp
));
4169 dbp
= skip_spaces (dbp
);
4172 readline (&lb
, inf
);
4177 dbp
= skip_spaces (dbp
);
4179 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
4181 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
4183 make_tag (dbp
, cp
-dbp
, TRUE
,
4184 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4189 Fortran_functions (inf
)
4192 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4195 dbp
++; /* Ratfor escape to fortran */
4196 dbp
= skip_spaces (dbp
);
4199 switch (lowcase (*dbp
))
4202 if (nocase_tail ("integer"))
4206 if (nocase_tail ("real"))
4210 if (nocase_tail ("logical"))
4214 if (nocase_tail ("complex") || nocase_tail ("character"))
4218 if (nocase_tail ("double"))
4220 dbp
= skip_spaces (dbp
);
4223 if (nocase_tail ("precision"))
4229 dbp
= skip_spaces (dbp
);
4232 switch (lowcase (*dbp
))
4235 if (nocase_tail ("function"))
4239 if (nocase_tail ("subroutine"))
4243 if (nocase_tail ("entry"))
4247 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
4249 dbp
= skip_spaces (dbp
);
4250 if (*dbp
== '\0') /* assume un-named */
4251 make_tag ("blockdata", 9, TRUE
,
4252 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
4254 F_getit (inf
); /* look for name */
4265 * Philippe Waroquiers (1998)
4268 static void Ada_getit
__P((FILE *, char *));
4270 /* Once we are positioned after an "interesting" keyword, let's get
4271 the real tag value necessary. */
4273 Ada_getit (inf
, name_qualifier
)
4275 char *name_qualifier
;
4283 dbp
= skip_spaces (dbp
);
4285 || (dbp
[0] == '-' && dbp
[1] == '-'))
4287 readline (&lb
, inf
);
4290 switch (lowcase(*dbp
))
4293 if (nocase_tail ("body"))
4295 /* Skipping body of procedure body or package body or ....
4296 resetting qualifier to body instead of spec. */
4297 name_qualifier
= "/b";
4302 /* Skipping type of task type or protected type ... */
4303 if (nocase_tail ("type"))
4310 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4315 dbp
= skip_spaces (dbp
);
4318 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4326 name
= concat (dbp
, name_qualifier
, "");
4328 make_tag (name
, strlen (name
), TRUE
,
4329 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4341 bool inquote
= FALSE
;
4342 bool skip_till_semicolumn
= FALSE
;
4344 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4346 while (*dbp
!= '\0')
4348 /* Skip a string i.e. "abcd". */
4349 if (inquote
|| (*dbp
== '"'))
4351 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4356 continue; /* advance char */
4361 break; /* advance line */
4365 /* Skip comments. */
4366 if (dbp
[0] == '-' && dbp
[1] == '-')
4367 break; /* advance line */
4369 /* Skip character enclosed in single quote i.e. 'a'
4370 and skip single quote starting an attribute i.e. 'Image. */
4379 if (skip_till_semicolumn
)
4382 skip_till_semicolumn
= FALSE
;
4384 continue; /* advance char */
4387 /* Search for beginning of a token. */
4388 if (!begtoken (*dbp
))
4391 continue; /* advance char */
4394 /* We are at the beginning of a token. */
4395 switch (lowcase(*dbp
))
4398 if (!packages_only
&& nocase_tail ("function"))
4399 Ada_getit (inf
, "/f");
4401 break; /* from switch */
4402 continue; /* advance char */
4404 if (!packages_only
&& nocase_tail ("procedure"))
4405 Ada_getit (inf
, "/p");
4406 else if (nocase_tail ("package"))
4407 Ada_getit (inf
, "/s");
4408 else if (nocase_tail ("protected")) /* protected type */
4409 Ada_getit (inf
, "/t");
4411 break; /* from switch */
4412 continue; /* advance char */
4415 if (typedefs
&& !packages_only
&& nocase_tail ("use"))
4417 /* when tagging types, avoid tagging use type Pack.Typename;
4418 for this, we will skip everything till a ; */
4419 skip_till_semicolumn
= TRUE
;
4420 continue; /* advance char */
4424 if (!packages_only
&& nocase_tail ("task"))
4425 Ada_getit (inf
, "/k");
4426 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4428 Ada_getit (inf
, "/t");
4429 while (*dbp
!= '\0')
4433 break; /* from switch */
4434 continue; /* advance char */
4437 /* Look for the end of the token. */
4438 while (!endtoken (*dbp
))
4441 } /* advance char */
4442 } /* advance line */
4447 * Unix and microcontroller assembly tag handling
4448 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4449 * Idea by Bob Weiner, Motorola Inc. (1994)
4457 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4459 /* If first char is alphabetic or one of [_.$], test for colon
4460 following identifier. */
4461 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4463 /* Read past label. */
4465 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4467 if (*cp
== ':' || iswhite (*cp
))
4468 /* Found end of label, so copy it and add it to the table. */
4469 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4470 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4478 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4479 * Perl variable names: /^(my|local).../
4480 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4481 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4482 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4485 Perl_functions (inf
)
4488 char *package
= savestr ("main"); /* current package name */
4491 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4495 if (LOOKING_AT (cp
, "package"))
4498 get_tag (cp
, &package
);
4500 else if (LOOKING_AT (cp
, "sub"))
4505 while (!notinname (*cp
))
4508 continue; /* nothing found */
4509 if ((pos
= etags_strchr (sp
, ':')) != NULL
4510 && pos
< cp
&& pos
[1] == ':')
4511 /* The name is already qualified. */
4512 make_tag (sp
, cp
- sp
, TRUE
,
4513 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4517 char savechar
, *name
;
4521 name
= concat (package
, "::", sp
);
4523 make_tag (name
, strlen(name
), TRUE
,
4524 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4528 else if (globals
) /* only if we are tagging global vars */
4530 /* Skip a qualifier, if any. */
4531 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4532 /* After "my" or "local", but before any following paren or space. */
4533 char *varstart
= cp
;
4535 if (qual
/* should this be removed? If yes, how? */
4536 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4541 while (ISALNUM (*cp
) || *cp
== '_');
4545 /* Should be examining a variable list at this point;
4546 could insist on seeing an open parenthesis. */
4547 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4553 make_tag (varstart
, cp
- varstart
, FALSE
,
4554 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4562 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4563 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4564 * More ideas by seb bacon <seb@jamkit.com> (2002)
4567 Python_functions (inf
)
4572 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4574 cp
= skip_spaces (cp
);
4575 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4578 while (!notinname (*cp
) && *cp
!= ':')
4580 make_tag (name
, cp
- name
, TRUE
,
4581 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4590 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4591 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4592 * - /^[ \t]*define\(\"[^\"]+/
4593 * Only with --members:
4594 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4595 * Idea by Diez B. Roggisch (2001)
4601 register char *cp
, *name
;
4602 bool search_identifier
= FALSE
;
4604 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4606 cp
= skip_spaces (cp
);
4608 if (search_identifier
4611 while (!notinname (*cp
))
4613 make_tag (name
, cp
- name
, TRUE
,
4614 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4615 search_identifier
= FALSE
;
4617 else if (LOOKING_AT (cp
, "function"))
4620 cp
= skip_spaces (cp
+1);
4624 while (!notinname (*cp
))
4626 make_tag (name
, cp
- name
, TRUE
,
4627 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4630 search_identifier
= TRUE
;
4632 else if (LOOKING_AT (cp
, "class"))
4637 while (*cp
!= '\0' && !iswhite (*cp
))
4639 make_tag (name
, cp
- name
, FALSE
,
4640 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4643 search_identifier
= TRUE
;
4645 else if (strneq (cp
, "define", 6)
4646 && (cp
= skip_spaces (cp
+6))
4648 && (*cp
== '"' || *cp
== '\''))
4652 while (*cp
!= quote
&& *cp
!= '\0')
4654 make_tag (name
, cp
- name
, FALSE
,
4655 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4658 && LOOKING_AT (cp
, "var")
4662 while (!notinname(*cp
))
4664 make_tag (name
, cp
- name
, FALSE
,
4665 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4672 * Cobol tag functions
4673 * We could look for anything that could be a paragraph name.
4674 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4675 * Idea by Corny de Souza (1993)
4678 Cobol_paragraphs (inf
)
4681 register char *bp
, *ep
;
4683 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4689 /* If eoln, compiler option or comment ignore whole line. */
4690 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4693 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4696 make_tag (bp
, ep
- bp
, TRUE
,
4697 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4704 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4707 Makefile_targets (inf
)
4712 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4714 if (*bp
== '\t' || *bp
== '#')
4716 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4718 if (*bp
== ':' || (globals
&& *bp
== '='))
4719 make_tag (lb
.buffer
, bp
- lb
.buffer
, TRUE
,
4720 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4727 * Original code by Mosur K. Mohan (1989)
4729 * Locates tags for procedures & functions. Doesn't do any type- or
4730 * var-definitions. It does look for the keyword "extern" or
4731 * "forward" immediately following the procedure statement; if found,
4732 * the tag is skipped.
4735 Pascal_functions (inf
)
4738 linebuffer tline
; /* mostly copied from C_entries */
4740 int save_lineno
, namelen
, taglen
;
4743 bool /* each of these flags is TRUE iff: */
4744 incomment
, /* point is inside a comment */
4745 inquote
, /* point is inside '..' string */
4746 get_tagname
, /* point is after PROCEDURE/FUNCTION
4747 keyword, so next item = potential tag */
4748 found_tag
, /* point is after a potential tag */
4749 inparms
, /* point is within parameter-list */
4750 verify_tag
; /* point has passed the parm-list, so the
4751 next token will determine whether this
4752 is a FORWARD/EXTERN to be ignored, or
4753 whether it is a real tag */
4755 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4756 name
= NULL
; /* keep compiler quiet */
4759 linebuffer_init (&tline
);
4761 incomment
= inquote
= FALSE
;
4762 found_tag
= FALSE
; /* have a proc name; check if extern */
4763 get_tagname
= FALSE
; /* found "procedure" keyword */
4764 inparms
= FALSE
; /* found '(' after "proc" */
4765 verify_tag
= FALSE
; /* check if "extern" is ahead */
4768 while (!feof (inf
)) /* long main loop to get next char */
4771 if (c
== '\0') /* if end of line */
4773 readline (&lb
, inf
);
4777 if (!((found_tag
&& verify_tag
)
4779 c
= *dbp
++; /* only if don't need *dbp pointing
4780 to the beginning of the name of
4781 the procedure or function */
4785 if (c
== '}') /* within { } comments */
4787 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4804 inquote
= TRUE
; /* found first quote */
4806 case '{': /* found open { comment */
4810 if (*dbp
== '*') /* found open (* comment */
4815 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4818 case ')': /* end of parms list */
4823 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4830 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4832 /* Check if this is an "extern" declaration. */
4835 if (lowcase (*dbp
== 'e'))
4837 if (nocase_tail ("extern")) /* superfluous, really! */
4843 else if (lowcase (*dbp
) == 'f')
4845 if (nocase_tail ("forward")) /* check for forward reference */
4851 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4855 make_tag (name
, namelen
, TRUE
,
4856 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4860 if (get_tagname
) /* grab name of proc or fn */
4867 /* Find block name. */
4868 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4871 /* Save all values for later tagging. */
4872 linebuffer_setlen (&tline
, lb
.len
);
4873 strcpy (tline
.buffer
, lb
.buffer
);
4874 save_lineno
= lineno
;
4875 save_lcno
= linecharno
;
4876 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4878 taglen
= cp
- lb
.buffer
+ 1;
4880 dbp
= cp
; /* set dbp to e-o-token */
4881 get_tagname
= FALSE
;
4885 /* And proceed to check for "extern". */
4887 else if (!incomment
&& !inquote
&& !found_tag
)
4889 /* Check for proc/fn keywords. */
4890 switch (lowcase (c
))
4893 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4897 if (nocase_tail ("unction"))
4902 } /* while not eof */
4904 free (tline
.buffer
);
4909 * Lisp tag functions
4910 * look for (def or (DEF, quote or QUOTE
4913 static void L_getit
__P((void));
4918 if (*dbp
== '\'') /* Skip prefix quote */
4920 else if (*dbp
== '(')
4923 /* Try to skip "(quote " */
4924 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4925 /* Ok, then skip "(" before name in (defstruct (foo)) */
4926 dbp
= skip_spaces (dbp
);
4928 get_tag (dbp
, NULL
);
4932 Lisp_functions (inf
)
4935 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4940 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4942 dbp
= skip_non_spaces (dbp
);
4943 dbp
= skip_spaces (dbp
);
4948 /* Check for (foo::defmumble name-defined ... */
4951 while (!notinname (*dbp
) && *dbp
!= ':');
4956 while (*dbp
== ':');
4958 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4960 dbp
= skip_non_spaces (dbp
);
4961 dbp
= skip_spaces (dbp
);
4971 * Lua script language parsing
4972 * Original code by David A. Capello <dacap@users.sourceforge.net> (2004)
4974 * "function" and "local function" are tags if they start at column 1.
4982 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4984 if (bp
[0] != 'f' && bp
[0] != 'l')
4987 LOOKING_AT (bp
, "local"); /* skip possible "local" */
4989 if (LOOKING_AT (bp
, "function"))
4996 * Postscript tag functions
4997 * Just look for lines where the first character is '/'
4998 * Also look at "defineps" for PSWrap
5000 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
5001 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
5007 register char *bp
, *ep
;
5009 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5014 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
5017 make_tag (bp
, ep
- bp
, TRUE
,
5018 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
5020 else if (LOOKING_AT (bp
, "defineps"))
5027 * Scheme tag functions
5028 * look for (def... xyzzy
5030 * (def ... ((...(xyzzy ....
5032 * Original code by Ken Haase (1985?)
5036 Scheme_functions (inf
)
5041 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5043 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
5045 bp
= skip_non_spaces (bp
+4);
5046 /* Skip over open parens and white space */
5047 while (notinname (*bp
))
5051 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
5057 /* Find tags in TeX and LaTeX input files. */
5059 /* TEX_toktab is a table of TeX control sequences that define tags.
5060 * Each entry records one such control sequence.
5062 * Original code from who knows whom.
5064 * Stefan Monnier (2002)
5067 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
5069 /* Default set of control sequences to put into TEX_toktab.
5070 The value of environment var TEXTAGS is prepended to this. */
5071 static char *TEX_defenv
= "\
5072 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
5073 :part:appendix:entry:index:def\
5074 :newcommand:renewcommand:newenvironment:renewenvironment";
5076 static void TEX_mode
__P((FILE *));
5077 static void TEX_decode_env
__P((char *, char *));
5079 static char TEX_esc
= '\\';
5080 static char TEX_opgrp
= '{';
5081 static char TEX_clgrp
= '}';
5084 * TeX/LaTeX scanning loop.
5093 /* Select either \ or ! as escape character. */
5096 /* Initialize token table once from environment. */
5097 if (TEX_toktab
== NULL
)
5098 TEX_decode_env ("TEXTAGS", TEX_defenv
);
5100 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5102 /* Look at each TEX keyword in line. */
5105 /* Look for a TEX escape. */
5106 while (*cp
++ != TEX_esc
)
5107 if (cp
[-1] == '\0' || cp
[-1] == '%')
5110 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
5111 if (strneq (cp
, key
->buffer
, key
->len
))
5114 int namelen
, linelen
;
5117 cp
= skip_spaces (cp
+ key
->len
);
5118 if (*cp
== TEX_opgrp
)
5124 (!iswhite (*p
) && *p
!= '#' &&
5125 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
5130 if (!opgrp
|| *p
== TEX_clgrp
)
5132 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
5134 linelen
= p
- lb
.buffer
+ 1;
5136 make_tag (cp
, namelen
, TRUE
,
5137 lb
.buffer
, linelen
, lineno
, linecharno
);
5138 goto tex_next_line
; /* We only tag a line once */
5146 #define TEX_LESC '\\'
5147 #define TEX_SESC '!'
5149 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
5150 chars accordingly. */
5157 while ((c
= getc (inf
)) != EOF
)
5159 /* Skip to next line if we hit the TeX comment char. */
5163 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
5179 /* If the input file is compressed, inf is a pipe, and rewind may fail.
5180 No attempt is made to correct the situation. */
5184 /* Read environment and prepend it to the default string.
5185 Build token table. */
5187 TEX_decode_env (evarname
, defenv
)
5191 register char *env
, *p
;
5194 /* Append default string to environment. */
5195 env
= getenv (evarname
);
5201 env
= concat (oldenv
, defenv
, "");
5204 /* Allocate a token table */
5205 for (len
= 1, p
= env
; p
;)
5206 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
5208 TEX_toktab
= xnew (len
, linebuffer
);
5210 /* Unpack environment string into token table. Be careful about */
5211 /* zero-length strings (leading ':', "::" and trailing ':') */
5212 for (i
= 0; *env
!= '\0';)
5214 p
= etags_strchr (env
, ':');
5215 if (!p
) /* End of environment string. */
5216 p
= env
+ strlen (env
);
5218 { /* Only non-zero strings. */
5219 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
5220 TEX_toktab
[i
].len
= p
- env
;
5227 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
5228 TEX_toktab
[i
].len
= 0;
5235 /* Texinfo support. Dave Love, Mar. 2000. */
5241 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5242 if (LOOKING_AT (cp
, "@node"))
5245 while (*cp
!= '\0' && *cp
!= ',')
5247 make_tag (start
, cp
- start
, TRUE
,
5248 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5253 /* Similar to LOOKING_AT but does not use notinname, does not skip */
5254 #define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \
5255 (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
5256 && ((cp) += sizeof(kw)-1)) /* skip spaces */
5260 * Contents of <title>, <h1>, <h2>, <h3> are tags.
5261 * Contents of <a name=xxx> are tags with name xxx.
5263 * Francesco Potortì, 2002.
5269 bool getnext
= FALSE
; /* next text outside of HTML tags is a tag */
5270 bool skiptag
= FALSE
; /* skip to the end of the current HTML tag */
5271 bool intag
= FALSE
; /* inside an html tag, looking for ID= */
5272 bool inanchor
= FALSE
; /* when INTAG, is an anchor, look for NAME= */
5276 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5278 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5279 for (;;) /* loop on the same line */
5281 if (skiptag
) /* skip HTML tag */
5283 while (*dbp
!= '\0' && *dbp
!= '>')
5289 continue; /* look on the same line */
5291 break; /* go to next line */
5294 else if (intag
) /* look for "name=" or "id=" */
5296 while (*dbp
!= '\0' && *dbp
!= '>'
5297 && lowcase (*dbp
) != 'n' && lowcase (*dbp
) != 'i')
5300 break; /* go to next line */
5305 continue; /* look on the same line */
5307 if ((inanchor
&& LOOKING_AT_NOCASE (dbp
, "name="))
5308 || LOOKING_AT_NOCASE (dbp
, "id="))
5310 bool quoted
= (dbp
[0] == '"');
5313 for (end
= ++dbp
; *end
!= '\0' && *end
!= '"'; end
++)
5316 for (end
= dbp
; *end
!= '\0' && intoken (*end
); end
++)
5318 linebuffer_setlen (&token_name
, end
- dbp
);
5319 strncpy (token_name
.buffer
, dbp
, end
- dbp
);
5320 token_name
.buffer
[end
- dbp
] = '\0';
5323 intag
= FALSE
; /* we found what we looked for */
5324 skiptag
= TRUE
; /* skip to the end of the tag */
5325 getnext
= TRUE
; /* then grab the text */
5326 continue; /* look on the same line */
5331 else if (getnext
) /* grab next tokens and tag them */
5333 dbp
= skip_spaces (dbp
);
5335 break; /* go to next line */
5339 inanchor
= (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]));
5340 continue; /* look on the same line */
5343 for (end
= dbp
+ 1; *end
!= '\0' && *end
!= '<'; end
++)
5345 make_tag (token_name
.buffer
, token_name
.len
, TRUE
,
5346 dbp
, end
- dbp
, lineno
, linecharno
);
5347 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5349 break; /* go to next line */
5352 else /* look for an interesting HTML tag */
5354 while (*dbp
!= '\0' && *dbp
!= '<')
5357 break; /* go to next line */
5359 if (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]))
5362 continue; /* look on the same line */
5364 else if (LOOKING_AT_NOCASE (dbp
, "<title>")
5365 || LOOKING_AT_NOCASE (dbp
, "<h1>")
5366 || LOOKING_AT_NOCASE (dbp
, "<h2>")
5367 || LOOKING_AT_NOCASE (dbp
, "<h3>"))
5371 continue; /* look on the same line */
5382 * Assumes that the predicate or rule starts at column 0.
5383 * Only the first clause of a predicate or rule is added.
5384 * Original code by Sunichirou Sugou (1989)
5385 * Rewritten by Anders Lindgren (1996)
5387 static int prolog_pr
__P((char *, char *));
5388 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
5389 static int prolog_atom
__P((char *, int));
5392 Prolog_functions (inf
)
5403 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5405 if (cp
[0] == '\0') /* Empty line */
5407 else if (iswhite (cp
[0])) /* Not a predicate */
5409 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
5410 prolog_skip_comment (&lb
, inf
);
5411 else if ((len
= prolog_pr (cp
, last
)) > 0)
5413 /* Predicate or rule. Store the function name so that we
5414 only generate a tag for the first clause. */
5416 last
= xnew(len
+ 1, char);
5417 else if (len
+ 1 > allocated
)
5418 xrnew (last
, len
+ 1, char);
5419 allocated
= len
+ 1;
5420 strncpy (last
, cp
, len
);
5428 prolog_skip_comment (plb
, inf
)
5436 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
5437 if (cp
[0] == '*' && cp
[1] == '/')
5439 readline (plb
, inf
);
5445 * A predicate or rule definition is added if it matches:
5446 * <beginning of line><Prolog Atom><whitespace>(
5447 * or <beginning of line><Prolog Atom><whitespace>:-
5449 * It is added to the tags database if it doesn't match the
5450 * name of the previous clause header.
5452 * Return the size of the name of the predicate or rule, or 0 if no
5458 char *last
; /* Name of last clause. */
5463 pos
= prolog_atom (s
, 0);
5468 pos
= skip_spaces (s
+ pos
) - s
;
5471 || (s
[pos
] == '(' && (pos
+= 1))
5472 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5473 && (last
== NULL
/* save only the first clause */
5474 || len
!= strlen (last
)
5475 || !strneq (s
, last
, len
)))
5477 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5485 * Consume a Prolog atom.
5486 * Return the number of bytes consumed, or -1 if there was an error.
5488 * A prolog atom, in this context, could be one of:
5489 * - An alphanumeric sequence, starting with a lower case letter.
5490 * - A quoted arbitrary string. Single quotes can escape themselves.
5491 * Backslash quotes everything.
5494 prolog_atom (s
, pos
)
5502 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5504 /* The atom is unquoted. */
5506 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5510 return pos
- origpos
;
5512 else if (s
[pos
] == '\'')
5523 pos
++; /* A double quote */
5525 else if (s
[pos
] == '\0')
5526 /* Multiline quoted atoms are ignored. */
5528 else if (s
[pos
] == '\\')
5530 if (s
[pos
+1] == '\0')
5537 return pos
- origpos
;
5545 * Support for Erlang
5547 * Generates tags for functions, defines, and records.
5548 * Assumes that Erlang functions start at column 0.
5549 * Original code by Anders Lindgren (1996)
5551 static int erlang_func
__P((char *, char *));
5552 static void erlang_attribute
__P((char *));
5553 static int erlang_atom
__P((char *));
5556 Erlang_functions (inf
)
5567 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5569 if (cp
[0] == '\0') /* Empty line */
5571 else if (iswhite (cp
[0])) /* Not function nor attribute */
5573 else if (cp
[0] == '%') /* comment */
5575 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5577 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5579 erlang_attribute (cp
);
5582 else if ((len
= erlang_func (cp
, last
)) > 0)
5585 * Function. Store the function name so that we only
5586 * generates a tag for the first clause.
5589 last
= xnew (len
+ 1, char);
5590 else if (len
+ 1 > allocated
)
5591 xrnew (last
, len
+ 1, char);
5592 allocated
= len
+ 1;
5593 strncpy (last
, cp
, len
);
5601 * A function definition is added if it matches:
5602 * <beginning of line><Erlang Atom><whitespace>(
5604 * It is added to the tags database if it doesn't match the
5605 * name of the previous clause header.
5607 * Return the size of the name of the function, or 0 if no function
5611 erlang_func (s
, last
)
5613 char *last
; /* Name of last clause. */
5618 pos
= erlang_atom (s
);
5623 pos
= skip_spaces (s
+ pos
) - s
;
5625 /* Save only the first clause. */
5628 || len
!= (int)strlen (last
)
5629 || !strneq (s
, last
, len
)))
5631 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5640 * Handle attributes. Currently, tags are generated for defines
5643 * They are on the form:
5644 * -define(foo, bar).
5645 * -define(Foo(M, N), M+N).
5646 * -record(graph, {vtab = notable, cyclic = true}).
5649 erlang_attribute (s
)
5654 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5657 int len
= erlang_atom (skip_spaces (cp
));
5659 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5666 * Consume an Erlang atom (or variable).
5667 * Return the number of bytes consumed, or -1 if there was an error.
5675 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5677 /* The atom is unquoted. */
5680 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5682 else if (s
[pos
] == '\'')
5684 for (pos
++; s
[pos
] != '\''; pos
++)
5685 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5686 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5695 #ifdef ETAGS_REGEXPS
5697 static char *scan_separators
__P((char *));
5698 static void add_regex
__P((char *, language
*));
5699 static char *substitute
__P((char *, char *, struct re_registers
*));
5702 * Take a string like "/blah/" and turn it into "blah", verifying
5703 * that the first and last characters are the same, and handling
5704 * quoted separator characters. Actually, stops on the occurrence of
5705 * an unquoted separator. Also process \t, \n, etc. and turn into
5706 * appropriate characters. Works in place. Null terminates name string.
5707 * Returns pointer to terminating separator, or NULL for
5708 * unterminated regexps.
5711 scan_separators (name
)
5715 char *copyto
= name
;
5716 bool quoted
= FALSE
;
5718 for (++name
; *name
!= '\0'; ++name
)
5724 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5725 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5726 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5727 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5728 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5729 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5730 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5731 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5732 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5738 /* Something else is quoted, so preserve the quote. */
5746 else if (*name
== '\\')
5748 else if (*name
== sep
)
5754 name
= NULL
; /* signal unterminated regexp */
5756 /* Terminate copied string. */
5761 /* Look at the argument of --regex or --no-regex and do the right
5762 thing. Same for each line of a regexp file. */
5764 analyse_regex (regex_arg
)
5767 if (regex_arg
== NULL
)
5769 free_regexps (); /* --no-regex: remove existing regexps */
5773 /* A real --regexp option or a line in a regexp file. */
5774 switch (regex_arg
[0])
5776 /* Comments in regexp file or null arg to --regex. */
5782 /* Read a regex file. This is recursive and may result in a
5783 loop, which will stop when the file descriptors are exhausted. */
5787 linebuffer regexbuf
;
5788 char *regexfile
= regex_arg
+ 1;
5790 /* regexfile is a file containing regexps, one per line. */
5791 regexfp
= fopen (regexfile
, "r");
5792 if (regexfp
== NULL
)
5797 linebuffer_init (®exbuf
);
5798 while (readline_internal (®exbuf
, regexfp
) > 0)
5799 analyse_regex (regexbuf
.buffer
);
5800 free (regexbuf
.buffer
);
5805 /* Regexp to be used for a specific language only. */
5809 char *lang_name
= regex_arg
+ 1;
5812 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5815 error ("unterminated language name in regex: %s", regex_arg
);
5819 lang
= get_language_from_langname (lang_name
);
5822 add_regex (cp
, lang
);
5826 /* Regexp to be used for any language. */
5828 add_regex (regex_arg
, NULL
);
5833 /* Separate the regexp pattern, compile it,
5834 and care for optional name and modifiers. */
5836 add_regex (regexp_pattern
, lang
)
5837 char *regexp_pattern
;
5840 static struct re_pattern_buffer zeropattern
;
5841 char sep
, *pat
, *name
, *modifiers
;
5843 struct re_pattern_buffer
*patbuf
;
5846 force_explicit_name
= TRUE
, /* do not use implicit tag names */
5847 ignore_case
= FALSE
, /* case is significant */
5848 multi_line
= FALSE
, /* matches are done one line at a time */
5849 single_line
= FALSE
; /* dot does not match newline */
5852 if (strlen(regexp_pattern
) < 3)
5854 error ("null regexp", (char *)NULL
);
5857 sep
= regexp_pattern
[0];
5858 name
= scan_separators (regexp_pattern
);
5861 error ("%s: unterminated regexp", regexp_pattern
);
5866 error ("null name for regexp \"%s\"", regexp_pattern
);
5869 modifiers
= scan_separators (name
);
5870 if (modifiers
== NULL
) /* no terminating separator --> no name */
5876 modifiers
+= 1; /* skip separator */
5878 /* Parse regex modifiers. */
5879 for (; modifiers
[0] != '\0'; modifiers
++)
5880 switch (modifiers
[0])
5883 if (modifiers
== name
)
5884 error ("forcing explicit tag name but no name, ignoring", NULL
);
5885 force_explicit_name
= TRUE
;
5895 need_filebuf
= TRUE
;
5900 wrongmod
[0] = modifiers
[0];
5902 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
5907 patbuf
= xnew (1, struct re_pattern_buffer
);
5908 *patbuf
= zeropattern
;
5911 static char lc_trans
[CHARS
];
5913 for (i
= 0; i
< CHARS
; i
++)
5914 lc_trans
[i
] = lowcase (i
);
5915 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5919 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
5921 pat
= regexp_pattern
;
5924 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
5926 re_set_syntax (RE_SYNTAX_EMACS
);
5928 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
5933 error ("%s while compiling pattern", err
);
5938 p_head
= xnew (1, regexp
);
5939 p_head
->pattern
= savestr (regexp_pattern
);
5940 p_head
->p_next
= rp
;
5941 p_head
->lang
= lang
;
5942 p_head
->pat
= patbuf
;
5943 p_head
->name
= savestr (name
);
5944 p_head
->error_signaled
= FALSE
;
5945 p_head
->force_explicit_name
= force_explicit_name
;
5946 p_head
->ignore_case
= ignore_case
;
5947 p_head
->multi_line
= multi_line
;
5951 * Do the substitutions indicated by the regular expression and
5955 substitute (in
, out
, regs
)
5957 struct re_registers
*regs
;
5960 int size
, dig
, diglen
;
5963 size
= strlen (out
);
5965 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5966 if (out
[size
- 1] == '\\')
5967 fatal ("pattern error in \"%s\"", out
);
5968 for (t
= etags_strchr (out
, '\\');
5970 t
= etags_strchr (t
+ 2, '\\'))
5974 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5980 /* Allocate space and do the substitutions. */
5982 result
= xnew (size
+ 1, char);
5984 for (t
= result
; *out
!= '\0'; out
++)
5985 if (*out
== '\\' && ISDIGIT (*++out
))
5988 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5989 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5996 assert (t
<= result
+ size
);
5997 assert (t
- result
== (int)strlen (result
));
6002 /* Deallocate all regexps. */
6007 while (p_head
!= NULL
)
6009 rp
= p_head
->p_next
;
6010 free (p_head
->pattern
);
6011 free (p_head
->name
);
6019 * Reads the whole file as a single string from `filebuf' and looks for
6020 * multi-line regular expressions, creating tags on matches.
6021 * readline already dealt with normal regexps.
6023 * Idea by Ben Wing <ben@666.com> (2002).
6026 regex_tag_multiline ()
6028 char *buffer
= filebuf
.buffer
;
6032 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6036 if (!rp
->multi_line
)
6037 continue; /* skip normal regexps */
6039 /* Generic initialisations before parsing file from memory. */
6040 lineno
= 1; /* reset global line number */
6041 charno
= 0; /* reset global char number */
6042 linecharno
= 0; /* reset global char number of line start */
6044 /* Only use generic regexps or those for the current language. */
6045 if (rp
->lang
!= NULL
&& rp
->lang
!= curfdp
->lang
)
6048 while (match
>= 0 && match
< filebuf
.len
)
6050 match
= re_search (rp
->pat
, buffer
, filebuf
.len
, charno
,
6051 filebuf
.len
- match
, &rp
->regs
);
6056 if (!rp
->error_signaled
)
6058 error ("regexp stack overflow while matching \"%s\"",
6060 rp
->error_signaled
= TRUE
;
6067 if (match
== rp
->regs
.end
[0])
6069 if (!rp
->error_signaled
)
6071 error ("regexp matches the empty string: \"%s\"",
6073 rp
->error_signaled
= TRUE
;
6075 match
= -3; /* exit from while loop */
6079 /* Match occurred. Construct a tag. */
6080 while (charno
< rp
->regs
.end
[0])
6081 if (buffer
[charno
++] == '\n')
6082 lineno
++, linecharno
= charno
;
6084 if (name
[0] == '\0')
6086 else /* make a named tag */
6087 name
= substitute (buffer
, rp
->name
, &rp
->regs
);
6088 if (rp
->force_explicit_name
)
6089 /* Force explicit tag name, if a name is there. */
6090 pfnote (name
, TRUE
, buffer
+ linecharno
,
6091 charno
- linecharno
+ 1, lineno
, linecharno
);
6093 make_tag (name
, strlen (name
), TRUE
, buffer
+ linecharno
,
6094 charno
- linecharno
+ 1, lineno
, linecharno
);
6101 #endif /* ETAGS_REGEXPS */
6108 register int len
= 0;
6110 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
6112 if (*cp
== '\0' && !intoken (dbp
[len
]))
6121 get_tag (bp
, namepp
)
6125 register char *cp
= bp
;
6129 /* Go till you get to white space or a syntactic break */
6130 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
6132 make_tag (bp
, cp
- bp
, TRUE
,
6133 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
6137 *namepp
= savenstr (bp
, cp
- bp
);
6141 * Read a line of text from `stream' into `lbp', excluding the
6142 * newline or CR-NL, if any. Return the number of characters read from
6143 * `stream', which is the length of the line including the newline.
6145 * On DOS or Windows we do not count the CR character, if any before the
6146 * NL, in the returned length; this mirrors the behavior of Emacs on those
6147 * platforms (for text files, it translates CR-NL to NL as it reads in the
6150 * If multi-line regular expressions are requested, each line read is
6151 * appended to `filebuf'.
6154 readline_internal (lbp
, stream
)
6156 register FILE *stream
;
6158 char *buffer
= lbp
->buffer
;
6159 register char *p
= lbp
->buffer
;
6160 register char *pend
;
6163 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
6167 register int c
= getc (stream
);
6170 /* We're at the end of linebuffer: expand it. */
6172 xrnew (buffer
, lbp
->size
, char);
6173 p
+= buffer
- lbp
->buffer
;
6174 pend
= buffer
+ lbp
->size
;
6175 lbp
->buffer
= buffer
;
6185 if (p
> buffer
&& p
[-1] == '\r')
6189 /* Assume CRLF->LF translation will be performed by Emacs
6190 when loading this file, so CRs won't appear in the buffer.
6191 It would be cleaner to compensate within Emacs;
6192 however, Emacs does not know how many CRs were deleted
6193 before any given point in the file. */
6208 lbp
->len
= p
- buffer
;
6210 if (need_filebuf
/* we need filebuf for multi-line regexps */
6211 && chars_deleted
> 0) /* not at EOF */
6213 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
6215 /* Expand filebuf. */
6217 xrnew (filebuf
.buffer
, filebuf
.size
, char);
6219 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
6220 filebuf
.len
+= lbp
->len
;
6221 filebuf
.buffer
[filebuf
.len
++] = '\n';
6222 filebuf
.buffer
[filebuf
.len
] = '\0';
6225 return lbp
->len
+ chars_deleted
;
6229 * Like readline_internal, above, but in addition try to match the
6230 * input line against relevant regular expressions and manage #line
6234 readline (lbp
, stream
)
6240 linecharno
= charno
; /* update global char number of line start */
6241 result
= readline_internal (lbp
, stream
); /* read line */
6242 lineno
+= 1; /* increment global line number */
6243 charno
+= result
; /* increment global char number */
6245 /* Honour #line directives. */
6246 if (!no_line_directive
)
6248 static bool discard_until_line_directive
;
6250 /* Check whether this is a #line directive. */
6251 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
6255 if (DEBUG
) start
= 0; /* shut up the compiler */
6256 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
6258 char *endp
= lbp
->buffer
+ start
;
6261 while ((endp
= etags_strchr (endp
, '"')) != NULL
6262 && endp
[-1] == '\\')
6265 /* Ok, this is a real #line directive. Let's deal with it. */
6267 char *taggedabsname
; /* absolute name of original file */
6268 char *taggedfname
; /* name of original file as given */
6269 char *name
; /* temp var */
6271 discard_until_line_directive
= FALSE
; /* found it */
6272 name
= lbp
->buffer
+ start
;
6274 canonicalize_filename (name
); /* for DOS */
6275 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
6276 if (filename_is_absolute (name
)
6277 || filename_is_absolute (curfdp
->infname
))
6278 taggedfname
= savestr (taggedabsname
);
6280 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
6282 if (streq (curfdp
->taggedfname
, taggedfname
))
6283 /* The #line directive is only a line number change. We
6284 deal with this afterwards. */
6287 /* The tags following this #line directive should be
6288 attributed to taggedfname. In order to do this, set
6289 curfdp accordingly. */
6291 fdesc
*fdp
; /* file description pointer */
6293 /* Go look for a file description already set up for the
6294 file indicated in the #line directive. If there is
6295 one, use it from now until the next #line
6297 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6298 if (streq (fdp
->infname
, curfdp
->infname
)
6299 && streq (fdp
->taggedfname
, taggedfname
))
6300 /* If we remove the second test above (after the &&)
6301 then all entries pertaining to the same file are
6302 coalesced in the tags file. If we use it, then
6303 entries pertaining to the same file but generated
6304 from different files (via #line directives) will
6305 go into separate sections in the tags file. These
6306 alternatives look equivalent. The first one
6307 destroys some apparently useless information. */
6313 /* Else, if we already tagged the real file, skip all
6314 input lines until the next #line directive. */
6315 if (fdp
== NULL
) /* not found */
6316 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6317 if (streq (fdp
->infabsname
, taggedabsname
))
6319 discard_until_line_directive
= TRUE
;
6323 /* Else create a new file description and use that from
6324 now on, until the next #line directive. */
6325 if (fdp
== NULL
) /* not found */
6328 fdhead
= xnew (1, fdesc
);
6329 *fdhead
= *curfdp
; /* copy curr. file description */
6331 fdhead
->infname
= savestr (curfdp
->infname
);
6332 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
6333 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
6334 fdhead
->taggedfname
= taggedfname
;
6335 fdhead
->usecharno
= FALSE
;
6336 fdhead
->prop
= NULL
;
6337 fdhead
->written
= FALSE
;
6341 free (taggedabsname
);
6343 readline (lbp
, stream
);
6345 } /* if a real #line directive */
6346 } /* if #line is followed by a a number */
6347 } /* if line begins with "#line " */
6349 /* If we are here, no #line directive was found. */
6350 if (discard_until_line_directive
)
6354 /* Do a tail recursion on ourselves, thus discarding the contents
6355 of the line buffer. */
6356 readline (lbp
, stream
);
6360 discard_until_line_directive
= FALSE
;
6363 } /* if #line directives should be considered */
6365 #ifdef ETAGS_REGEXPS
6371 /* Match against relevant regexps. */
6373 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6375 /* Only use generic regexps or those for the current language.
6376 Also do not use multiline regexps, which is the job of
6377 regex_tag_multiline. */
6378 if ((rp
->lang
!= NULL
&& rp
->lang
!= fdhead
->lang
)
6382 match
= re_match (rp
->pat
, lbp
->buffer
, lbp
->len
, 0, &rp
->regs
);
6387 if (!rp
->error_signaled
)
6389 error ("regexp stack overflow while matching \"%s\"",
6391 rp
->error_signaled
= TRUE
;
6398 /* Empty string matched. */
6399 if (!rp
->error_signaled
)
6401 error ("regexp matches the empty string: \"%s\"", rp
->pattern
);
6402 rp
->error_signaled
= TRUE
;
6406 /* Match occurred. Construct a tag. */
6408 if (name
[0] == '\0')
6410 else /* make a named tag */
6411 name
= substitute (lbp
->buffer
, rp
->name
, &rp
->regs
);
6412 if (rp
->force_explicit_name
)
6413 /* Force explicit tag name, if a name is there. */
6414 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
6416 make_tag (name
, strlen (name
), TRUE
,
6417 lbp
->buffer
, match
, lineno
, linecharno
);
6422 #endif /* ETAGS_REGEXPS */
6427 * Return a pointer to a space of size strlen(cp)+1 allocated
6428 * with xnew where the string CP has been copied.
6434 return savenstr (cp
, strlen (cp
));
6438 * Return a pointer to a space of size LEN+1 allocated with xnew where
6439 * the string CP has been copied for at most the first LEN characters.
6448 dp
= xnew (len
+ 1, char);
6449 strncpy (dp
, cp
, len
);
6455 * Return the ptr in sp at which the character c last
6456 * appears; NULL if not found
6458 * Identical to POSIX strrchr, included for portability.
6461 etags_strrchr (sp
, c
)
6462 register const char *sp
;
6465 register const char *r
;
6477 * Return the ptr in sp at which the character c first
6478 * appears; NULL if not found
6480 * Identical to POSIX strchr, included for portability.
6483 etags_strchr (sp
, c
)
6484 register const char *sp
;
6496 * Compare two strings, ignoring case for alphabetic characters.
6498 * Same as BSD's strcasecmp, included for portability.
6501 etags_strcasecmp (s1
, s2
)
6502 register const char *s1
;
6503 register const char *s2
;
6506 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6507 ? lowcase (*s1
) == lowcase (*s2
)
6511 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6512 ? lowcase (*s1
) - lowcase (*s2
)
6517 * Compare two strings, ignoring case for alphabetic characters.
6518 * Stop after a given number of characters
6520 * Same as BSD's strncasecmp, included for portability.
6523 etags_strncasecmp (s1
, s2
, n
)
6524 register const char *s1
;
6525 register const char *s2
;
6528 while (*s1
!= '\0' && n
-- > 0
6529 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6530 ? lowcase (*s1
) == lowcase (*s2
)
6537 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6538 ? lowcase (*s1
) - lowcase (*s2
)
6542 /* Skip spaces, return new pointer. */
6547 while (iswhite (*cp
))
6552 /* Skip non spaces, return new pointer. */
6554 skip_non_spaces (cp
)
6557 while (*cp
!= '\0' && !iswhite (*cp
))
6562 /* Print error message and exit. */
6568 exit (EXIT_FAILURE
);
6576 exit (EXIT_FAILURE
);
6580 suggest_asking_for_help ()
6582 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6583 progname
, LONG_OPTIONS
? "--help" : "-h");
6584 exit (EXIT_FAILURE
);
6587 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6590 const char *s1
, *s2
;
6592 fprintf (stderr
, "%s: ", progname
);
6593 fprintf (stderr
, s1
, s2
);
6594 fprintf (stderr
, "\n");
6597 /* Return a newly-allocated string whose contents
6598 concatenate those of s1, s2, s3. */
6603 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6604 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6606 strcpy (result
, s1
);
6607 strcpy (result
+ len1
, s2
);
6608 strcpy (result
+ len1
+ len2
, s3
);
6609 result
[len1
+ len2
+ len3
] = '\0';
6615 /* Does the same work as the system V getcwd, but does not need to
6616 guess the buffer size in advance. */
6622 char *path
= xnew (bufsize
, char);
6624 while (getcwd (path
, bufsize
) == NULL
)
6626 if (errno
!= ERANGE
)
6630 path
= xnew (bufsize
, char);
6633 canonicalize_filename (path
);
6636 #else /* not HAVE_GETCWD */
6639 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6643 for (p
= path
; *p
!= '\0'; p
++)
6649 return strdup (path
);
6650 #else /* not MSDOS */
6654 linebuffer_init (&path
);
6655 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6656 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6661 #endif /* not MSDOS */
6662 #endif /* not HAVE_GETCWD */
6665 /* Return a newly allocated string containing the file name of FILE
6666 relative to the absolute directory DIR (which should end with a slash). */
6668 relative_filename (file
, dir
)
6671 char *fp
, *dp
, *afn
, *res
;
6674 /* Find the common root of file and dir (with a trailing slash). */
6675 afn
= absolute_filename (file
, cwd
);
6678 while (*fp
++ == *dp
++)
6680 fp
--, dp
--; /* back to the first differing char */
6682 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6685 do /* look at the equal chars until '/' */
6689 /* Build a sequence of "../" strings for the resulting relative file name. */
6691 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6693 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6696 strcat (res
, "../");
6698 /* Add the file name relative to the common root of file and dir. */
6699 strcat (res
, fp
+ 1);
6705 /* Return a newly allocated string containing the absolute file name
6706 of FILE given DIR (which should end with a slash). */
6708 absolute_filename (file
, dir
)
6711 char *slashp
, *cp
, *res
;
6713 if (filename_is_absolute (file
))
6714 res
= savestr (file
);
6716 /* We don't support non-absolute file names with a drive
6717 letter, like `d:NAME' (it's too much hassle). */
6718 else if (file
[1] == ':')
6719 fatal ("%s: relative file names with drive letters not supported", file
);
6722 res
= concat (dir
, file
, "");
6724 /* Delete the "/dirname/.." and "/." substrings. */
6725 slashp
= etags_strchr (res
, '/');
6726 while (slashp
!= NULL
&& slashp
[0] != '\0')
6728 if (slashp
[1] == '.')
6730 if (slashp
[2] == '.'
6731 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6736 while (cp
>= res
&& !filename_is_absolute (cp
));
6738 cp
= slashp
; /* the absolute name begins with "/.." */
6740 /* Under MSDOS and NT we get `d:/NAME' as absolute
6741 file name, so the luser could say `d:/../NAME'.
6742 We silently treat this as `d:/NAME'. */
6743 else if (cp
[0] != '/')
6746 strcpy (cp
, slashp
+ 3);
6750 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6752 strcpy (slashp
, slashp
+ 2);
6757 slashp
= etags_strchr (slashp
+ 1, '/');
6761 return savestr ("/");
6766 /* Return a newly allocated string containing the absolute
6767 file name of dir where FILE resides given DIR (which should
6768 end with a slash). */
6770 absolute_dirname (file
, dir
)
6776 canonicalize_filename (file
);
6777 slashp
= etags_strrchr (file
, '/');
6779 return savestr (dir
);
6782 res
= absolute_filename (file
, dir
);
6788 /* Whether the argument string is an absolute file name. The argument
6789 string must have been canonicalized with canonicalize_filename. */
6791 filename_is_absolute (fn
)
6794 return (fn
[0] == '/'
6796 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6801 /* Translate backslashes into slashes. Works in place. */
6803 canonicalize_filename (fn
)
6807 /* Canonicalize drive letter case. */
6808 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6809 fn
[0] = upcase (fn
[0]);
6810 /* Convert backslashes to slashes. */
6811 for (; *fn
!= '\0'; fn
++)
6816 fn
= NULL
; /* shut up the compiler */
6821 /* Initialize a linebuffer for use */
6823 linebuffer_init (lbp
)
6826 lbp
->size
= (DEBUG
) ? 3 : 200;
6827 lbp
->buffer
= xnew (lbp
->size
, char);
6828 lbp
->buffer
[0] = '\0';
6832 /* Set the minimum size of a string contained in a linebuffer. */
6834 linebuffer_setlen (lbp
, toksize
)
6838 while (lbp
->size
<= toksize
)
6841 xrnew (lbp
->buffer
, lbp
->size
, char);
6846 /* Like malloc but get fatal error if memory is exhausted. */
6851 PTR result
= (PTR
) malloc (size
);
6853 fatal ("virtual memory exhausted", (char *)NULL
);
6858 xrealloc (ptr
, size
)
6862 PTR result
= (PTR
) realloc (ptr
, size
);
6864 fatal ("virtual memory exhausted", (char *)NULL
);
6870 * c-indentation-style: gnu
6871 * indent-tabs-mode: t
6874 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")
6878 /* arch-tag: 8a9b748d-390c-4922-99db-2eeefa921051
6879 (do not change this comment) */
6881 /* etags.c ends here */