1 /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*-
3 Copyright (C) 1984 The Regents of the University of California
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the
14 3. Neither the name of the University nor the names of its
15 contributors may be used to endorse or promote products derived
16 from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 Copyright (C) 1984, 1987, 1988, 1989, 1993, 1994, 1995, 1998, 1999,
32 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
33 Free Software Foundation, Inc.
35 This file is not considered part of GNU Emacs.
37 This program is free software; you can redistribute it and/or modify
38 it under the terms of the GNU General Public License as published by
39 the Free Software Foundation; either version 3, or (at your option)
42 This program is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
47 You should have received a copy of the GNU General Public License
48 along with this program; see the file COPYING. If not, write to the
49 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
50 Boston, MA 02110-1301, USA. */
53 /* NB To comply with the above BSD license, copyright information is
54 reproduced in etc/ETAGS.README. That file should be updated when the
57 To the best of our knowledge, this code was originally based on the
58 ctags.c distributed with BSD4.2, which was copyrighted by the
59 University of California, as described above. */
64 * 1983 Ctags originally by Ken Arnold.
65 * 1984 Fortran added by Jim Kleckner.
66 * 1984 Ed Pelegri-Llopart added C typedefs.
67 * 1985 Emacs TAGS format by Richard Stallman.
68 * 1989 Sam Kendall added C++.
69 * 1992 Joseph B. Wells improved C and C++ parsing.
70 * 1993 Francesco Potortì reorganised C and C++.
71 * 1994 Line-by-line regexp tags by Tom Tromey.
72 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
73 * 2002 #line directives by Francesco Potortì.
75 * Francesco Potortì <pot@gnu.org> has maintained and improved it since 1993.
79 * If you want to add support for a new language, start by looking at the LUA
80 * language, which is the simplest. Alternatively, consider shipping a
81 * configuration file containing regexp definitions for etags.
84 char pot_etags_version
[] = "@(#) pot revision number is 17.38";
94 # define NDEBUG /* disable assert */
99 /* On some systems, Emacs defines static as nothing for the sake
100 of unexec. We don't want that here since we don't use unexec. */
102 # ifndef PTR /* for XEmacs */
105 # ifndef __P /* for XEmacs */
106 # define __P(args) args
108 #else /* no config.h */
109 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
110 # define __P(args) args /* use prototypes */
111 # define PTR void * /* for generic pointers */
112 # else /* not standard C */
113 # define __P(args) () /* no prototypes */
114 # define const /* remove const for old compilers' sake */
115 # define PTR long * /* don't use void* */
117 #endif /* !HAVE_CONFIG_H */
120 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
123 /* WIN32_NATIVE is for XEmacs.
124 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
129 #endif /* WIN32_NATIVE */
135 # include <sys/param.h>
137 # ifndef HAVE_CONFIG_H
139 # include <sys/config.h>
151 # define MAXPATHLEN _MAX_PATH
157 # endif /* undef HAVE_GETCWD */
158 #else /* not WINDOWSNT */
162 # else /* no standard C headers */
163 extern char *getenv
__P((const char *));
164 extern char *strcpy
__P((char *, const char *));
165 extern char *strncpy
__P((char *, const char *, unsigned long));
166 extern char *strcat
__P((char *, const char *));
167 extern char *strncat
__P((char *, const char *, unsigned long));
168 extern int strcmp
__P((const char *, const char *));
169 extern int strncmp
__P((const char *, const char *, unsigned long));
170 extern int system
__P((const char *));
171 extern unsigned long strlen
__P((const char *));
172 extern void *malloc
__P((unsigned long));
173 extern void *realloc
__P((void *, unsigned long));
174 extern void exit
__P((int));
175 extern void free
__P((void *));
176 extern void *memmove
__P((void *, const void *, unsigned long));
178 # define EXIT_SUCCESS 1
179 # define EXIT_FAILURE 0
181 # define EXIT_SUCCESS 0
182 # define EXIT_FAILURE 1
185 #endif /* !WINDOWSNT */
190 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
191 extern char *getcwd (char *buf
, size_t size
);
193 #endif /* HAVE_UNISTD_H */
201 #include <sys/types.h>
202 #include <sys/stat.h>
206 # undef assert /* some systems have a buggy assert.h */
207 # define assert(x) ((void) 0)
210 #if !defined (S_ISREG) && defined (S_IFREG)
211 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
214 #ifdef NO_LONG_OPTIONS /* define this if you don't have GNU getopt */
215 # define NO_LONG_OPTIONS TRUE
216 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
218 extern int optind
, opterr
;
220 # define NO_LONG_OPTIONS FALSE
222 #endif /* NO_LONG_OPTIONS */
224 #ifndef HAVE_CONFIG_H /* this is a standalone compilation */
225 # ifdef __CYGWIN__ /* compiling on Cygwin */
227 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
228 If you want regular expression support
, you should
delete this notice
and
229 arrange to use the GNU regex
.h
and regex
.c
.
234 /* Define CTAGS to make the program "ctags" compatible with the usual one.
235 Leave it undefined to make the program "etags", which makes emacs-style
236 tag tables and tags typedefs, #defines and struct/union/enum by default. */
244 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
245 #define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
246 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
247 #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
249 #define CHARS 256 /* 2^sizeof(char) */
250 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
251 #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
252 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
253 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
254 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
255 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
257 #define ISALNUM(c) isalnum (CHAR(c))
258 #define ISALPHA(c) isalpha (CHAR(c))
259 #define ISDIGIT(c) isdigit (CHAR(c))
260 #define ISLOWER(c) islower (CHAR(c))
262 #define lowcase(c) tolower (CHAR(c))
263 #define upcase(c) toupper (CHAR(c))
267 * xnew, xrnew -- allocate, reallocate storage
269 * SYNOPSIS: Type *xnew (int n, Type);
270 * void xrnew (OldPointer, int n, Type);
273 # include "chkmalloc.h"
274 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
275 (n) * sizeof (Type)))
276 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
277 (char *) (op), (n) * sizeof (Type)))
279 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
280 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
281 (char *) (op), (n) * sizeof (Type)))
286 typedef void Lang_function
__P((FILE *));
290 char *suffix
; /* file name suffix for this compressor */
291 char *command
; /* takes one arg and decompresses to stdout */
296 char *name
; /* language name */
297 char *help
; /* detailed help for the language */
298 Lang_function
*function
; /* parse function */
299 char **suffixes
; /* name suffixes of this language's files */
300 char **filenames
; /* names of this language's files */
301 char **interpreters
; /* interpreters for this language */
302 bool metasource
; /* source used to generate other sources */
307 struct fdesc
*next
; /* for the linked list */
308 char *infname
; /* uncompressed input file name */
309 char *infabsname
; /* absolute uncompressed input file name */
310 char *infabsdir
; /* absolute dir of input file */
311 char *taggedfname
; /* file name to write in tagfile */
312 language
*lang
; /* language of file */
313 char *prop
; /* file properties to write in tagfile */
314 bool usecharno
; /* etags tags shall contain char number */
315 bool written
; /* entry written in the tags file */
318 typedef struct node_st
319 { /* sorting structure */
320 struct node_st
*left
, *right
; /* left and right sons */
321 fdesc
*fdp
; /* description of file to whom tag belongs */
322 char *name
; /* tag name */
323 char *regex
; /* search regexp */
324 bool valid
; /* write this tag on the tag file */
325 bool is_func
; /* function tag: use regexp in CTAGS mode */
326 bool been_warned
; /* warning already given for duplicated tag */
327 int lno
; /* line number tag is on */
328 long cno
; /* character number line starts on */
332 * A `linebuffer' is a structure which holds a line of text.
333 * `readline_internal' reads a line from a stream into a linebuffer
334 * and works regardless of the length of the line.
335 * SIZE is the size of BUFFER, LEN is the length of the string in
336 * BUFFER after readline reads it.
345 /* Used to support mixing of --lang and file names. */
349 at_language
, /* a language specification */
350 at_regexp
, /* a regular expression */
351 at_filename
, /* a file name */
352 at_stdin
, /* read from stdin here */
353 at_end
/* stop parsing the list */
354 } arg_type
; /* argument type */
355 language
*lang
; /* language associated with the argument */
356 char *what
; /* the argument itself */
359 /* Structure defining a regular expression. */
360 typedef struct regexp
362 struct regexp
*p_next
; /* pointer to next in list */
363 language
*lang
; /* if set, use only for this language */
364 char *pattern
; /* the regexp pattern */
365 char *name
; /* tag name */
366 struct re_pattern_buffer
*pat
; /* the compiled pattern */
367 struct re_registers regs
; /* re registers */
368 bool error_signaled
; /* already signaled for this regexp */
369 bool force_explicit_name
; /* do not allow implict tag name */
370 bool ignore_case
; /* ignore case when matching */
371 bool multi_line
; /* do a multi-line match on the whole file */
375 /* Many compilers barf on this:
376 Lang_function Ada_funcs;
377 so let's write it this way */
378 static void Ada_funcs
__P((FILE *));
379 static void Asm_labels
__P((FILE *));
380 static void C_entries
__P((int c_ext
, FILE *));
381 static void default_C_entries
__P((FILE *));
382 static void plain_C_entries
__P((FILE *));
383 static void Cjava_entries
__P((FILE *));
384 static void Cobol_paragraphs
__P((FILE *));
385 static void Cplusplus_entries
__P((FILE *));
386 static void Cstar_entries
__P((FILE *));
387 static void Erlang_functions
__P((FILE *));
388 static void Forth_words
__P((FILE *));
389 static void Fortran_functions
__P((FILE *));
390 static void HTML_labels
__P((FILE *));
391 static void Lisp_functions
__P((FILE *));
392 static void Lua_functions
__P((FILE *));
393 static void Makefile_targets
__P((FILE *));
394 static void Pascal_functions
__P((FILE *));
395 static void Perl_functions
__P((FILE *));
396 static void PHP_functions
__P((FILE *));
397 static void PS_functions
__P((FILE *));
398 static void Prolog_functions
__P((FILE *));
399 static void Python_functions
__P((FILE *));
400 static void Scheme_functions
__P((FILE *));
401 static void TeX_commands
__P((FILE *));
402 static void Texinfo_nodes
__P((FILE *));
403 static void Yacc_entries
__P((FILE *));
404 static void just_read_file
__P((FILE *));
406 static void print_language_names
__P((void));
407 static void print_version
__P((void));
408 static void print_help
__P((argument
*));
409 int main
__P((int, char **));
411 static compressor
*get_compressor_from_suffix
__P((char *, char **));
412 static language
*get_language_from_langname
__P((const char *));
413 static language
*get_language_from_interpreter
__P((char *));
414 static language
*get_language_from_filename
__P((char *, bool));
415 static void readline
__P((linebuffer
*, FILE *));
416 static long readline_internal
__P((linebuffer
*, FILE *));
417 static bool nocase_tail
__P((char *));
418 static void get_tag
__P((char *, char **));
420 static void analyse_regex
__P((char *));
421 static void free_regexps
__P((void));
422 static void regex_tag_multiline
__P((void));
423 static void error
__P((const char *, const char *));
424 static void suggest_asking_for_help
__P((void));
425 void fatal
__P((char *, char *));
426 static void pfatal
__P((char *));
427 static void add_node
__P((node
*, node
**));
429 static void init
__P((void));
430 static void process_file_name
__P((char *, language
*));
431 static void process_file
__P((FILE *, char *, language
*));
432 static void find_entries
__P((FILE *));
433 static void free_tree
__P((node
*));
434 static void free_fdesc
__P((fdesc
*));
435 static void pfnote
__P((char *, bool, char *, int, int, long));
436 static void make_tag
__P((char *, int, bool, char *, int, int, long));
437 static void invalidate_nodes
__P((fdesc
*, node
**));
438 static void put_entries
__P((node
*));
440 static char *concat
__P((char *, char *, char *));
441 static char *skip_spaces
__P((char *));
442 static char *skip_non_spaces
__P((char *));
443 static char *savenstr
__P((char *, int));
444 static char *savestr
__P((char *));
445 static char *etags_strchr
__P((const char *, int));
446 static char *etags_strrchr
__P((const char *, int));
447 static int etags_strcasecmp
__P((const char *, const char *));
448 static int etags_strncasecmp
__P((const char *, const char *, int));
449 static char *etags_getcwd
__P((void));
450 static char *relative_filename
__P((char *, char *));
451 static char *absolute_filename
__P((char *, char *));
452 static char *absolute_dirname
__P((char *, char *));
453 static bool filename_is_absolute
__P((char *f
));
454 static void canonicalize_filename
__P((char *));
455 static void linebuffer_init
__P((linebuffer
*));
456 static void linebuffer_setlen
__P((linebuffer
*, int));
457 static PTR xmalloc
__P((unsigned int));
458 static PTR xrealloc
__P((char *, unsigned int));
461 static char searchar
= '/'; /* use /.../ searches */
463 static char *tagfile
; /* output file */
464 static char *progname
; /* name this program was invoked with */
465 static char *cwd
; /* current working directory */
466 static char *tagfiledir
; /* directory of tagfile */
467 static FILE *tagf
; /* ioptr for tags file */
469 static fdesc
*fdhead
; /* head of file description list */
470 static fdesc
*curfdp
; /* current file description */
471 static int lineno
; /* line number of current line */
472 static long charno
; /* current character number */
473 static long linecharno
; /* charno of start of current line */
474 static char *dbp
; /* pointer to start of current tag */
476 static const int invalidcharno
= -1;
478 static node
*nodehead
; /* the head of the binary tree of tags */
479 static node
*last_node
; /* the last node created */
481 static linebuffer lb
; /* the current line */
482 static linebuffer filebuf
; /* a buffer containing the whole file */
483 static linebuffer token_name
; /* a buffer containing a tag name */
485 /* boolean "functions" (see init) */
486 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
489 *white
= " \f\t\n\r\v",
491 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
492 /* token ending chars */
493 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
494 /* token starting chars */
495 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
496 /* valid in-token chars */
497 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
499 static bool append_to_tagfile
; /* -a: append to tags */
500 /* The next five default to TRUE in C and derived languages. */
501 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
502 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
503 /* 0 struct/enum/union decls, and C++ */
504 /* member functions. */
505 static bool constantypedefs
; /* -d: create tags for C #define, enum */
506 /* constants and variables. */
507 /* -D: opposite of -d. Default under ctags. */
508 static bool globals
; /* create tags for global variables */
509 static bool members
; /* create tags for C member variables */
510 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
511 static bool no_line_directive
; /* ignore #line directives (undocumented) */
512 static bool no_duplicates
; /* no duplicate tags for ctags (undocumented) */
513 static bool update
; /* -u: update tags */
514 static bool vgrind_style
; /* -v: create vgrind style index output */
515 static bool no_warnings
; /* -w: suppress warnings (undocumented) */
516 static bool cxref_style
; /* -x: create cxref style output */
517 static bool cplusplus
; /* .[hc] means C++, not C (undocumented) */
518 static bool ignoreindent
; /* -I: ignore indentation in C */
519 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
521 /* STDIN is defined in LynxOS system headers */
526 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
527 static bool parsing_stdin
; /* --parse-stdin used */
529 static regexp
*p_head
; /* list of all regexps */
530 static bool need_filebuf
; /* some regexes are multi-line */
532 static struct option longopts
[] =
534 { "append", no_argument
, NULL
, 'a' },
535 { "packages-only", no_argument
, &packages_only
, TRUE
},
536 { "c++", no_argument
, NULL
, 'C' },
537 { "declarations", no_argument
, &declarations
, TRUE
},
538 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
539 { "no-duplicates", no_argument
, &no_duplicates
, TRUE
},
540 { "help", no_argument
, NULL
, 'h' },
541 { "help", no_argument
, NULL
, 'H' },
542 { "ignore-indentation", no_argument
, NULL
, 'I' },
543 { "language", required_argument
, NULL
, 'l' },
544 { "members", no_argument
, &members
, TRUE
},
545 { "no-members", no_argument
, &members
, FALSE
},
546 { "output", required_argument
, NULL
, 'o' },
547 { "regex", required_argument
, NULL
, 'r' },
548 { "no-regex", no_argument
, NULL
, 'R' },
549 { "ignore-case-regex", required_argument
, NULL
, 'c' },
550 { "parse-stdin", required_argument
, NULL
, STDIN
},
551 { "version", no_argument
, NULL
, 'V' },
553 #if CTAGS /* Ctags options */
554 { "backward-search", no_argument
, NULL
, 'B' },
555 { "cxref", no_argument
, NULL
, 'x' },
556 { "defines", no_argument
, NULL
, 'd' },
557 { "globals", no_argument
, &globals
, TRUE
},
558 { "typedefs", no_argument
, NULL
, 't' },
559 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
560 { "update", no_argument
, NULL
, 'u' },
561 { "vgrind", no_argument
, NULL
, 'v' },
562 { "no-warn", no_argument
, NULL
, 'w' },
564 #else /* Etags options */
565 { "no-defines", no_argument
, NULL
, 'D' },
566 { "no-globals", no_argument
, &globals
, FALSE
},
567 { "include", required_argument
, NULL
, 'i' },
572 static compressor compressors
[] =
574 { "z", "gzip -d -c"},
575 { "Z", "gzip -d -c"},
576 { "gz", "gzip -d -c"},
577 { "GZ", "gzip -d -c"},
578 { "bz2", "bzip2 -d -c" },
587 static char *Ada_suffixes
[] =
588 { "ads", "adb", "ada", NULL
};
589 static char Ada_help
[] =
590 "In Ada code, functions, procedures, packages, tasks and types are\n\
591 tags. Use the `--packages-only' option to create tags for\n\
593 Ada tag names have suffixes indicating the type of entity:\n\
594 Entity type: Qualifier:\n\
595 ------------ ----------\n\
602 Thus, `M-x find-tag <RET> bidule/b <RET>' will go directly to the\n\
603 body of the package `bidule', while `M-x find-tag <RET> bidule <RET>'\n\
604 will just search for any tag `bidule'.";
607 static char *Asm_suffixes
[] =
608 { "a", /* Unix assembler */
609 "asm", /* Microcontroller assembly */
610 "def", /* BSO/Tasking definition includes */
611 "inc", /* Microcontroller include files */
612 "ins", /* Microcontroller include files */
613 "s", "sa", /* Unix assembler */
614 "S", /* cpp-processed Unix assembler */
615 "src", /* BSO/Tasking C compiler output */
618 static char Asm_help
[] =
619 "In assembler code, labels appearing at the beginning of a line,\n\
620 followed by a colon, are tags.";
623 /* Note that .c and .h can be considered C++, if the --c++ flag was
624 given, or if the `class' or `template' keywords are met inside the file.
625 That is why default_C_entries is called for these. */
626 static char *default_C_suffixes
[] =
628 #if CTAGS /* C help for Ctags */
629 static char default_C_help
[] =
630 "In C code, any C function is a tag. Use -t to tag typedefs.\n\
631 Use -T to tag definitions of `struct', `union' and `enum'.\n\
632 Use -d to tag `#define' macro definitions and `enum' constants.\n\
633 Use --globals to tag global variables.\n\
634 You can tag function declarations and external variables by\n\
635 using `--declarations', and struct members by using `--members'.";
636 #else /* C help for Etags */
637 static char default_C_help
[] =
638 "In C code, any C function or typedef is a tag, and so are\n\
639 definitions of `struct', `union' and `enum'. `#define' macro\n\
640 definitions and `enum' constants are tags unless you specify\n\
641 `--no-defines'. Global variables are tags unless you specify\n\
642 `--no-globals' and so are struct members unless you specify\n\
643 `--no-members'. Use of `--no-globals', `--no-defines' and\n\
644 `--no-members' can make the tags table file much smaller.\n\
645 You can tag function declarations and external variables by\n\
646 using `--declarations'.";
647 #endif /* C help for Ctags and Etags */
649 static char *Cplusplus_suffixes
[] =
650 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
651 "M", /* Objective C++ */
652 "pdb", /* Postscript with C syntax */
654 static char Cplusplus_help
[] =
655 "In C++ code, all the tag constructs of C code are tagged. (Use\n\
656 --help --lang=c --lang=c++ for full help.)\n\
657 In addition to C tags, member functions are also recognized. Member\n\
658 variables are recognized unless you use the `--no-members' option.\n\
659 Tags for variables and functions in classes are named `CLASS::VARIABLE'\n\
660 and `CLASS::FUNCTION'. `operator' definitions have tag names like\n\
663 static char *Cjava_suffixes
[] =
665 static char Cjava_help
[] =
666 "In Java code, all the tags constructs of C and C++ code are\n\
667 tagged. (Use --help --lang=c --lang=c++ --lang=java for full help.)";
670 static char *Cobol_suffixes
[] =
671 { "COB", "cob", NULL
};
672 static char Cobol_help
[] =
673 "In Cobol code, tags are paragraph names; that is, any word\n\
674 starting in column 8 and followed by a period.";
676 static char *Cstar_suffixes
[] =
677 { "cs", "hs", NULL
};
679 static char *Erlang_suffixes
[] =
680 { "erl", "hrl", NULL
};
681 static char Erlang_help
[] =
682 "In Erlang code, the tags are the functions, records and macros\n\
683 defined in the file.";
685 char *Forth_suffixes
[] =
686 { "fth", "tok", NULL
};
687 static char Forth_help
[] =
688 "In Forth code, tags are words defined by `:',\n\
689 constant, code, create, defer, value, variable, buffer:, field.";
691 static char *Fortran_suffixes
[] =
692 { "F", "f", "f90", "for", NULL
};
693 static char Fortran_help
[] =
694 "In Fortran code, functions, subroutines and block data are tags.";
696 static char *HTML_suffixes
[] =
697 { "htm", "html", "shtml", NULL
};
698 static char HTML_help
[] =
699 "In HTML input files, the tags are the `title' and the `h1', `h2',\n\
700 `h3' headers. Also, tags are `name=' in anchors and all\n\
701 occurrences of `id='.";
703 static char *Lisp_suffixes
[] =
704 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
705 static char Lisp_help
[] =
706 "In Lisp code, any function defined with `defun', any variable\n\
707 defined with `defvar' or `defconst', and in general the first\n\
708 argument of any expression that starts with `(def' in column zero\n\
711 static char *Lua_suffixes
[] =
712 { "lua", "LUA", NULL
};
713 static char Lua_help
[] =
714 "In Lua scripts, all functions are tags.";
716 static char *Makefile_filenames
[] =
717 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
718 static char Makefile_help
[] =
719 "In makefiles, targets are tags; additionally, variables are tags\n\
720 unless you specify `--no-globals'.";
722 static char *Objc_suffixes
[] =
723 { "lm", /* Objective lex file */
724 "m", /* Objective C file */
726 static char Objc_help
[] =
727 "In Objective C code, tags include Objective C definitions for classes,\n\
728 class categories, methods and protocols. Tags for variables and\n\
729 functions in classes are named `CLASS::VARIABLE' and `CLASS::FUNCTION'.\n\
730 (Use --help --lang=c --lang=objc --lang=java for full help.)";
732 static char *Pascal_suffixes
[] =
733 { "p", "pas", NULL
};
734 static char Pascal_help
[] =
735 "In Pascal code, the tags are the functions and procedures defined\n\
737 /* " // this is for working around an Emacs highlighting bug... */
739 static char *Perl_suffixes
[] =
740 { "pl", "pm", NULL
};
741 static char *Perl_interpreters
[] =
742 { "perl", "@PERL@", NULL
};
743 static char Perl_help
[] =
744 "In Perl code, the tags are the packages, subroutines and variables\n\
745 defined by the `package', `sub', `my' and `local' keywords. Use\n\
746 `--globals' if you want to tag global variables. Tags for\n\
747 subroutines are named `PACKAGE::SUB'. The name for subroutines\n\
748 defined in the default package is `main::SUB'.";
750 static char *PHP_suffixes
[] =
751 { "php", "php3", "php4", NULL
};
752 static char PHP_help
[] =
753 "In PHP code, tags are functions, classes and defines. Unless you use\n\
754 the `--no-members' option, vars are tags too.";
756 static char *plain_C_suffixes
[] =
757 { "pc", /* Pro*C file */
760 static char *PS_suffixes
[] =
761 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
762 static char PS_help
[] =
763 "In PostScript code, the tags are the functions.";
765 static char *Prolog_suffixes
[] =
767 static char Prolog_help
[] =
768 "In Prolog code, tags are predicates and rules at the beginning of\n\
771 static char *Python_suffixes
[] =
773 static char Python_help
[] =
774 "In Python code, `def' or `class' at the beginning of a line\n\
777 /* Can't do the `SCM' or `scm' prefix with a version number. */
778 static char *Scheme_suffixes
[] =
779 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
780 static char Scheme_help
[] =
781 "In Scheme code, tags include anything defined with `def' or with a\n\
782 construct whose name starts with `def'. They also include\n\
783 variables set with `set!' at top level in the file.";
785 static char *TeX_suffixes
[] =
786 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
787 static char TeX_help
[] =
788 "In LaTeX text, the argument of any of the commands `\\chapter',\n\
789 `\\section', `\\subsection', `\\subsubsection', `\\eqno', `\\label',\n\
790 `\\ref', `\\cite', `\\bibitem', `\\part', `\\appendix', `\\entry',\n\
791 `\\index', `\\def', `\\newcommand', `\\renewcommand',\n\
792 `\\newenvironment' or `\\renewenvironment' is a tag.\n\
794 Other commands can be specified by setting the environment variable\n\
795 `TEXTAGS' to a colon-separated list like, for example,\n\
796 TEXTAGS=\"mycommand:myothercommand\".";
799 static char *Texinfo_suffixes
[] =
800 { "texi", "texinfo", "txi", NULL
};
801 static char Texinfo_help
[] =
802 "for texinfo files, lines starting with @node are tagged.";
804 static char *Yacc_suffixes
[] =
805 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
806 static char Yacc_help
[] =
807 "In Bison or Yacc input files, each rule defines as a tag the\n\
808 nonterminal it constructs. The portions of the file that contain\n\
809 C code are parsed as C code (use --help --lang=c --lang=yacc\n\
812 static char auto_help
[] =
813 "`auto' is not a real language, it indicates to use\n\
814 a default language for files base on file name suffix and file contents.";
816 static char none_help
[] =
817 "`none' is not a real language, it indicates to only do\n\
818 regexp processing on files.";
820 static char no_lang_help
[] =
821 "No detailed help available for this language.";
825 * Table of languages.
827 * It is ok for a given function to be listed under more than one
828 * name. I just didn't.
831 static language lang_names
[] =
833 { "ada", Ada_help
, Ada_funcs
, Ada_suffixes
},
834 { "asm", Asm_help
, Asm_labels
, Asm_suffixes
},
835 { "c", default_C_help
, default_C_entries
, default_C_suffixes
},
836 { "c++", Cplusplus_help
, Cplusplus_entries
, Cplusplus_suffixes
},
837 { "c*", no_lang_help
, Cstar_entries
, Cstar_suffixes
},
838 { "cobol", Cobol_help
, Cobol_paragraphs
, Cobol_suffixes
},
839 { "erlang", Erlang_help
, Erlang_functions
, Erlang_suffixes
},
840 { "forth", Forth_help
, Forth_words
, Forth_suffixes
},
841 { "fortran", Fortran_help
, Fortran_functions
, Fortran_suffixes
},
842 { "html", HTML_help
, HTML_labels
, HTML_suffixes
},
843 { "java", Cjava_help
, Cjava_entries
, Cjava_suffixes
},
844 { "lisp", Lisp_help
, Lisp_functions
, Lisp_suffixes
},
845 { "lua", Lua_help
, Lua_functions
, Lua_suffixes
},
846 { "makefile", Makefile_help
,Makefile_targets
,NULL
,Makefile_filenames
},
847 { "objc", Objc_help
, plain_C_entries
, Objc_suffixes
},
848 { "pascal", Pascal_help
, Pascal_functions
, Pascal_suffixes
},
849 { "perl",Perl_help
,Perl_functions
,Perl_suffixes
,NULL
,Perl_interpreters
},
850 { "php", PHP_help
, PHP_functions
, PHP_suffixes
},
851 { "postscript",PS_help
, PS_functions
, PS_suffixes
},
852 { "proc", no_lang_help
, plain_C_entries
, plain_C_suffixes
},
853 { "prolog", Prolog_help
, Prolog_functions
, Prolog_suffixes
},
854 { "python", Python_help
, Python_functions
, Python_suffixes
},
855 { "scheme", Scheme_help
, Scheme_functions
, Scheme_suffixes
},
856 { "tex", TeX_help
, TeX_commands
, TeX_suffixes
},
857 { "texinfo", Texinfo_help
, Texinfo_nodes
, Texinfo_suffixes
},
858 { "yacc", Yacc_help
,Yacc_entries
,Yacc_suffixes
,NULL
,NULL
,TRUE
},
859 { "auto", auto_help
}, /* default guessing scheme */
860 { "none", none_help
, just_read_file
}, /* regexp matching only */
861 { NULL
} /* end of list */
866 print_language_names ()
871 puts ("\nThese are the currently supported languages, along with the\n\
872 default file names and dot suffixes:");
873 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
875 printf (" %-*s", 10, lang
->name
);
876 if (lang
->filenames
!= NULL
)
877 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
878 printf (" %s", *name
);
879 if (lang
->suffixes
!= NULL
)
880 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
881 printf (" .%s", *ext
);
884 puts ("where `auto' means use default language for files based on file\n\
885 name suffix, and `none' means only do regexp processing on files.\n\
886 If no language is specified and no matching suffix is found,\n\
887 the first line of the file is read for a sharp-bang (#!) sequence\n\
888 followed by the name of an interpreter. If no such sequence is found,\n\
889 Fortran is tried first; if no tags are found, C is tried next.\n\
890 When parsing any C file, a \"class\" or \"template\" keyword\n\
892 puts ("Compressed files are supported using gzip and bzip2.\n\
894 For detailed help on a given language use, for example,\n\
895 etags --help --lang=ada.");
899 # define EMACS_NAME "standalone"
902 # define VERSION "17.38"
907 /* Makes it easier to update automatically. */
908 char emacs_copyright
[] = "Copyright (C) 2008 Free Software Foundation, Inc.";
910 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
911 puts (emacs_copyright
);
912 puts ("This program is distributed under the terms in ETAGS.README");
917 #ifndef PRINT_UNDOCUMENTED_OPTIONS_HELP
918 # define PRINT_UNDOCUMENTED_OPTIONS_HELP FALSE
922 print_help (argbuffer
)
925 bool help_for_lang
= FALSE
;
927 for (; argbuffer
->arg_type
!= at_end
; argbuffer
++)
928 if (argbuffer
->arg_type
== at_language
)
932 puts (argbuffer
->lang
->help
);
933 help_for_lang
= TRUE
;
939 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
941 These are the options accepted by %s.\n", progname
, progname
);
943 puts ("WARNING: long option names do not work with this executable,\n\
944 as it is not linked with GNU getopt.");
946 puts ("You may use unambiguous abbreviations for the long option names.");
947 puts (" A - as file name means read names from stdin (one per line).\n\
948 Absolute names are stored in the output file as they are.\n\
949 Relative ones are stored relative to the output file's directory.\n");
951 puts ("-a, --append\n\
952 Append tag entries to existing tags file.");
954 puts ("--packages-only\n\
955 For Ada files, only generate tags for packages.");
958 puts ("-B, --backward-search\n\
959 Write the search commands for the tag entries using '?', the\n\
960 backward-search command instead of '/', the forward-search command.");
962 /* This option is mostly obsolete, because etags can now automatically
963 detect C++. Retained for backward compatibility and for debugging and
964 experimentation. In principle, we could want to tag as C++ even
965 before any "class" or "template" keyword.
967 Treat files whose name suffix defaults to C language as C++ files.");
970 puts ("--declarations\n\
971 In C and derived languages, create tags for function declarations,");
973 puts ("\tand create tags for extern variables if --globals is used.");
976 ("\tand create tags for extern variables unless --no-globals is used.");
979 puts ("-d, --defines\n\
980 Create tag entries for C #define constants and enum constants, too.");
982 puts ("-D, --no-defines\n\
983 Don't create tag entries for C #define constants and enum constants.\n\
984 This makes the tags file smaller.");
987 puts ("-i FILE, --include=FILE\n\
988 Include a note in tag file indicating that, when searching for\n\
989 a tag, one should also consult the tags file FILE after\n\
990 checking the current file.");
992 puts ("-l LANG, --language=LANG\n\
993 Force the following files to be considered as written in the\n\
994 named language up to the next --language=LANG option.");
998 Create tag entries for global variables in some languages.");
1000 puts ("--no-globals\n\
1001 Do not create tag entries for global variables in some\n\
1002 languages. This makes the tags file smaller.");
1004 if (PRINT_UNDOCUMENTED_OPTIONS_HELP
)
1005 puts ("--no-line-directive\n\
1006 Ignore #line preprocessor directives in C and derived languages.");
1010 Create tag entries for members of structures in some languages.");
1012 puts ("--no-members\n\
1013 Do not create tag entries for members of structures\n\
1014 in some languages.");
1016 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
1017 Make a tag for each line matching a regular expression pattern\n\
1018 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
1019 files only. REGEXFILE is a file containing one REGEXP per line.\n\
1020 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
1021 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
1022 puts (" If TAGNAME/ is present, the tags created are named.\n\
1023 For example Tcl named tags can be created with:\n\
1024 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
1025 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
1026 `m' means to allow multi-line matches, `s' implies `m' and\n\
1027 causes dot to match any character, including newline.");
1029 puts ("-R, --no-regex\n\
1030 Don't create tags from regexps for the following files.");
1032 puts ("-I, --ignore-indentation\n\
1033 In C and C++ do not assume that a closing brace in the first\n\
1034 column is the final brace of a function or structure definition.");
1036 puts ("-o FILE, --output=FILE\n\
1037 Write the tags to FILE.");
1039 puts ("--parse-stdin=NAME\n\
1040 Read from standard input and record tags as belonging to file NAME.");
1044 puts ("-t, --typedefs\n\
1045 Generate tag entries for C and Ada typedefs.");
1046 puts ("-T, --typedefs-and-c++\n\
1047 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
1048 and C++ member functions.");
1052 puts ("-u, --update\n\
1053 Update the tag entries for the given files, leaving tag\n\
1054 entries for other files in place. Currently, this is\n\
1055 implemented by deleting the existing entries for the given\n\
1056 files and then rewriting the new entries at the end of the\n\
1057 tags file. It is often faster to simply rebuild the entire\n\
1058 tag file than to use this.");
1062 puts ("-v, --vgrind\n\
1063 Print on the standard output an index of items intended for\n\
1064 human consumption, similar to the output of vgrind. The index\n\
1065 is sorted, and gives the page number of each item.");
1067 if (PRINT_UNDOCUMENTED_OPTIONS_HELP
)
1068 puts ("-w, --no-duplicates\n\
1069 Do not create duplicate tag entries, for compatibility with\n\
1070 traditional ctags.");
1072 if (PRINT_UNDOCUMENTED_OPTIONS_HELP
)
1073 puts ("-w, --no-warn\n\
1074 Suppress warning messages about duplicate tag entries.");
1076 puts ("-x, --cxref\n\
1077 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
1078 The output uses line numbers instead of page numbers, but\n\
1079 beyond that the differences are cosmetic; try both to see\n\
1083 puts ("-V, --version\n\
1084 Print the version of the program.\n\
1086 Print this help message.\n\
1087 Followed by one or more `--language' options prints detailed\n\
1088 help about tag generation for the specified languages.");
1090 print_language_names ();
1093 puts ("Report bugs to bug-gnu-emacs@gnu.org");
1095 exit (EXIT_SUCCESS
);
1099 #ifdef VMS /* VMS specific functions */
1103 /* This is a BUG! ANY arbitrary limit is a BUG!
1104 Won't someone please fix this? */
1105 #define MAX_FILE_SPEC_LEN 255
1108 char body
[MAX_FILE_SPEC_LEN
+ 1];
1112 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
1113 returning in each successive call the next file name matching the input
1114 spec. The function expects that each in_spec passed
1115 to it will be processed to completion; in particular, up to and
1116 including the call following that in which the last matching name
1117 is returned, the function ignores the value of in_spec, and will
1118 only start processing a new spec with the following call.
1119 If an error occurs, on return out_spec contains the value
1120 of in_spec when the error occurred.
1122 With each successive file name returned in out_spec, the
1123 function's return value is one. When there are no more matching
1124 names the function returns zero. If on the first call no file
1125 matches in_spec, or there is any other error, -1 is returned.
1129 #include <descrip.h>
1130 #define OUTSIZE MAX_FILE_SPEC_LEN
1136 static long context
= 0;
1137 static struct dsc$descriptor_s o
;
1138 static struct dsc$descriptor_s i
;
1139 static bool pass1
= TRUE
;
1146 o
.dsc$a_pointer
= (char *) out
;
1147 o
.dsc$w_length
= (short)OUTSIZE
;
1148 i
.dsc$a_pointer
= in
;
1149 i
.dsc$w_length
= (short)strlen(in
);
1150 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
1151 i
.dsc$b_class
= DSC$K_CLASS_S
;
1152 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
1153 o
.dsc$b_class
= DSC$K_CLASS_VS
;
1155 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
1157 out
->body
[out
->curlen
] = EOS
;
1160 else if (status
== RMS$_NMF
)
1164 strcpy(out
->body
, in
);
1167 lib$
find_file_end(&context
);
1173 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
1174 name of each file specified by the provided arg expanding wildcards.
1177 gfnames (arg
, p_error
)
1181 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
1183 switch (fn_exp (&filename
, arg
))
1187 return filename
.body
;
1193 return filename
.body
;
1197 #ifndef OLD /* Newer versions of VMS do provide `system'. */
1201 error ("%s", "system() function not implemented under VMS");
1205 #define VERSION_DELIM ';'
1206 char *massage_name (s
)
1212 if (*s
== VERSION_DELIM
)
1230 unsigned int nincluded_files
;
1231 char **included_files
;
1232 argument
*argbuffer
;
1233 int current_arg
, file_count
;
1234 linebuffer filename_lb
;
1235 bool help_asked
= FALSE
;
1244 _fmode
= O_BINARY
; /* all of files are treated as binary files */
1248 nincluded_files
= 0;
1249 included_files
= xnew (argc
, char *);
1253 /* Allocate enough no matter what happens. Overkill, but each one
1255 argbuffer
= xnew (argc
, argument
);
1258 * Always find typedefs and structure tags.
1259 * Also default to find macro constants, enum constants, struct
1260 * members and global variables. Do it for both etags and ctags.
1262 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1263 globals
= members
= TRUE
;
1265 /* When the optstring begins with a '-' getopt_long does not rearrange the
1266 non-options arguments to be at the end, but leaves them alone. */
1267 optstring
= concat (NO_LONG_OPTIONS
? "" : "-",
1268 "ac:Cf:Il:o:r:RSVhH",
1269 (CTAGS
) ? "BxdtTuvw" : "Di:");
1271 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, NULL
)) != EOF
)
1275 /* If getopt returns 0, then it has already processed a
1276 long-named option. We should do nothing. */
1280 /* This means that a file name has been seen. Record it. */
1281 argbuffer
[current_arg
].arg_type
= at_filename
;
1282 argbuffer
[current_arg
].what
= optarg
;
1288 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1289 argbuffer
[current_arg
].arg_type
= at_stdin
;
1290 argbuffer
[current_arg
].what
= optarg
;
1294 fatal ("cannot parse standard input more than once", (char *)NULL
);
1295 parsing_stdin
= TRUE
;
1298 /* Common options. */
1299 case 'a': append_to_tagfile
= TRUE
; break;
1300 case 'C': cplusplus
= TRUE
; break;
1301 case 'f': /* for compatibility with old makefiles */
1305 error ("-o option may only be given once.", (char *)NULL
);
1306 suggest_asking_for_help ();
1312 case 'S': /* for backward compatibility */
1313 ignoreindent
= TRUE
;
1317 language
*lang
= get_language_from_langname (optarg
);
1320 argbuffer
[current_arg
].lang
= lang
;
1321 argbuffer
[current_arg
].arg_type
= at_language
;
1327 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1328 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1331 argbuffer
[current_arg
].arg_type
= at_regexp
;
1332 argbuffer
[current_arg
].what
= optarg
;
1336 argbuffer
[current_arg
].arg_type
= at_regexp
;
1337 argbuffer
[current_arg
].what
= NULL
;
1349 case 'D': constantypedefs
= FALSE
; break;
1350 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1352 /* Ctags options. */
1353 case 'B': searchar
= '?'; break;
1354 case 'd': constantypedefs
= TRUE
; break;
1355 case 't': typedefs
= TRUE
; break;
1356 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1357 case 'u': update
= TRUE
; break;
1358 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1359 case 'x': cxref_style
= TRUE
; break;
1360 case 'w': no_warnings
= TRUE
; break;
1362 suggest_asking_for_help ();
1366 /* No more options. Store the rest of arguments. */
1367 for (; optind
< argc
; optind
++)
1369 argbuffer
[current_arg
].arg_type
= at_filename
;
1370 argbuffer
[current_arg
].what
= argv
[optind
];
1375 argbuffer
[current_arg
].arg_type
= at_end
;
1378 print_help (argbuffer
);
1381 if (nincluded_files
== 0 && file_count
== 0)
1383 error ("no input files specified.", (char *)NULL
);
1384 suggest_asking_for_help ();
1388 if (tagfile
== NULL
)
1389 tagfile
= CTAGS
? "tags" : "TAGS";
1390 cwd
= etags_getcwd (); /* the current working directory */
1391 if (cwd
[strlen (cwd
) - 1] != '/')
1394 cwd
= concat (oldcwd
, "/", "");
1397 /* Relative file names are made relative to the current directory. */
1398 if (streq (tagfile
, "-")
1399 || strneq (tagfile
, "/dev/", 5))
1402 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1404 init (); /* set up boolean "functions" */
1406 linebuffer_init (&lb
);
1407 linebuffer_init (&filename_lb
);
1408 linebuffer_init (&filebuf
);
1409 linebuffer_init (&token_name
);
1413 if (streq (tagfile
, "-"))
1417 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1418 doesn't take effect until after `stdout' is already open). */
1419 if (!isatty (fileno (stdout
)))
1420 setmode (fileno (stdout
), O_BINARY
);
1424 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1430 * Loop through files finding functions.
1432 for (i
= 0; i
< current_arg
; i
++)
1434 static language
*lang
; /* non-NULL if language is forced */
1437 switch (argbuffer
[i
].arg_type
)
1440 lang
= argbuffer
[i
].lang
;
1443 analyse_regex (argbuffer
[i
].what
);
1447 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1451 error ("can't find file %s\n", this_file
);
1456 this_file
= massage_name (this_file
);
1459 this_file
= argbuffer
[i
].what
;
1461 /* Input file named "-" means read file names from stdin
1462 (one per line) and use them. */
1463 if (streq (this_file
, "-"))
1466 fatal ("cannot parse standard input AND read file names from it",
1468 while (readline_internal (&filename_lb
, stdin
) > 0)
1469 process_file_name (filename_lb
.buffer
, lang
);
1472 process_file_name (this_file
, lang
);
1478 this_file
= argbuffer
[i
].what
;
1479 process_file (stdin
, this_file
, lang
);
1486 free (filebuf
.buffer
);
1487 free (token_name
.buffer
);
1489 if (!CTAGS
|| cxref_style
)
1491 /* Write the remaining tags to tagf (ETAGS) or stdout (CXREF). */
1492 put_entries (nodehead
);
1493 free_tree (nodehead
);
1499 /* Output file entries that have no tags. */
1500 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1502 fprintf (tagf
, "\f\n%s,0\n", fdp
->taggedfname
);
1504 while (nincluded_files
-- > 0)
1505 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1507 if (fclose (tagf
) == EOF
)
1511 exit (EXIT_SUCCESS
);
1514 /* From here on, we are in (CTAGS && !cxref_style) */
1518 for (i
= 0; i
< current_arg
; ++i
)
1520 switch (argbuffer
[i
].arg_type
)
1526 continue; /* the for loop */
1529 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1530 tagfile
, argbuffer
[i
].what
, tagfile
);
1531 if (system (cmd
) != EXIT_SUCCESS
)
1532 fatal ("failed to execute shell command", (char *)NULL
);
1534 append_to_tagfile
= TRUE
;
1537 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1540 put_entries (nodehead
); /* write all the tags (CTAGS) */
1541 free_tree (nodehead
);
1543 if (fclose (tagf
) == EOF
)
1547 if (append_to_tagfile
|| update
)
1549 char cmd
[2*BUFSIZ
+20];
1550 /* Maybe these should be used:
1551 setenv ("LC_COLLATE", "C", 1);
1552 setenv ("LC_ALL", "C", 1); */
1553 sprintf (cmd
, "sort -u -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1554 exit (system (cmd
));
1556 return EXIT_SUCCESS
;
1561 * Return a compressor given the file name. If EXTPTR is non-zero,
1562 * return a pointer into FILE where the compressor-specific
1563 * extension begins. If no compressor is found, NULL is returned
1564 * and EXTPTR is not significant.
1565 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1568 get_compressor_from_suffix (file
, extptr
)
1573 char *slash
, *suffix
;
1575 /* This relies on FN to be after canonicalize_filename,
1576 so we don't need to consider backslashes on DOS_NT. */
1577 slash
= etags_strrchr (file
, '/');
1578 suffix
= etags_strrchr (file
, '.');
1579 if (suffix
== NULL
|| suffix
< slash
)
1584 /* Let those poor souls who live with DOS 8+3 file name limits get
1585 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1586 Only the first do loop is run if not MSDOS */
1589 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1590 if (streq (compr
->suffix
, suffix
))
1593 break; /* do it only once: not really a loop */
1596 } while (*suffix
!= '\0');
1603 * Return a language given the name.
1606 get_language_from_langname (name
)
1612 error ("empty language name", (char *)NULL
);
1615 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1616 if (streq (name
, lang
->name
))
1618 error ("unknown language \"%s\"", name
);
1626 * Return a language given the interpreter name.
1629 get_language_from_interpreter (interpreter
)
1635 if (interpreter
== NULL
)
1637 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1638 if (lang
->interpreters
!= NULL
)
1639 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1640 if (streq (*iname
, interpreter
))
1649 * Return a language given the file name.
1652 get_language_from_filename (file
, case_sensitive
)
1654 bool case_sensitive
;
1657 char **name
, **ext
, *suffix
;
1659 /* Try whole file name first. */
1660 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1661 if (lang
->filenames
!= NULL
)
1662 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1663 if ((case_sensitive
)
1664 ? streq (*name
, file
)
1665 : strcaseeq (*name
, file
))
1668 /* If not found, try suffix after last dot. */
1669 suffix
= etags_strrchr (file
, '.');
1673 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1674 if (lang
->suffixes
!= NULL
)
1675 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1676 if ((case_sensitive
)
1677 ? streq (*ext
, suffix
)
1678 : strcaseeq (*ext
, suffix
))
1685 * This routine is called on each file argument.
1688 process_file_name (file
, lang
)
1692 struct stat stat_buf
;
1696 char *compressed_name
, *uncompressed_name
;
1697 char *ext
, *real_name
;
1700 canonicalize_filename (file
);
1701 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1703 error ("skipping inclusion of %s in self.", file
);
1706 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1708 compressed_name
= NULL
;
1709 real_name
= uncompressed_name
= savestr (file
);
1713 real_name
= compressed_name
= savestr (file
);
1714 uncompressed_name
= savenstr (file
, ext
- file
);
1717 /* If the canonicalized uncompressed name
1718 has already been dealt with, skip it silently. */
1719 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1721 assert (fdp
->infname
!= NULL
);
1722 if (streq (uncompressed_name
, fdp
->infname
))
1726 if (stat (real_name
, &stat_buf
) != 0)
1728 /* Reset real_name and try with a different name. */
1730 if (compressed_name
!= NULL
) /* try with the given suffix */
1732 if (stat (uncompressed_name
, &stat_buf
) == 0)
1733 real_name
= uncompressed_name
;
1735 else /* try all possible suffixes */
1737 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1739 compressed_name
= concat (file
, ".", compr
->suffix
);
1740 if (stat (compressed_name
, &stat_buf
) != 0)
1744 char *suf
= compressed_name
+ strlen (file
);
1745 size_t suflen
= strlen (compr
->suffix
) + 1;
1746 for ( ; suf
[1]; suf
++, suflen
--)
1748 memmove (suf
, suf
+ 1, suflen
);
1749 if (stat (compressed_name
, &stat_buf
) == 0)
1751 real_name
= compressed_name
;
1755 if (real_name
!= NULL
)
1758 free (compressed_name
);
1759 compressed_name
= NULL
;
1763 real_name
= compressed_name
;
1768 if (real_name
== NULL
)
1773 } /* try with a different name */
1775 if (!S_ISREG (stat_buf
.st_mode
))
1777 error ("skipping %s: it is not a regular file.", real_name
);
1780 if (real_name
== compressed_name
)
1782 char *cmd
= concat (compr
->command
, " ", real_name
);
1783 inf
= (FILE *) popen (cmd
, "r");
1787 inf
= fopen (real_name
, "r");
1794 process_file (inf
, uncompressed_name
, lang
);
1796 if (real_name
== compressed_name
)
1797 retval
= pclose (inf
);
1799 retval
= fclose (inf
);
1804 if (compressed_name
) free (compressed_name
);
1805 if (uncompressed_name
) free (uncompressed_name
);
1812 process_file (fh
, fn
, lang
)
1817 static const fdesc emptyfdesc
;
1820 /* Create a new input file description entry. */
1821 fdp
= xnew (1, fdesc
);
1824 fdp
->infname
= savestr (fn
);
1826 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1827 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1828 if (filename_is_absolute (fn
))
1830 /* An absolute file name. Canonicalize it. */
1831 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1835 /* A file name relative to cwd. Make it relative
1836 to the directory of the tags file. */
1837 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1839 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1841 fdp
->written
= FALSE
; /* not written on tags file yet */
1844 curfdp
= fdhead
; /* the current file description */
1848 /* If not Ctags, and if this is not metasource and if it contained no #line
1849 directives, we can write the tags and free all nodes pointing to
1852 && curfdp
->usecharno
/* no #line directives in this file */
1853 && !curfdp
->lang
->metasource
)
1857 /* Look for the head of the sublist relative to this file. See add_node
1858 for the structure of the node tree. */
1860 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1861 if (np
->fdp
== curfdp
)
1864 /* If we generated tags for this file, write and delete them. */
1867 /* This is the head of the last sublist, if any. The following
1868 instructions depend on this being true. */
1869 assert (np
->left
== NULL
);
1871 assert (fdhead
== curfdp
);
1872 assert (last_node
->fdp
== curfdp
);
1873 put_entries (np
); /* write tags for file curfdp->taggedfname */
1874 free_tree (np
); /* remove the written nodes */
1876 nodehead
= NULL
; /* no nodes left */
1878 prev
->left
= NULL
; /* delete the pointer to the sublist */
1884 * This routine sets up the boolean pseudo-functions which work
1885 * by setting boolean flags dependent upon the corresponding character.
1886 * Every char which is NOT in that string is not a white char. Therefore,
1887 * all of the array "_wht" is set to FALSE, and then the elements
1888 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1889 * of a char is TRUE if it is the string "white", else FALSE.
1897 for (i
= 0; i
< CHARS
; i
++)
1898 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1899 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1900 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1901 notinname('\0') = notinname('\n');
1902 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1903 begtoken('\0') = begtoken('\n');
1904 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1905 intoken('\0') = intoken('\n');
1906 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1907 endtoken('\0') = endtoken('\n');
1911 * This routine opens the specified file and calls the function
1912 * which finds the function and type definitions.
1919 language
*lang
= curfdp
->lang
;
1920 Lang_function
*parser
= NULL
;
1922 /* If user specified a language, use it. */
1923 if (lang
!= NULL
&& lang
->function
!= NULL
)
1925 parser
= lang
->function
;
1928 /* Else try to guess the language given the file name. */
1931 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1932 if (lang
!= NULL
&& lang
->function
!= NULL
)
1934 curfdp
->lang
= lang
;
1935 parser
= lang
->function
;
1939 /* Else look for sharp-bang as the first two characters. */
1941 && readline_internal (&lb
, inf
) > 0
1943 && lb
.buffer
[0] == '#'
1944 && lb
.buffer
[1] == '!')
1948 /* Set lp to point at the first char after the last slash in the
1949 line or, if no slashes, at the first nonblank. Then set cp to
1950 the first successive blank and terminate the string. */
1951 lp
= etags_strrchr (lb
.buffer
+2, '/');
1955 lp
= skip_spaces (lb
.buffer
+ 2);
1956 cp
= skip_non_spaces (lp
);
1959 if (strlen (lp
) > 0)
1961 lang
= get_language_from_interpreter (lp
);
1962 if (lang
!= NULL
&& lang
->function
!= NULL
)
1964 curfdp
->lang
= lang
;
1965 parser
= lang
->function
;
1970 /* We rewind here, even if inf may be a pipe. We fail if the
1971 length of the first line is longer than the pipe block size,
1972 which is unlikely. */
1975 /* Else try to guess the language given the case insensitive file name. */
1978 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1979 if (lang
!= NULL
&& lang
->function
!= NULL
)
1981 curfdp
->lang
= lang
;
1982 parser
= lang
->function
;
1986 /* Else try Fortran or C. */
1989 node
*old_last_node
= last_node
;
1991 curfdp
->lang
= get_language_from_langname ("fortran");
1994 if (old_last_node
== last_node
)
1995 /* No Fortran entries found. Try C. */
1997 /* We do not tag if rewind fails.
1998 Only the file name will be recorded in the tags file. */
2000 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
2006 if (!no_line_directive
2007 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
2008 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
2009 file, or anyway we parsed a file that is automatically generated from
2010 this one. If this is the case, the bingo.c file contained #line
2011 directives that generated tags pointing to this file. Let's delete
2012 them all before parsing this file, which is the real source. */
2014 fdesc
**fdpp
= &fdhead
;
2015 while (*fdpp
!= NULL
)
2017 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
2018 /* We found one of those! We must delete both the file description
2019 and all tags referring to it. */
2021 fdesc
*badfdp
= *fdpp
;
2023 /* Delete the tags referring to badfdp->taggedfname
2024 that were obtained from badfdp->infname. */
2025 invalidate_nodes (badfdp
, &nodehead
);
2027 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
2028 free_fdesc (badfdp
);
2031 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
2034 assert (parser
!= NULL
);
2036 /* Generic initialisations before reading from file. */
2037 linebuffer_setlen (&filebuf
, 0); /* reset the file buffer */
2039 /* Generic initialisations before parsing file with readline. */
2040 lineno
= 0; /* reset global line number */
2041 charno
= 0; /* reset global char number */
2042 linecharno
= 0; /* reset global char number of line start */
2046 regex_tag_multiline ();
2051 * Check whether an implicitly named tag should be created,
2052 * then call `pfnote'.
2053 * NAME is a string that is internally copied by this function.
2055 * TAGS format specification
2056 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
2057 * The following is explained in some more detail in etc/ETAGS.EBNF.
2059 * make_tag creates tags with "implicit tag names" (unnamed tags)
2060 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
2061 * 1. NAME does not contain any of the characters in NONAM;
2062 * 2. LINESTART contains name as either a rightmost, or rightmost but
2063 * one character, substring;
2064 * 3. the character, if any, immediately before NAME in LINESTART must
2065 * be a character in NONAM;
2066 * 4. the character, if any, immediately after NAME in LINESTART must
2067 * also be a character in NONAM.
2069 * The implementation uses the notinname() macro, which recognises the
2070 * characters stored in the string `nonam'.
2071 * etags.el needs to use the same characters that are in NONAM.
2074 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
2075 char *name
; /* tag name, or NULL if unnamed */
2076 int namelen
; /* tag length */
2077 bool is_func
; /* tag is a function */
2078 char *linestart
; /* start of the line where tag is */
2079 int linelen
; /* length of the line where tag is */
2080 int lno
; /* line number */
2081 long cno
; /* character number */
2083 bool named
= (name
!= NULL
&& namelen
> 0);
2085 if (!CTAGS
&& named
) /* maybe set named to false */
2086 /* Let's try to make an implicit tag name, that is, create an unnamed tag
2087 such that etags.el can guess a name from it. */
2090 register char *cp
= name
;
2092 for (i
= 0; i
< namelen
; i
++)
2093 if (notinname (*cp
++))
2095 if (i
== namelen
) /* rule #1 */
2097 cp
= linestart
+ linelen
- namelen
;
2098 if (notinname (linestart
[linelen
-1]))
2099 cp
-= 1; /* rule #4 */
2100 if (cp
>= linestart
/* rule #2 */
2102 || notinname (cp
[-1])) /* rule #3 */
2103 && strneq (name
, cp
, namelen
)) /* rule #2 */
2104 named
= FALSE
; /* use implicit tag name */
2109 name
= savenstr (name
, namelen
);
2112 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
2117 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
2118 char *name
; /* tag name, or NULL if unnamed */
2119 bool is_func
; /* tag is a function */
2120 char *linestart
; /* start of the line where tag is */
2121 int linelen
; /* length of the line where tag is */
2122 int lno
; /* line number */
2123 long cno
; /* character number */
2127 assert (name
== NULL
|| name
[0] != '\0');
2128 if (CTAGS
&& name
== NULL
)
2131 np
= xnew (1, node
);
2133 /* If ctags mode, change name "main" to M<thisfilename>. */
2134 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
2136 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
2137 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
2138 fp
= etags_strrchr (np
->name
, '.');
2139 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
2145 np
->been_warned
= FALSE
;
2147 np
->is_func
= is_func
;
2149 if (np
->fdp
->usecharno
)
2150 /* Our char numbers are 0-base, because of C language tradition?
2151 ctags compatibility? old versions compatibility? I don't know.
2152 Anyway, since emacs's are 1-base we expect etags.el to take care
2153 of the difference. If we wanted to have 1-based numbers, we would
2154 uncomment the +1 below. */
2155 np
->cno
= cno
/* + 1 */ ;
2157 np
->cno
= invalidcharno
;
2158 np
->left
= np
->right
= NULL
;
2159 if (CTAGS
&& !cxref_style
)
2161 if (strlen (linestart
) < 50)
2162 np
->regex
= concat (linestart
, "$", "");
2164 np
->regex
= savenstr (linestart
, 50);
2167 np
->regex
= savenstr (linestart
, linelen
);
2169 add_node (np
, &nodehead
);
2174 * recurse on left children, iterate on right children.
2182 register node
*node_right
= np
->right
;
2183 free_tree (np
->left
);
2184 if (np
->name
!= NULL
)
2194 * delete a file description
2198 register fdesc
*fdp
;
2200 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
2201 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
2202 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
2203 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
2204 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
2210 * Adds a node to the tree of nodes. In etags mode, sort by file
2211 * name. In ctags mode, sort by tag name. Make no attempt at
2214 * add_node is the only function allowed to add nodes, so it can
2218 add_node (np
, cur_node_p
)
2219 node
*np
, **cur_node_p
;
2222 register node
*cur_node
= *cur_node_p
;
2224 if (cur_node
== NULL
)
2234 /* For each file name, tags are in a linked sublist on the right
2235 pointer. The first tags of different files are a linked list
2236 on the left pointer. last_node points to the end of the last
2238 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
2240 /* Let's use the same sublist as the last added node. */
2241 assert (last_node
->right
== NULL
);
2242 last_node
->right
= np
;
2245 else if (cur_node
->fdp
== np
->fdp
)
2247 /* Scanning the list we found the head of a sublist which is
2248 good for us. Let's scan this sublist. */
2249 add_node (np
, &cur_node
->right
);
2252 /* The head of this sublist is not good for us. Let's try the
2254 add_node (np
, &cur_node
->left
);
2255 } /* if ETAGS mode */
2260 dif
= strcmp (np
->name
, cur_node
->name
);
2263 * If this tag name matches an existing one, then
2264 * do not add the node, but maybe print a warning.
2266 if (no_duplicates
&& !dif
)
2268 if (np
->fdp
== cur_node
->fdp
)
2272 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
2273 np
->fdp
->infname
, lineno
, np
->name
);
2274 fprintf (stderr
, "Second entry ignored\n");
2277 else if (!cur_node
->been_warned
&& !no_warnings
)
2281 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2282 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2283 cur_node
->been_warned
= TRUE
;
2288 /* Actually add the node */
2289 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2290 } /* if CTAGS mode */
2294 * invalidate_nodes ()
2295 * Scan the node tree and invalidate all nodes pointing to the
2296 * given file description (CTAGS case) or free them (ETAGS case).
2299 invalidate_nodes (badfdp
, npp
)
2310 if (np
->left
!= NULL
)
2311 invalidate_nodes (badfdp
, &np
->left
);
2312 if (np
->fdp
== badfdp
)
2314 if (np
->right
!= NULL
)
2315 invalidate_nodes (badfdp
, &np
->right
);
2319 assert (np
->fdp
!= NULL
);
2320 if (np
->fdp
== badfdp
)
2322 *npp
= np
->left
; /* detach the sublist from the list */
2323 np
->left
= NULL
; /* isolate it */
2324 free_tree (np
); /* free it */
2325 invalidate_nodes (badfdp
, npp
);
2328 invalidate_nodes (badfdp
, &np
->left
);
2333 static int total_size_of_entries
__P((node
*));
2334 static int number_len
__P((long));
2336 /* Length of a non-negative number's decimal representation. */
2342 while ((num
/= 10) > 0)
2348 * Return total number of characters that put_entries will output for
2349 * the nodes in the linked list at the right of the specified node.
2350 * This count is irrelevant with etags.el since emacs 19.34 at least,
2351 * but is still supplied for backward compatibility.
2354 total_size_of_entries (np
)
2357 register int total
= 0;
2359 for (; np
!= NULL
; np
= np
->right
)
2362 total
+= strlen (np
->regex
) + 1; /* pat\177 */
2363 if (np
->name
!= NULL
)
2364 total
+= strlen (np
->name
) + 1; /* name\001 */
2365 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2366 if (np
->cno
!= invalidcharno
) /* cno */
2367 total
+= number_len (np
->cno
);
2368 total
+= 1; /* newline */
2379 static fdesc
*fdp
= NULL
;
2384 /* Output subentries that precede this one */
2386 put_entries (np
->left
);
2388 /* Output this entry */
2397 fprintf (tagf
, "\f\n%s,%d\n",
2398 fdp
->taggedfname
, total_size_of_entries (np
));
2399 fdp
->written
= TRUE
;
2401 fputs (np
->regex
, tagf
);
2402 fputc ('\177', tagf
);
2403 if (np
->name
!= NULL
)
2405 fputs (np
->name
, tagf
);
2406 fputc ('\001', tagf
);
2408 fprintf (tagf
, "%d,", np
->lno
);
2409 if (np
->cno
!= invalidcharno
)
2410 fprintf (tagf
, "%ld", np
->cno
);
2416 if (np
->name
== NULL
)
2417 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2422 fprintf (stdout
, "%s %s %d\n",
2423 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2425 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2426 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->regex
);
2430 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2433 { /* function or #define macro with args */
2434 putc (searchar
, tagf
);
2437 for (sp
= np
->regex
; *sp
; sp
++)
2439 if (*sp
== '\\' || *sp
== searchar
)
2443 putc (searchar
, tagf
);
2446 { /* anything else; text pattern inadequate */
2447 fprintf (tagf
, "%d", np
->lno
);
2452 } /* if this node contains a valid tag */
2454 /* Output subentries that follow this one */
2455 put_entries (np
->right
);
2457 put_entries (np
->left
);
2462 #define C_EXT 0x00fff /* C extensions */
2463 #define C_PLAIN 0x00000 /* C */
2464 #define C_PLPL 0x00001 /* C++ */
2465 #define C_STAR 0x00003 /* C* */
2466 #define C_JAVA 0x00005 /* JAVA */
2467 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2468 #define YACC 0x10000 /* yacc file */
2471 * The C symbol tables.
2476 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2478 st_C_ignore
, st_C_attribute
,
2481 st_C_class
, st_C_template
,
2482 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
2485 static unsigned int hash
__P((const char *, unsigned int));
2486 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2487 static enum sym_type C_symtype
__P((char *, int, int));
2489 /* Feed stuff between (but not including) %[ and %] lines to:
2495 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2499 while, 0, st_C_ignore
2500 switch, 0, st_C_ignore
2501 return, 0, st_C_ignore
2502 __attribute__, 0, st_C_attribute
2503 GTY, 0, st_C_attribute
2504 @interface, 0, st_C_objprot
2505 @protocol, 0, st_C_objprot
2506 @implementation,0, st_C_objimpl
2507 @end, 0, st_C_objend
2508 import, (C_JAVA & ~C_PLPL), st_C_ignore
2509 package, (C_JAVA & ~C_PLPL), st_C_ignore
2510 friend, C_PLPL, st_C_ignore
2511 extends, (C_JAVA & ~C_PLPL), st_C_javastruct
2512 implements, (C_JAVA & ~C_PLPL), st_C_javastruct
2513 interface, (C_JAVA & ~C_PLPL), st_C_struct
2514 class, 0, st_C_class
2515 namespace, C_PLPL, st_C_struct
2516 domain, C_STAR, st_C_struct
2517 union, 0, st_C_struct
2518 struct, 0, st_C_struct
2519 extern, 0, st_C_extern
2521 typedef, 0, st_C_typedef
2522 define, 0, st_C_define
2523 undef, 0, st_C_define
2524 operator, C_PLPL, st_C_operator
2525 template, 0, st_C_template
2526 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2527 DEFUN, 0, st_C_gnumacro
2528 SYSCALL, 0, st_C_gnumacro
2529 ENTRY, 0, st_C_gnumacro
2530 PSEUDO, 0, st_C_gnumacro
2531 # These are defined inside C functions, so currently they are not met.
2532 # EXFUN used in glibc, DEFVAR_* in emacs.
2533 #EXFUN, 0, st_C_gnumacro
2534 #DEFVAR_, 0, st_C_gnumacro
2536 and replace lines between %< and %> with its output, then:
2537 - remove the #if characterset check
2538 - make in_word_set static and not inline. */
2540 /* C code produced by gperf version 3.0.1 */
2541 /* Command-line: gperf -m 5 */
2542 /* Computed positions: -k'2-3' */
2544 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2545 /* maximum key range = 33, duplicates = 0 */
2556 register const char *str
;
2557 register unsigned int len
;
2559 static unsigned char asso_values
[] =
2561 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2562 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2563 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2564 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2565 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2566 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2567 35, 35, 35, 35, 35, 35, 35, 35, 35, 3,
2568 26, 35, 35, 35, 35, 35, 35, 35, 27, 35,
2569 35, 35, 35, 24, 0, 35, 35, 35, 35, 0,
2570 35, 35, 35, 35, 35, 1, 35, 16, 35, 6,
2571 23, 0, 0, 35, 22, 0, 35, 35, 5, 0,
2572 0, 15, 1, 35, 6, 35, 8, 19, 35, 16,
2573 4, 5, 35, 35, 35, 35, 35, 35, 35, 35,
2574 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2575 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2576 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2577 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2578 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2579 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2580 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2581 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2582 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2583 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2584 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2585 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2586 35, 35, 35, 35, 35, 35
2588 register int hval
= len
;
2593 hval
+= asso_values
[(unsigned char)str
[2]];
2596 hval
+= asso_values
[(unsigned char)str
[1]];
2602 static struct C_stab_entry
*
2603 in_word_set (str
, len
)
2604 register const char *str
;
2605 register unsigned int len
;
2609 TOTAL_KEYWORDS
= 33,
2610 MIN_WORD_LENGTH
= 2,
2611 MAX_WORD_LENGTH
= 15,
2616 static struct C_stab_entry wordlist
[] =
2619 {"if", 0, st_C_ignore
},
2620 {"GTY", 0, st_C_attribute
},
2621 {"@end", 0, st_C_objend
},
2622 {"union", 0, st_C_struct
},
2623 {"define", 0, st_C_define
},
2624 {"import", (C_JAVA
& ~C_PLPL
), st_C_ignore
},
2625 {"template", 0, st_C_template
},
2626 {"operator", C_PLPL
, st_C_operator
},
2627 {"@interface", 0, st_C_objprot
},
2628 {"implements", (C_JAVA
& ~C_PLPL
), st_C_javastruct
},
2629 {"friend", C_PLPL
, st_C_ignore
},
2630 {"typedef", 0, st_C_typedef
},
2631 {"return", 0, st_C_ignore
},
2632 {"@implementation",0, st_C_objimpl
},
2633 {"@protocol", 0, st_C_objprot
},
2634 {"interface", (C_JAVA
& ~C_PLPL
), st_C_struct
},
2635 {"extern", 0, st_C_extern
},
2636 {"extends", (C_JAVA
& ~C_PLPL
), st_C_javastruct
},
2637 {"struct", 0, st_C_struct
},
2638 {"domain", C_STAR
, st_C_struct
},
2639 {"switch", 0, st_C_ignore
},
2640 {"enum", 0, st_C_enum
},
2641 {"for", 0, st_C_ignore
},
2642 {"namespace", C_PLPL
, st_C_struct
},
2643 {"class", 0, st_C_class
},
2644 {"while", 0, st_C_ignore
},
2645 {"undef", 0, st_C_define
},
2646 {"package", (C_JAVA
& ~C_PLPL
), st_C_ignore
},
2647 {"__attribute__", 0, st_C_attribute
},
2648 {"SYSCALL", 0, st_C_gnumacro
},
2649 {"ENTRY", 0, st_C_gnumacro
},
2650 {"PSEUDO", 0, st_C_gnumacro
},
2651 {"DEFUN", 0, st_C_gnumacro
}
2654 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2656 register int key
= hash (str
, len
);
2658 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2660 register const char *s
= wordlist
[key
].name
;
2662 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1) && s
[len
] == '\0')
2663 return &wordlist
[key
];
2670 static enum sym_type
2671 C_symtype (str
, len
, c_ext
)
2676 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2678 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2685 * Ignoring __attribute__ ((list))
2687 static bool inattribute
; /* looking at an __attribute__ construct */
2690 * C functions and variables are recognized using a simple
2691 * finite automaton. fvdef is its state variable.
2695 fvnone
, /* nothing seen */
2696 fdefunkey
, /* Emacs DEFUN keyword seen */
2697 fdefunname
, /* Emacs DEFUN name seen */
2698 foperator
, /* func: operator keyword seen (cplpl) */
2699 fvnameseen
, /* function or variable name seen */
2700 fstartlist
, /* func: just after open parenthesis */
2701 finlist
, /* func: in parameter list */
2702 flistseen
, /* func: after parameter list */
2703 fignore
, /* func: before open brace */
2704 vignore
/* var-like: ignore until ';' */
2707 static bool fvextern
; /* func or var: extern keyword seen; */
2710 * typedefs are recognized using a simple finite automaton.
2711 * typdef is its state variable.
2715 tnone
, /* nothing seen */
2716 tkeyseen
, /* typedef keyword seen */
2717 ttypeseen
, /* defined type seen */
2718 tinbody
, /* inside typedef body */
2719 tend
, /* just before typedef tag */
2720 tignore
/* junk after typedef tag */
2724 * struct-like structures (enum, struct and union) are recognized
2725 * using another simple finite automaton. `structdef' is its state
2730 snone
, /* nothing seen yet,
2731 or in struct body if bracelev > 0 */
2732 skeyseen
, /* struct-like keyword seen */
2733 stagseen
, /* struct-like tag seen */
2734 scolonseen
/* colon seen after struct-like tag */
2738 * When objdef is different from onone, objtag is the name of the class.
2740 static char *objtag
= "<uninited>";
2743 * Yet another little state machine to deal with preprocessor lines.
2747 dnone
, /* nothing seen */
2748 dsharpseen
, /* '#' seen as first char on line */
2749 ddefineseen
, /* '#' and 'define' seen */
2750 dignorerest
/* ignore rest of line */
2754 * State machine for Objective C protocols and implementations.
2755 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2759 onone
, /* nothing seen */
2760 oprotocol
, /* @interface or @protocol seen */
2761 oimplementation
, /* @implementations seen */
2762 otagseen
, /* class name seen */
2763 oparenseen
, /* parenthesis before category seen */
2764 ocatseen
, /* category name seen */
2765 oinbody
, /* in @implementation body */
2766 omethodsign
, /* in @implementation body, after +/- */
2767 omethodtag
, /* after method name */
2768 omethodcolon
, /* after method colon */
2769 omethodparm
, /* after method parameter */
2770 oignore
/* wait for @end */
2775 * Use this structure to keep info about the token read, and how it
2776 * should be tagged. Used by the make_C_tag function to build a tag.
2780 char *line
; /* string containing the token */
2781 int offset
; /* where the token starts in LINE */
2782 int length
; /* token length */
2784 The previous members can be used to pass strings around for generic
2785 purposes. The following ones specifically refer to creating tags. In this
2786 case the token contained here is the pattern that will be used to create a
2789 bool valid
; /* do not create a tag; the token should be
2790 invalidated whenever a state machine is
2791 reset prematurely */
2792 bool named
; /* create a named tag */
2793 int lineno
; /* source line number of tag */
2794 long linepos
; /* source char number of tag */
2795 } token
; /* latest token read */
2798 * Variables and functions for dealing with nested structures.
2799 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2801 static void pushclass_above
__P((int, char *, int));
2802 static void popclass_above
__P((int));
2803 static void write_classname
__P((linebuffer
*, char *qualifier
));
2806 char **cname
; /* nested class names */
2807 int *bracelev
; /* nested class brace level */
2808 int nl
; /* class nesting level (elements used) */
2809 int size
; /* length of the array */
2810 } cstack
; /* stack for nested declaration tags */
2811 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2812 #define nestlev (cstack.nl)
2813 /* After struct keyword or in struct body, not inside a nested function. */
2814 #define instruct (structdef == snone && nestlev > 0 \
2815 && bracelev == cstack.bracelev[nestlev-1] + 1)
2818 pushclass_above (bracelev
, str
, len
)
2825 popclass_above (bracelev
);
2827 if (nl
>= cstack
.size
)
2829 int size
= cstack
.size
*= 2;
2830 xrnew (cstack
.cname
, size
, char *);
2831 xrnew (cstack
.bracelev
, size
, int);
2833 assert (nl
== 0 || cstack
.bracelev
[nl
-1] < bracelev
);
2834 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2835 cstack
.bracelev
[nl
] = bracelev
;
2840 popclass_above (bracelev
)
2845 for (nl
= cstack
.nl
- 1;
2846 nl
>= 0 && cstack
.bracelev
[nl
] >= bracelev
;
2849 if (cstack
.cname
[nl
] != NULL
)
2850 free (cstack
.cname
[nl
]);
2856 write_classname (cn
, qualifier
)
2861 int qlen
= strlen (qualifier
);
2863 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2867 cn
->buffer
[0] = '\0';
2871 len
= strlen (cstack
.cname
[0]);
2872 linebuffer_setlen (cn
, len
);
2873 strcpy (cn
->buffer
, cstack
.cname
[0]);
2875 for (i
= 1; i
< cstack
.nl
; i
++)
2880 s
= cstack
.cname
[i
];
2885 linebuffer_setlen (cn
, len
);
2886 strncat (cn
->buffer
, qualifier
, qlen
);
2887 strncat (cn
->buffer
, s
, slen
);
2892 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2893 static void make_C_tag
__P((bool));
2897 * checks to see if the current token is at the start of a
2898 * function or variable, or corresponds to a typedef, or
2899 * is a struct/union/enum tag, or #define, or an enum constant.
2901 * *IS_FUNC gets TRUE if the token is a function or #define macro
2902 * with args. C_EXTP points to which language we are looking at.
2913 consider_token (str
, len
, c
, c_extp
, bracelev
, parlev
, is_func_or_var
)
2914 register char *str
; /* IN: token pointer */
2915 register int len
; /* IN: token length */
2916 register int c
; /* IN: first char after the token */
2917 int *c_extp
; /* IN, OUT: C extensions mask */
2918 int bracelev
; /* IN: brace level */
2919 int parlev
; /* IN: parenthesis level */
2920 bool *is_func_or_var
; /* OUT: function or variable found */
2922 /* When structdef is stagseen, scolonseen, or snone with bracelev > 0,
2923 structtype is the type of the preceding struct-like keyword, and
2924 structbracelev is the brace level where it has been seen. */
2925 static enum sym_type structtype
;
2926 static int structbracelev
;
2927 static enum sym_type toktype
;
2930 toktype
= C_symtype (str
, len
, *c_extp
);
2933 * Skip __attribute__
2935 if (toktype
== st_C_attribute
)
2942 * Advance the definedef state machine.
2947 /* We're not on a preprocessor line. */
2948 if (toktype
== st_C_gnumacro
)
2955 if (toktype
== st_C_define
)
2957 definedef
= ddefineseen
;
2961 definedef
= dignorerest
;
2966 * Make a tag for any macro, unless it is a constant
2967 * and constantypedefs is FALSE.
2969 definedef
= dignorerest
;
2970 *is_func_or_var
= (c
== '(');
2971 if (!*is_func_or_var
&& !constantypedefs
)
2978 error ("internal error: definedef value.", (char *)NULL
);
2987 if (toktype
== st_C_typedef
)
3007 if (structdef
== snone
&& fvdef
== fvnone
)
3026 case st_C_javastruct
:
3027 if (structdef
== stagseen
)
3028 structdef
= scolonseen
;
3032 if ((*c_extp
& C_AUTO
) /* automatic detection of C++ language */
3034 && definedef
== dnone
&& structdef
== snone
3035 && typdef
== tnone
&& fvdef
== fvnone
)
3036 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
3037 if (toktype
== st_C_template
)
3044 && (typdef
== tkeyseen
3045 || (typedefs_or_cplusplus
&& structdef
== snone
)))
3047 structdef
= skeyseen
;
3048 structtype
= toktype
;
3049 structbracelev
= bracelev
;
3050 if (fvdef
== fvnameseen
)
3056 if (structdef
== skeyseen
)
3058 structdef
= stagseen
;
3062 if (typdef
!= tnone
)
3065 /* Detect Objective C constructs. */
3075 objdef
= oimplementation
;
3079 case oimplementation
:
3080 /* Save the class tag for functions or variables defined inside. */
3081 objtag
= savenstr (str
, len
);
3085 /* Save the class tag for categories. */
3086 objtag
= savenstr (str
, len
);
3088 *is_func_or_var
= TRUE
;
3092 *is_func_or_var
= TRUE
;
3100 objdef
= omethodtag
;
3101 linebuffer_setlen (&token_name
, len
);
3102 strncpy (token_name
.buffer
, str
, len
);
3103 token_name
.buffer
[len
] = '\0';
3109 objdef
= omethodparm
;
3115 objdef
= omethodtag
;
3116 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
3117 strncat (token_name
.buffer
, str
, len
);
3122 if (toktype
== st_C_objend
)
3124 /* Memory leakage here: the string pointed by objtag is
3125 never released, because many tests would be needed to
3126 avoid breaking on incorrect input code. The amount of
3127 memory leaked here is the sum of the lengths of the
3135 /* A function, variable or enum constant? */
3157 *is_func_or_var
= TRUE
;
3161 && structdef
== snone
3162 && structtype
== st_C_enum
&& bracelev
> structbracelev
)
3163 return TRUE
; /* enum constant */
3169 fvdef
= fdefunname
; /* GNU macro */
3170 *is_func_or_var
= TRUE
;
3178 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
3179 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
3188 if (len
>= 10 && strneq (str
+len
-10, "::operator", 10))
3190 if (*c_extp
& C_AUTO
) /* automatic detection of C++ */
3191 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
3193 *is_func_or_var
= TRUE
;
3196 if (bracelev
> 0 && !instruct
)
3198 fvdef
= fvnameseen
; /* function or variable */
3199 *is_func_or_var
= TRUE
;
3210 * C_entries often keeps pointers to tokens or lines which are older than
3211 * the line currently read. By keeping two line buffers, and switching
3212 * them at end of line, it is possible to use those pointers.
3220 #define current_lb_is_new (newndx == curndx)
3221 #define switch_line_buffers() (curndx = 1 - curndx)
3223 #define curlb (lbs[curndx].lb)
3224 #define newlb (lbs[newndx].lb)
3225 #define curlinepos (lbs[curndx].linepos)
3226 #define newlinepos (lbs[newndx].linepos)
3228 #define plainc ((c_ext & C_EXT) == C_PLAIN)
3229 #define cplpl (c_ext & C_PLPL)
3230 #define cjava ((c_ext & C_JAVA) == C_JAVA)
3232 #define CNL_SAVE_DEFINEDEF() \
3234 curlinepos = charno; \
3235 readline (&curlb, inf); \
3236 lp = curlb.buffer; \
3243 CNL_SAVE_DEFINEDEF(); \
3244 if (savetoken.valid) \
3246 token = savetoken; \
3247 savetoken.valid = FALSE; \
3249 definedef = dnone; \
3257 /* This function is never called when token.valid is FALSE, but
3258 we must protect against invalid input or internal errors. */
3260 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3261 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3263 { /* this branch is optimised away if !DEBUG */
3264 make_tag (concat ("INVALID TOKEN:-->", token_name
.buffer
, ""),
3265 token_name
.len
+ 17, isfun
, token
.line
,
3266 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3267 error ("INVALID TOKEN", NULL
);
3270 token
.valid
= FALSE
;
3276 * This routine finds functions, variables, typedefs,
3277 * #define's, enum constants and struct/union/enum definitions in
3278 * C syntax and adds them to the list.
3281 C_entries (c_ext
, inf
)
3282 int c_ext
; /* extension of C */
3283 FILE *inf
; /* input file */
3285 register char c
; /* latest char read; '\0' for end of line */
3286 register char *lp
; /* pointer one beyond the character `c' */
3287 int curndx
, newndx
; /* indices for current and new lb */
3288 register int tokoff
; /* offset in line of start of current token */
3289 register int toklen
; /* length of current token */
3290 char *qualifier
; /* string used to qualify names */
3291 int qlen
; /* length of qualifier */
3292 int bracelev
; /* current brace level */
3293 int bracketlev
; /* current bracket level */
3294 int parlev
; /* current parenthesis level */
3295 int attrparlev
; /* __attribute__ parenthesis level */
3296 int templatelev
; /* current template level */
3297 int typdefbracelev
; /* bracelev where a typedef struct body begun */
3298 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3299 bool yacc_rules
; /* in the rules part of a yacc file */
3300 struct tok savetoken
= {0}; /* token saved during preprocessor handling */
3303 linebuffer_init (&lbs
[0].lb
);
3304 linebuffer_init (&lbs
[1].lb
);
3305 if (cstack
.size
== 0)
3307 cstack
.size
= (DEBUG
) ? 1 : 4;
3309 cstack
.cname
= xnew (cstack
.size
, char *);
3310 cstack
.bracelev
= xnew (cstack
.size
, int);
3313 tokoff
= toklen
= typdefbracelev
= 0; /* keep compiler quiet */
3314 curndx
= newndx
= 0;
3318 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3319 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3321 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3322 token
.valid
= savetoken
.valid
= FALSE
;
3323 bracelev
= bracketlev
= parlev
= attrparlev
= templatelev
= 0;
3325 { qualifier
= "."; qlen
= 1; }
3327 { qualifier
= "::"; qlen
= 2; }
3335 /* If we are at the end of the line, the next character is a
3336 '\0'; do not skip it, because it is what tells us
3337 to read the next line. */
3358 /* Newlines inside comments do not end macro definitions in
3360 CNL_SAVE_DEFINEDEF ();
3373 /* Newlines inside strings do not end macro definitions
3374 in traditional cpp, even though compilers don't
3375 usually accept them. */
3376 CNL_SAVE_DEFINEDEF ();
3386 /* Hmmm, something went wrong. */
3395 else if (bracketlev
> 0)
3400 if (--bracketlev
> 0)
3404 CNL_SAVE_DEFINEDEF ();
3432 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3445 else if (/* cplpl && */ *lp
== '/')
3451 if ((c_ext
& YACC
) && *lp
== '%')
3453 /* Entering or exiting rules section in yacc file. */
3455 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3456 typdef
= tnone
; structdef
= snone
;
3457 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3459 yacc_rules
= !yacc_rules
;
3465 if (definedef
== dnone
)
3468 bool cpptoken
= TRUE
;
3470 /* Look back on this line. If all blanks, or nonblanks
3471 followed by an end of comment, this is a preprocessor
3473 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3476 if (*cp
== '*' && *(cp
+1) == '/')
3485 definedef
= dsharpseen
;
3486 } /* if (definedef == dnone) */
3494 /* Consider token only if some involved conditions are satisfied. */
3495 if (typdef
!= tignore
3496 && definedef
!= dignorerest
3499 && (definedef
!= dnone
3500 || structdef
!= scolonseen
)
3507 if (c
== ':' && *lp
== ':' && begtoken (lp
[1]))
3508 /* This handles :: in the middle,
3509 but not at the beginning of an identifier.
3510 Also, space-separated :: is not recognised. */
3512 if (c_ext
& C_AUTO
) /* automatic detection of C++ */
3513 c_ext
= (c_ext
| C_PLPL
) & ~C_AUTO
;
3517 goto still_in_token
;
3521 bool funorvar
= FALSE
;
3524 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3525 &c_ext
, bracelev
, parlev
,
3528 if (fvdef
== foperator
)
3531 lp
= skip_spaces (lp
-1);
3535 && !iswhite (*lp
) && *lp
!= '(')
3538 toklen
+= lp
- oldlp
;
3540 token
.named
= FALSE
;
3542 && nestlev
> 0 && definedef
== dnone
)
3543 /* in struct body */
3545 write_classname (&token_name
, qualifier
);
3546 linebuffer_setlen (&token_name
,
3547 token_name
.len
+qlen
+toklen
);
3548 strcat (token_name
.buffer
, qualifier
);
3549 strncat (token_name
.buffer
,
3550 newlb
.buffer
+ tokoff
, toklen
);
3553 else if (objdef
== ocatseen
)
3554 /* Objective C category */
3556 int len
= strlen (objtag
) + 2 + toklen
;
3557 linebuffer_setlen (&token_name
, len
);
3558 strcpy (token_name
.buffer
, objtag
);
3559 strcat (token_name
.buffer
, "(");
3560 strncat (token_name
.buffer
,
3561 newlb
.buffer
+ tokoff
, toklen
);
3562 strcat (token_name
.buffer
, ")");
3565 else if (objdef
== omethodtag
3566 || objdef
== omethodparm
)
3567 /* Objective C method */
3571 else if (fvdef
== fdefunname
)
3572 /* GNU DEFUN and similar macros */
3574 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3578 /* Rewrite the tag so that emacs lisp DEFUNs
3579 can be found by their elisp name */
3585 linebuffer_setlen (&token_name
, len
);
3586 strncpy (token_name
.buffer
,
3587 newlb
.buffer
+ off
, len
);
3588 token_name
.buffer
[len
] = '\0';
3591 if (token_name
.buffer
[len
] == '_')
3592 token_name
.buffer
[len
] = '-';
3593 token
.named
= defun
;
3597 linebuffer_setlen (&token_name
, toklen
);
3598 strncpy (token_name
.buffer
,
3599 newlb
.buffer
+ tokoff
, toklen
);
3600 token_name
.buffer
[toklen
] = '\0';
3601 /* Name macros and members. */
3602 token
.named
= (structdef
== stagseen
3603 || typdef
== ttypeseen
3606 && definedef
== dignorerest
)
3608 && definedef
== dnone
3609 && structdef
== snone
3612 token
.lineno
= lineno
;
3613 token
.offset
= tokoff
;
3614 token
.length
= toklen
;
3615 token
.line
= newlb
.buffer
;
3616 token
.linepos
= newlinepos
;
3619 if (definedef
== dnone
3620 && (fvdef
== fvnameseen
3621 || fvdef
== foperator
3622 || structdef
== stagseen
3624 || typdef
== ttypeseen
3625 || objdef
!= onone
))
3627 if (current_lb_is_new
)
3628 switch_line_buffers ();
3630 else if (definedef
!= dnone
3631 || fvdef
== fdefunname
3633 make_C_tag (funorvar
);
3635 else /* not yacc and consider_token failed */
3637 if (inattribute
&& fvdef
== fignore
)
3639 /* We have just met __attribute__ after a
3640 function parameter list: do not tag the
3647 } /* if (endtoken (c)) */
3648 else if (intoken (c
))
3654 } /* if (midtoken) */
3655 else if (begtoken (c
))
3663 /* This prevents tagging fb in
3664 void (__attribute__((noreturn)) *fb) (void);
3665 Fixing this is not easy and not very important. */
3669 if (plainc
|| declarations
)
3671 make_C_tag (TRUE
); /* a function */
3676 if (structdef
== stagseen
&& !cjava
)
3678 popclass_above (bracelev
);
3686 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3688 tokoff
= lp
- 1 - newlb
.buffer
;
3693 } /* if (begtoken) */
3694 } /* if must look at token */
3697 /* Detect end of line, colon, comma, semicolon and various braces
3698 after having handled a token.*/
3704 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3706 make_C_tag (FALSE
); /* a yacc function */
3709 if (definedef
!= dnone
)
3715 make_C_tag (TRUE
); /* an Objective C class */
3719 objdef
= omethodcolon
;
3720 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3721 strcat (token_name
.buffer
, ":");
3724 if (structdef
== stagseen
)
3726 structdef
= scolonseen
;
3729 /* Should be useless, but may be work as a safety net. */
3730 if (cplpl
&& fvdef
== flistseen
)
3732 make_C_tag (TRUE
); /* a function */
3738 if (definedef
!= dnone
|| inattribute
)
3744 make_C_tag (FALSE
); /* a typedef */
3754 if (typdef
== tignore
|| cplpl
)
3758 if ((globals
&& bracelev
== 0 && (!fvextern
|| declarations
))
3759 || (members
&& instruct
))
3760 make_C_tag (FALSE
); /* a variable */
3763 token
.valid
= FALSE
;
3767 && (cplpl
|| !instruct
)
3768 && (typdef
== tnone
|| (typdef
!= tignore
&& instruct
)))
3770 && plainc
&& instruct
))
3771 make_C_tag (TRUE
); /* a function */
3777 && cplpl
&& structdef
== stagseen
)
3778 make_C_tag (FALSE
); /* forward declaration */
3780 token
.valid
= FALSE
;
3781 } /* switch (fvdef) */
3787 if (structdef
== stagseen
)
3791 if (definedef
!= dnone
|| inattribute
)
3797 make_C_tag (TRUE
); /* an Objective C method */
3818 && (!fvextern
|| declarations
))
3819 || (members
&& instruct
)))
3820 make_C_tag (FALSE
); /* a variable */
3823 if ((declarations
&& typdef
== tnone
&& !instruct
)
3824 || (members
&& typdef
!= tignore
&& instruct
))
3826 make_C_tag (TRUE
); /* a function */
3829 else if (!declarations
)
3831 token
.valid
= FALSE
;
3836 if (structdef
== stagseen
)
3840 if (definedef
!= dnone
|| inattribute
)
3842 if (structdef
== stagseen
)
3849 make_C_tag (FALSE
); /* a typedef */
3861 if ((members
&& bracelev
== 1)
3862 || (globals
&& bracelev
== 0
3863 && (!fvextern
|| declarations
)))
3864 make_C_tag (FALSE
); /* a variable */
3878 if (definedef
!= dnone
)
3880 if (objdef
== otagseen
&& parlev
== 0)
3881 objdef
= oparenseen
;
3885 if (typdef
== ttypeseen
3889 /* This handles constructs like:
3890 typedef void OperatorFun (int fun); */
3909 if (--attrparlev
== 0)
3910 inattribute
= FALSE
;
3913 if (definedef
!= dnone
)
3915 if (objdef
== ocatseen
&& parlev
== 1)
3917 make_C_tag (TRUE
); /* an Objective C category */
3931 || typdef
== ttypeseen
))
3934 make_C_tag (FALSE
); /* a typedef */
3937 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3941 if (definedef
!= dnone
)
3943 if (typdef
== ttypeseen
)
3945 /* Whenever typdef is set to tinbody (currently only
3946 here), typdefbracelev should be set to bracelev. */
3948 typdefbracelev
= bracelev
;
3953 make_C_tag (TRUE
); /* a function */
3962 make_C_tag (TRUE
); /* an Objective C class */
3967 make_C_tag (TRUE
); /* an Objective C method */
3971 /* Neutralize `extern "C" {' grot. */
3972 if (bracelev
== 0 && structdef
== snone
&& nestlev
== 0
3980 case skeyseen
: /* unnamed struct */
3981 pushclass_above (bracelev
, NULL
, 0);
3984 case stagseen
: /* named struct or enum */
3985 case scolonseen
: /* a class */
3986 pushclass_above (bracelev
,token
.line
+token
.offset
, token
.length
);
3988 make_C_tag (FALSE
); /* a struct or enum */
3994 if (definedef
!= dnone
)
3996 if (fvdef
== fstartlist
)
3998 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3999 token
.valid
= FALSE
;
4003 if (definedef
!= dnone
)
4006 if (!ignoreindent
&& lp
== newlb
.buffer
+ 1)
4009 token
.valid
= FALSE
; /* unexpected value, token unreliable */
4010 bracelev
= 0; /* reset brace level if first column */
4011 parlev
= 0; /* also reset paren level, just in case... */
4013 else if (bracelev
< 0)
4015 token
.valid
= FALSE
; /* something gone amiss, token unreliable */
4018 if (bracelev
== 0 && fvdef
== vignore
)
4019 fvdef
= fvnone
; /* end of function */
4020 popclass_above (bracelev
);
4022 /* Only if typdef == tinbody is typdefbracelev significant. */
4023 if (typdef
== tinbody
&& bracelev
<= typdefbracelev
)
4025 assert (bracelev
== typdefbracelev
);
4030 if (definedef
!= dnone
)
4040 if ((members
&& bracelev
== 1)
4041 || (globals
&& bracelev
== 0 && (!fvextern
|| declarations
)))
4042 make_C_tag (FALSE
); /* a variable */
4050 && (structdef
== stagseen
|| fvdef
== fvnameseen
))
4057 if (templatelev
> 0)
4065 if (objdef
== oinbody
&& bracelev
== 0)
4067 objdef
= omethodsign
;
4072 case '#': case '~': case '&': case '%': case '/':
4073 case '|': case '^': case '!': case '.': case '?':
4074 if (definedef
!= dnone
)
4076 /* These surely cannot follow a function tag in C. */
4089 if (objdef
== otagseen
)
4091 make_C_tag (TRUE
); /* an Objective C class */
4094 /* If a macro spans multiple lines don't reset its state. */
4096 CNL_SAVE_DEFINEDEF ();
4102 } /* while not eof */
4104 free (lbs
[0].lb
.buffer
);
4105 free (lbs
[1].lb
.buffer
);
4109 * Process either a C++ file or a C file depending on the setting
4113 default_C_entries (inf
)
4116 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
4119 /* Always do plain C. */
4121 plain_C_entries (inf
)
4127 /* Always do C++. */
4129 Cplusplus_entries (inf
)
4132 C_entries (C_PLPL
, inf
);
4135 /* Always do Java. */
4140 C_entries (C_JAVA
, inf
);
4148 C_entries (C_STAR
, inf
);
4151 /* Always do Yacc. */
4156 C_entries (YACC
, inf
);
4160 /* Useful macros. */
4161 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
4162 for (; /* loop initialization */ \
4163 !feof (file_pointer) /* loop test */ \
4164 && /* instructions at start of loop */ \
4165 (readline (&line_buffer, file_pointer), \
4166 char_pointer = line_buffer.buffer, \
4170 #define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \
4171 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \
4172 && strneq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4173 && notinname ((cp)[sizeof(kw)-1]) /* end of kw */ \
4174 && ((cp) = skip_spaces((cp)+sizeof(kw)-1))) /* skip spaces */
4176 /* Similar to LOOKING_AT but does not use notinname, does not skip */
4177 #define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */ \
4178 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \
4179 && strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4180 && ((cp) += sizeof(kw)-1)) /* skip spaces */
4183 * Read a file, but do no processing. This is used to do regexp
4184 * matching on files that have no language defined.
4187 just_read_file (inf
)
4190 register char *dummy
;
4192 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
4197 /* Fortran parsing */
4199 static void F_takeprec
__P((void));
4200 static void F_getit
__P((FILE *));
4205 dbp
= skip_spaces (dbp
);
4209 dbp
= skip_spaces (dbp
);
4210 if (strneq (dbp
, "(*)", 3))
4215 if (!ISDIGIT (*dbp
))
4217 --dbp
; /* force failure */
4222 while (ISDIGIT (*dbp
));
4231 dbp
= skip_spaces (dbp
);
4234 readline (&lb
, inf
);
4239 dbp
= skip_spaces (dbp
);
4241 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
4243 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
4245 make_tag (dbp
, cp
-dbp
, TRUE
,
4246 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4251 Fortran_functions (inf
)
4254 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4257 dbp
++; /* Ratfor escape to fortran */
4258 dbp
= skip_spaces (dbp
);
4261 switch (lowcase (*dbp
))
4264 if (nocase_tail ("integer"))
4268 if (nocase_tail ("real"))
4272 if (nocase_tail ("logical"))
4276 if (nocase_tail ("complex") || nocase_tail ("character"))
4280 if (nocase_tail ("double"))
4282 dbp
= skip_spaces (dbp
);
4285 if (nocase_tail ("precision"))
4291 dbp
= skip_spaces (dbp
);
4294 switch (lowcase (*dbp
))
4297 if (nocase_tail ("function"))
4301 if (nocase_tail ("subroutine"))
4305 if (nocase_tail ("entry"))
4309 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
4311 dbp
= skip_spaces (dbp
);
4312 if (*dbp
== '\0') /* assume un-named */
4313 make_tag ("blockdata", 9, TRUE
,
4314 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
4316 F_getit (inf
); /* look for name */
4327 * Philippe Waroquiers (1998)
4330 static void Ada_getit
__P((FILE *, char *));
4332 /* Once we are positioned after an "interesting" keyword, let's get
4333 the real tag value necessary. */
4335 Ada_getit (inf
, name_qualifier
)
4337 char *name_qualifier
;
4345 dbp
= skip_spaces (dbp
);
4347 || (dbp
[0] == '-' && dbp
[1] == '-'))
4349 readline (&lb
, inf
);
4352 switch (lowcase(*dbp
))
4355 if (nocase_tail ("body"))
4357 /* Skipping body of procedure body or package body or ....
4358 resetting qualifier to body instead of spec. */
4359 name_qualifier
= "/b";
4364 /* Skipping type of task type or protected type ... */
4365 if (nocase_tail ("type"))
4372 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4377 dbp
= skip_spaces (dbp
);
4380 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4388 name
= concat (dbp
, name_qualifier
, "");
4390 make_tag (name
, strlen (name
), TRUE
,
4391 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4403 bool inquote
= FALSE
;
4404 bool skip_till_semicolumn
= FALSE
;
4406 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4408 while (*dbp
!= '\0')
4410 /* Skip a string i.e. "abcd". */
4411 if (inquote
|| (*dbp
== '"'))
4413 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4418 continue; /* advance char */
4423 break; /* advance line */
4427 /* Skip comments. */
4428 if (dbp
[0] == '-' && dbp
[1] == '-')
4429 break; /* advance line */
4431 /* Skip character enclosed in single quote i.e. 'a'
4432 and skip single quote starting an attribute i.e. 'Image. */
4441 if (skip_till_semicolumn
)
4444 skip_till_semicolumn
= FALSE
;
4446 continue; /* advance char */
4449 /* Search for beginning of a token. */
4450 if (!begtoken (*dbp
))
4453 continue; /* advance char */
4456 /* We are at the beginning of a token. */
4457 switch (lowcase(*dbp
))
4460 if (!packages_only
&& nocase_tail ("function"))
4461 Ada_getit (inf
, "/f");
4463 break; /* from switch */
4464 continue; /* advance char */
4466 if (!packages_only
&& nocase_tail ("procedure"))
4467 Ada_getit (inf
, "/p");
4468 else if (nocase_tail ("package"))
4469 Ada_getit (inf
, "/s");
4470 else if (nocase_tail ("protected")) /* protected type */
4471 Ada_getit (inf
, "/t");
4473 break; /* from switch */
4474 continue; /* advance char */
4477 if (typedefs
&& !packages_only
&& nocase_tail ("use"))
4479 /* when tagging types, avoid tagging use type Pack.Typename;
4480 for this, we will skip everything till a ; */
4481 skip_till_semicolumn
= TRUE
;
4482 continue; /* advance char */
4486 if (!packages_only
&& nocase_tail ("task"))
4487 Ada_getit (inf
, "/k");
4488 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4490 Ada_getit (inf
, "/t");
4491 while (*dbp
!= '\0')
4495 break; /* from switch */
4496 continue; /* advance char */
4499 /* Look for the end of the token. */
4500 while (!endtoken (*dbp
))
4503 } /* advance char */
4504 } /* advance line */
4509 * Unix and microcontroller assembly tag handling
4510 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4511 * Idea by Bob Weiner, Motorola Inc. (1994)
4519 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4521 /* If first char is alphabetic or one of [_.$], test for colon
4522 following identifier. */
4523 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4525 /* Read past label. */
4527 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4529 if (*cp
== ':' || iswhite (*cp
))
4530 /* Found end of label, so copy it and add it to the table. */
4531 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4532 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4540 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4541 * Perl variable names: /^(my|local).../
4542 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4543 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4544 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4547 Perl_functions (inf
)
4550 char *package
= savestr ("main"); /* current package name */
4553 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4555 cp
= skip_spaces (cp
);
4557 if (LOOKING_AT (cp
, "package"))
4560 get_tag (cp
, &package
);
4562 else if (LOOKING_AT (cp
, "sub"))
4567 while (!notinname (*cp
))
4570 continue; /* nothing found */
4571 if ((pos
= etags_strchr (sp
, ':')) != NULL
4572 && pos
< cp
&& pos
[1] == ':')
4573 /* The name is already qualified. */
4574 make_tag (sp
, cp
- sp
, TRUE
,
4575 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4579 char savechar
, *name
;
4583 name
= concat (package
, "::", sp
);
4585 make_tag (name
, strlen(name
), TRUE
,
4586 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4590 else if (globals
) /* only if we are tagging global vars */
4592 /* Skip a qualifier, if any. */
4593 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4594 /* After "my" or "local", but before any following paren or space. */
4595 char *varstart
= cp
;
4597 if (qual
/* should this be removed? If yes, how? */
4598 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4603 while (ISALNUM (*cp
) || *cp
== '_');
4607 /* Should be examining a variable list at this point;
4608 could insist on seeing an open parenthesis. */
4609 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4615 make_tag (varstart
, cp
- varstart
, FALSE
,
4616 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4625 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4626 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4627 * More ideas by seb bacon <seb@jamkit.com> (2002)
4630 Python_functions (inf
)
4635 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4637 cp
= skip_spaces (cp
);
4638 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4641 while (!notinname (*cp
) && *cp
!= ':')
4643 make_tag (name
, cp
- name
, TRUE
,
4644 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4653 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4654 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4655 * - /^[ \t]*define\(\"[^\"]+/
4656 * Only with --members:
4657 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4658 * Idea by Diez B. Roggisch (2001)
4664 register char *cp
, *name
;
4665 bool search_identifier
= FALSE
;
4667 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4669 cp
= skip_spaces (cp
);
4671 if (search_identifier
4674 while (!notinname (*cp
))
4676 make_tag (name
, cp
- name
, TRUE
,
4677 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4678 search_identifier
= FALSE
;
4680 else if (LOOKING_AT (cp
, "function"))
4683 cp
= skip_spaces (cp
+1);
4687 while (!notinname (*cp
))
4689 make_tag (name
, cp
- name
, TRUE
,
4690 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4693 search_identifier
= TRUE
;
4695 else if (LOOKING_AT (cp
, "class"))
4700 while (*cp
!= '\0' && !iswhite (*cp
))
4702 make_tag (name
, cp
- name
, FALSE
,
4703 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4706 search_identifier
= TRUE
;
4708 else if (strneq (cp
, "define", 6)
4709 && (cp
= skip_spaces (cp
+6))
4711 && (*cp
== '"' || *cp
== '\''))
4715 while (*cp
!= quote
&& *cp
!= '\0')
4717 make_tag (name
, cp
- name
, FALSE
,
4718 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4721 && LOOKING_AT (cp
, "var")
4725 while (!notinname(*cp
))
4727 make_tag (name
, cp
- name
, FALSE
,
4728 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4735 * Cobol tag functions
4736 * We could look for anything that could be a paragraph name.
4737 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4738 * Idea by Corny de Souza (1993)
4741 Cobol_paragraphs (inf
)
4744 register char *bp
, *ep
;
4746 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4752 /* If eoln, compiler option or comment ignore whole line. */
4753 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4756 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4759 make_tag (bp
, ep
- bp
, TRUE
,
4760 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4767 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4770 Makefile_targets (inf
)
4775 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4777 if (*bp
== '\t' || *bp
== '#')
4779 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4781 if (*bp
== ':' || (globals
&& *bp
== '='))
4783 /* We should detect if there is more than one tag, but we do not.
4784 We just skip initial and final spaces. */
4785 char * namestart
= skip_spaces (lb
.buffer
);
4786 while (--bp
> namestart
)
4787 if (!notinname (*bp
))
4789 make_tag (namestart
, bp
- namestart
+ 1, TRUE
,
4790 lb
.buffer
, bp
- lb
.buffer
+ 2, lineno
, linecharno
);
4798 * Original code by Mosur K. Mohan (1989)
4800 * Locates tags for procedures & functions. Doesn't do any type- or
4801 * var-definitions. It does look for the keyword "extern" or
4802 * "forward" immediately following the procedure statement; if found,
4803 * the tag is skipped.
4806 Pascal_functions (inf
)
4809 linebuffer tline
; /* mostly copied from C_entries */
4811 int save_lineno
, namelen
, taglen
;
4814 bool /* each of these flags is TRUE if: */
4815 incomment
, /* point is inside a comment */
4816 inquote
, /* point is inside '..' string */
4817 get_tagname
, /* point is after PROCEDURE/FUNCTION
4818 keyword, so next item = potential tag */
4819 found_tag
, /* point is after a potential tag */
4820 inparms
, /* point is within parameter-list */
4821 verify_tag
; /* point has passed the parm-list, so the
4822 next token will determine whether this
4823 is a FORWARD/EXTERN to be ignored, or
4824 whether it is a real tag */
4826 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4827 name
= NULL
; /* keep compiler quiet */
4830 linebuffer_init (&tline
);
4832 incomment
= inquote
= FALSE
;
4833 found_tag
= FALSE
; /* have a proc name; check if extern */
4834 get_tagname
= FALSE
; /* found "procedure" keyword */
4835 inparms
= FALSE
; /* found '(' after "proc" */
4836 verify_tag
= FALSE
; /* check if "extern" is ahead */
4839 while (!feof (inf
)) /* long main loop to get next char */
4842 if (c
== '\0') /* if end of line */
4844 readline (&lb
, inf
);
4848 if (!((found_tag
&& verify_tag
)
4850 c
= *dbp
++; /* only if don't need *dbp pointing
4851 to the beginning of the name of
4852 the procedure or function */
4856 if (c
== '}') /* within { } comments */
4858 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4875 inquote
= TRUE
; /* found first quote */
4877 case '{': /* found open { comment */
4881 if (*dbp
== '*') /* found open (* comment */
4886 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4889 case ')': /* end of parms list */
4894 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4901 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4903 /* Check if this is an "extern" declaration. */
4906 if (lowcase (*dbp
== 'e'))
4908 if (nocase_tail ("extern")) /* superfluous, really! */
4914 else if (lowcase (*dbp
) == 'f')
4916 if (nocase_tail ("forward")) /* check for forward reference */
4922 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4926 make_tag (name
, namelen
, TRUE
,
4927 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4931 if (get_tagname
) /* grab name of proc or fn */
4938 /* Find block name. */
4939 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4942 /* Save all values for later tagging. */
4943 linebuffer_setlen (&tline
, lb
.len
);
4944 strcpy (tline
.buffer
, lb
.buffer
);
4945 save_lineno
= lineno
;
4946 save_lcno
= linecharno
;
4947 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4949 taglen
= cp
- lb
.buffer
+ 1;
4951 dbp
= cp
; /* set dbp to e-o-token */
4952 get_tagname
= FALSE
;
4956 /* And proceed to check for "extern". */
4958 else if (!incomment
&& !inquote
&& !found_tag
)
4960 /* Check for proc/fn keywords. */
4961 switch (lowcase (c
))
4964 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4968 if (nocase_tail ("unction"))
4973 } /* while not eof */
4975 free (tline
.buffer
);
4980 * Lisp tag functions
4981 * look for (def or (DEF, quote or QUOTE
4984 static void L_getit
__P((void));
4989 if (*dbp
== '\'') /* Skip prefix quote */
4991 else if (*dbp
== '(')
4994 /* Try to skip "(quote " */
4995 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4996 /* Ok, then skip "(" before name in (defstruct (foo)) */
4997 dbp
= skip_spaces (dbp
);
4999 get_tag (dbp
, NULL
);
5003 Lisp_functions (inf
)
5006 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5011 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
5013 dbp
= skip_non_spaces (dbp
);
5014 dbp
= skip_spaces (dbp
);
5019 /* Check for (foo::defmumble name-defined ... */
5022 while (!notinname (*dbp
) && *dbp
!= ':');
5027 while (*dbp
== ':');
5029 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
5031 dbp
= skip_non_spaces (dbp
);
5032 dbp
= skip_spaces (dbp
);
5042 * Lua script language parsing
5043 * Original code by David A. Capello <dacap@users.sourceforge.net> (2004)
5045 * "function" and "local function" are tags if they start at column 1.
5053 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5055 if (bp
[0] != 'f' && bp
[0] != 'l')
5058 (void)LOOKING_AT (bp
, "local"); /* skip possible "local" */
5060 if (LOOKING_AT (bp
, "function"))
5068 * Just look for lines where the first character is '/'
5069 * Also look at "defineps" for PSWrap
5071 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
5072 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
5078 register char *bp
, *ep
;
5080 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5085 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
5088 make_tag (bp
, ep
- bp
, TRUE
,
5089 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
5091 else if (LOOKING_AT (bp
, "defineps"))
5099 * Ignore anything after \ followed by space or in ( )
5100 * Look for words defined by :
5101 * Look for constant, code, create, defer, value, and variable
5102 * OBP extensions: Look for buffer:, field,
5103 * Ideas by Eduardo Horvath <eeh@netbsd.org> (2004)
5111 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5112 while ((bp
= skip_spaces (bp
))[0] != '\0')
5113 if (bp
[0] == '\\' && iswhite(bp
[1]))
5114 break; /* read next line */
5115 else if (bp
[0] == '(' && iswhite(bp
[1]))
5116 do /* skip to ) or eol */
5118 while (*bp
!= ')' && *bp
!= '\0');
5119 else if ((bp
[0] == ':' && iswhite(bp
[1]) && bp
++)
5120 || LOOKING_AT_NOCASE (bp
, "constant")
5121 || LOOKING_AT_NOCASE (bp
, "code")
5122 || LOOKING_AT_NOCASE (bp
, "create")
5123 || LOOKING_AT_NOCASE (bp
, "defer")
5124 || LOOKING_AT_NOCASE (bp
, "value")
5125 || LOOKING_AT_NOCASE (bp
, "variable")
5126 || LOOKING_AT_NOCASE (bp
, "buffer:")
5127 || LOOKING_AT_NOCASE (bp
, "field"))
5128 get_tag (skip_spaces (bp
), NULL
); /* Yay! A definition! */
5130 bp
= skip_non_spaces (bp
);
5135 * Scheme tag functions
5136 * look for (def... xyzzy
5138 * (def ... ((...(xyzzy ....
5140 * Original code by Ken Haase (1985?)
5143 Scheme_functions (inf
)
5148 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5150 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
5152 bp
= skip_non_spaces (bp
+4);
5153 /* Skip over open parens and white space */
5154 while (notinname (*bp
))
5158 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
5164 /* Find tags in TeX and LaTeX input files. */
5166 /* TEX_toktab is a table of TeX control sequences that define tags.
5167 * Each entry records one such control sequence.
5169 * Original code from who knows whom.
5171 * Stefan Monnier (2002)
5174 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
5176 /* Default set of control sequences to put into TEX_toktab.
5177 The value of environment var TEXTAGS is prepended to this. */
5178 static char *TEX_defenv
= "\
5179 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
5180 :part:appendix:entry:index:def\
5181 :newcommand:renewcommand:newenvironment:renewenvironment";
5183 static void TEX_mode
__P((FILE *));
5184 static void TEX_decode_env
__P((char *, char *));
5186 static char TEX_esc
= '\\';
5187 static char TEX_opgrp
= '{';
5188 static char TEX_clgrp
= '}';
5191 * TeX/LaTeX scanning loop.
5200 /* Select either \ or ! as escape character. */
5203 /* Initialize token table once from environment. */
5204 if (TEX_toktab
== NULL
)
5205 TEX_decode_env ("TEXTAGS", TEX_defenv
);
5207 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5209 /* Look at each TEX keyword in line. */
5212 /* Look for a TEX escape. */
5213 while (*cp
++ != TEX_esc
)
5214 if (cp
[-1] == '\0' || cp
[-1] == '%')
5217 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
5218 if (strneq (cp
, key
->buffer
, key
->len
))
5221 int namelen
, linelen
;
5224 cp
= skip_spaces (cp
+ key
->len
);
5225 if (*cp
== TEX_opgrp
)
5231 (!iswhite (*p
) && *p
!= '#' &&
5232 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
5237 if (!opgrp
|| *p
== TEX_clgrp
)
5239 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
5241 linelen
= p
- lb
.buffer
+ 1;
5243 make_tag (cp
, namelen
, TRUE
,
5244 lb
.buffer
, linelen
, lineno
, linecharno
);
5245 goto tex_next_line
; /* We only tag a line once */
5253 #define TEX_LESC '\\'
5254 #define TEX_SESC '!'
5256 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
5257 chars accordingly. */
5264 while ((c
= getc (inf
)) != EOF
)
5266 /* Skip to next line if we hit the TeX comment char. */
5268 while (c
!= '\n' && c
!= EOF
)
5270 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
5286 /* If the input file is compressed, inf is a pipe, and rewind may fail.
5287 No attempt is made to correct the situation. */
5291 /* Read environment and prepend it to the default string.
5292 Build token table. */
5294 TEX_decode_env (evarname
, defenv
)
5298 register char *env
, *p
;
5301 /* Append default string to environment. */
5302 env
= getenv (evarname
);
5308 env
= concat (oldenv
, defenv
, "");
5311 /* Allocate a token table */
5312 for (len
= 1, p
= env
; p
;)
5313 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
5315 TEX_toktab
= xnew (len
, linebuffer
);
5317 /* Unpack environment string into token table. Be careful about */
5318 /* zero-length strings (leading ':', "::" and trailing ':') */
5319 for (i
= 0; *env
!= '\0';)
5321 p
= etags_strchr (env
, ':');
5322 if (!p
) /* End of environment string. */
5323 p
= env
+ strlen (env
);
5325 { /* Only non-zero strings. */
5326 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
5327 TEX_toktab
[i
].len
= p
- env
;
5334 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
5335 TEX_toktab
[i
].len
= 0;
5342 /* Texinfo support. Dave Love, Mar. 2000. */
5348 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5349 if (LOOKING_AT (cp
, "@node"))
5352 while (*cp
!= '\0' && *cp
!= ',')
5354 make_tag (start
, cp
- start
, TRUE
,
5355 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5362 * Contents of <title>, <h1>, <h2>, <h3> are tags.
5363 * Contents of <a name=xxx> are tags with name xxx.
5365 * Francesco Potortì, 2002.
5371 bool getnext
= FALSE
; /* next text outside of HTML tags is a tag */
5372 bool skiptag
= FALSE
; /* skip to the end of the current HTML tag */
5373 bool intag
= FALSE
; /* inside an html tag, looking for ID= */
5374 bool inanchor
= FALSE
; /* when INTAG, is an anchor, look for NAME= */
5378 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5380 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5381 for (;;) /* loop on the same line */
5383 if (skiptag
) /* skip HTML tag */
5385 while (*dbp
!= '\0' && *dbp
!= '>')
5391 continue; /* look on the same line */
5393 break; /* go to next line */
5396 else if (intag
) /* look for "name=" or "id=" */
5398 while (*dbp
!= '\0' && *dbp
!= '>'
5399 && lowcase (*dbp
) != 'n' && lowcase (*dbp
) != 'i')
5402 break; /* go to next line */
5407 continue; /* look on the same line */
5409 if ((inanchor
&& LOOKING_AT_NOCASE (dbp
, "name="))
5410 || LOOKING_AT_NOCASE (dbp
, "id="))
5412 bool quoted
= (dbp
[0] == '"');
5415 for (end
= ++dbp
; *end
!= '\0' && *end
!= '"'; end
++)
5418 for (end
= dbp
; *end
!= '\0' && intoken (*end
); end
++)
5420 linebuffer_setlen (&token_name
, end
- dbp
);
5421 strncpy (token_name
.buffer
, dbp
, end
- dbp
);
5422 token_name
.buffer
[end
- dbp
] = '\0';
5425 intag
= FALSE
; /* we found what we looked for */
5426 skiptag
= TRUE
; /* skip to the end of the tag */
5427 getnext
= TRUE
; /* then grab the text */
5428 continue; /* look on the same line */
5433 else if (getnext
) /* grab next tokens and tag them */
5435 dbp
= skip_spaces (dbp
);
5437 break; /* go to next line */
5441 inanchor
= (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]));
5442 continue; /* look on the same line */
5445 for (end
= dbp
+ 1; *end
!= '\0' && *end
!= '<'; end
++)
5447 make_tag (token_name
.buffer
, token_name
.len
, TRUE
,
5448 dbp
, end
- dbp
, lineno
, linecharno
);
5449 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5451 break; /* go to next line */
5454 else /* look for an interesting HTML tag */
5456 while (*dbp
!= '\0' && *dbp
!= '<')
5459 break; /* go to next line */
5461 if (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]))
5464 continue; /* look on the same line */
5466 else if (LOOKING_AT_NOCASE (dbp
, "<title>")
5467 || LOOKING_AT_NOCASE (dbp
, "<h1>")
5468 || LOOKING_AT_NOCASE (dbp
, "<h2>")
5469 || LOOKING_AT_NOCASE (dbp
, "<h3>"))
5473 continue; /* look on the same line */
5484 * Assumes that the predicate or rule starts at column 0.
5485 * Only the first clause of a predicate or rule is added.
5486 * Original code by Sunichirou Sugou (1989)
5487 * Rewritten by Anders Lindgren (1996)
5489 static int prolog_pr
__P((char *, char *));
5490 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
5491 static int prolog_atom
__P((char *, int));
5494 Prolog_functions (inf
)
5505 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5507 if (cp
[0] == '\0') /* Empty line */
5509 else if (iswhite (cp
[0])) /* Not a predicate */
5511 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
5512 prolog_skip_comment (&lb
, inf
);
5513 else if ((len
= prolog_pr (cp
, last
)) > 0)
5515 /* Predicate or rule. Store the function name so that we
5516 only generate a tag for the first clause. */
5518 last
= xnew(len
+ 1, char);
5519 else if (len
+ 1 > allocated
)
5520 xrnew (last
, len
+ 1, char);
5521 allocated
= len
+ 1;
5522 strncpy (last
, cp
, len
);
5532 prolog_skip_comment (plb
, inf
)
5540 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
5541 if (cp
[0] == '*' && cp
[1] == '/')
5543 readline (plb
, inf
);
5549 * A predicate or rule definition is added if it matches:
5550 * <beginning of line><Prolog Atom><whitespace>(
5551 * or <beginning of line><Prolog Atom><whitespace>:-
5553 * It is added to the tags database if it doesn't match the
5554 * name of the previous clause header.
5556 * Return the size of the name of the predicate or rule, or 0 if no
5562 char *last
; /* Name of last clause. */
5567 pos
= prolog_atom (s
, 0);
5572 pos
= skip_spaces (s
+ pos
) - s
;
5575 || (s
[pos
] == '(' && (pos
+= 1))
5576 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5577 && (last
== NULL
/* save only the first clause */
5578 || len
!= (int)strlen (last
)
5579 || !strneq (s
, last
, len
)))
5581 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5589 * Consume a Prolog atom.
5590 * Return the number of bytes consumed, or -1 if there was an error.
5592 * A prolog atom, in this context, could be one of:
5593 * - An alphanumeric sequence, starting with a lower case letter.
5594 * - A quoted arbitrary string. Single quotes can escape themselves.
5595 * Backslash quotes everything.
5598 prolog_atom (s
, pos
)
5606 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5608 /* The atom is unquoted. */
5610 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5614 return pos
- origpos
;
5616 else if (s
[pos
] == '\'')
5627 pos
++; /* A double quote */
5629 else if (s
[pos
] == '\0')
5630 /* Multiline quoted atoms are ignored. */
5632 else if (s
[pos
] == '\\')
5634 if (s
[pos
+1] == '\0')
5641 return pos
- origpos
;
5649 * Support for Erlang
5651 * Generates tags for functions, defines, and records.
5652 * Assumes that Erlang functions start at column 0.
5653 * Original code by Anders Lindgren (1996)
5655 static int erlang_func
__P((char *, char *));
5656 static void erlang_attribute
__P((char *));
5657 static int erlang_atom
__P((char *));
5660 Erlang_functions (inf
)
5671 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5673 if (cp
[0] == '\0') /* Empty line */
5675 else if (iswhite (cp
[0])) /* Not function nor attribute */
5677 else if (cp
[0] == '%') /* comment */
5679 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5681 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5683 erlang_attribute (cp
);
5690 else if ((len
= erlang_func (cp
, last
)) > 0)
5693 * Function. Store the function name so that we only
5694 * generates a tag for the first clause.
5697 last
= xnew (len
+ 1, char);
5698 else if (len
+ 1 > allocated
)
5699 xrnew (last
, len
+ 1, char);
5700 allocated
= len
+ 1;
5701 strncpy (last
, cp
, len
);
5711 * A function definition is added if it matches:
5712 * <beginning of line><Erlang Atom><whitespace>(
5714 * It is added to the tags database if it doesn't match the
5715 * name of the previous clause header.
5717 * Return the size of the name of the function, or 0 if no function
5721 erlang_func (s
, last
)
5723 char *last
; /* Name of last clause. */
5728 pos
= erlang_atom (s
);
5733 pos
= skip_spaces (s
+ pos
) - s
;
5735 /* Save only the first clause. */
5738 || len
!= (int)strlen (last
)
5739 || !strneq (s
, last
, len
)))
5741 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5750 * Handle attributes. Currently, tags are generated for defines
5753 * They are on the form:
5754 * -define(foo, bar).
5755 * -define(Foo(M, N), M+N).
5756 * -record(graph, {vtab = notable, cyclic = true}).
5759 erlang_attribute (s
)
5764 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5767 int len
= erlang_atom (skip_spaces (cp
));
5769 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5776 * Consume an Erlang atom (or variable).
5777 * Return the number of bytes consumed, or -1 if there was an error.
5785 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5787 /* The atom is unquoted. */
5790 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5792 else if (s
[pos
] == '\'')
5794 for (pos
++; s
[pos
] != '\''; pos
++)
5795 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5796 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5805 static char *scan_separators
__P((char *));
5806 static void add_regex
__P((char *, language
*));
5807 static char *substitute
__P((char *, char *, struct re_registers
*));
5810 * Take a string like "/blah/" and turn it into "blah", verifying
5811 * that the first and last characters are the same, and handling
5812 * quoted separator characters. Actually, stops on the occurrence of
5813 * an unquoted separator. Also process \t, \n, etc. and turn into
5814 * appropriate characters. Works in place. Null terminates name string.
5815 * Returns pointer to terminating separator, or NULL for
5816 * unterminated regexps.
5819 scan_separators (name
)
5823 char *copyto
= name
;
5824 bool quoted
= FALSE
;
5826 for (++name
; *name
!= '\0'; ++name
)
5832 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5833 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5834 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5835 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5836 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5837 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5838 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5839 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5840 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5846 /* Something else is quoted, so preserve the quote. */
5854 else if (*name
== '\\')
5856 else if (*name
== sep
)
5862 name
= NULL
; /* signal unterminated regexp */
5864 /* Terminate copied string. */
5869 /* Look at the argument of --regex or --no-regex and do the right
5870 thing. Same for each line of a regexp file. */
5872 analyse_regex (regex_arg
)
5875 if (regex_arg
== NULL
)
5877 free_regexps (); /* --no-regex: remove existing regexps */
5881 /* A real --regexp option or a line in a regexp file. */
5882 switch (regex_arg
[0])
5884 /* Comments in regexp file or null arg to --regex. */
5890 /* Read a regex file. This is recursive and may result in a
5891 loop, which will stop when the file descriptors are exhausted. */
5895 linebuffer regexbuf
;
5896 char *regexfile
= regex_arg
+ 1;
5898 /* regexfile is a file containing regexps, one per line. */
5899 regexfp
= fopen (regexfile
, "r");
5900 if (regexfp
== NULL
)
5905 linebuffer_init (®exbuf
);
5906 while (readline_internal (®exbuf
, regexfp
) > 0)
5907 analyse_regex (regexbuf
.buffer
);
5908 free (regexbuf
.buffer
);
5913 /* Regexp to be used for a specific language only. */
5917 char *lang_name
= regex_arg
+ 1;
5920 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5923 error ("unterminated language name in regex: %s", regex_arg
);
5927 lang
= get_language_from_langname (lang_name
);
5930 add_regex (cp
, lang
);
5934 /* Regexp to be used for any language. */
5936 add_regex (regex_arg
, NULL
);
5941 /* Separate the regexp pattern, compile it,
5942 and care for optional name and modifiers. */
5944 add_regex (regexp_pattern
, lang
)
5945 char *regexp_pattern
;
5948 static struct re_pattern_buffer zeropattern
;
5949 char sep
, *pat
, *name
, *modifiers
;
5951 struct re_pattern_buffer
*patbuf
;
5954 force_explicit_name
= TRUE
, /* do not use implicit tag names */
5955 ignore_case
= FALSE
, /* case is significant */
5956 multi_line
= FALSE
, /* matches are done one line at a time */
5957 single_line
= FALSE
; /* dot does not match newline */
5960 if (strlen(regexp_pattern
) < 3)
5962 error ("null regexp", (char *)NULL
);
5965 sep
= regexp_pattern
[0];
5966 name
= scan_separators (regexp_pattern
);
5969 error ("%s: unterminated regexp", regexp_pattern
);
5974 error ("null name for regexp \"%s\"", regexp_pattern
);
5977 modifiers
= scan_separators (name
);
5978 if (modifiers
== NULL
) /* no terminating separator --> no name */
5984 modifiers
+= 1; /* skip separator */
5986 /* Parse regex modifiers. */
5987 for (; modifiers
[0] != '\0'; modifiers
++)
5988 switch (modifiers
[0])
5991 if (modifiers
== name
)
5992 error ("forcing explicit tag name but no name, ignoring", NULL
);
5993 force_explicit_name
= TRUE
;
6003 need_filebuf
= TRUE
;
6008 wrongmod
[0] = modifiers
[0];
6010 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
6015 patbuf
= xnew (1, struct re_pattern_buffer
);
6016 *patbuf
= zeropattern
;
6019 static char lc_trans
[CHARS
];
6021 for (i
= 0; i
< CHARS
; i
++)
6022 lc_trans
[i
] = lowcase (i
);
6023 patbuf
->translate
= lc_trans
; /* translation table to fold case */
6027 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
6029 pat
= regexp_pattern
;
6032 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
6034 re_set_syntax (RE_SYNTAX_EMACS
);
6036 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
6041 error ("%s while compiling pattern", err
);
6046 p_head
= xnew (1, regexp
);
6047 p_head
->pattern
= savestr (regexp_pattern
);
6048 p_head
->p_next
= rp
;
6049 p_head
->lang
= lang
;
6050 p_head
->pat
= patbuf
;
6051 p_head
->name
= savestr (name
);
6052 p_head
->error_signaled
= FALSE
;
6053 p_head
->force_explicit_name
= force_explicit_name
;
6054 p_head
->ignore_case
= ignore_case
;
6055 p_head
->multi_line
= multi_line
;
6059 * Do the substitutions indicated by the regular expression and
6063 substitute (in
, out
, regs
)
6065 struct re_registers
*regs
;
6068 int size
, dig
, diglen
;
6071 size
= strlen (out
);
6073 /* Pass 1: figure out how much to allocate by finding all \N strings. */
6074 if (out
[size
- 1] == '\\')
6075 fatal ("pattern error in \"%s\"", out
);
6076 for (t
= etags_strchr (out
, '\\');
6078 t
= etags_strchr (t
+ 2, '\\'))
6082 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
6088 /* Allocate space and do the substitutions. */
6090 result
= xnew (size
+ 1, char);
6092 for (t
= result
; *out
!= '\0'; out
++)
6093 if (*out
== '\\' && ISDIGIT (*++out
))
6096 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
6097 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
6104 assert (t
<= result
+ size
);
6105 assert (t
- result
== (int)strlen (result
));
6110 /* Deallocate all regexps. */
6115 while (p_head
!= NULL
)
6117 rp
= p_head
->p_next
;
6118 free (p_head
->pattern
);
6119 free (p_head
->name
);
6127 * Reads the whole file as a single string from `filebuf' and looks for
6128 * multi-line regular expressions, creating tags on matches.
6129 * readline already dealt with normal regexps.
6131 * Idea by Ben Wing <ben@666.com> (2002).
6134 regex_tag_multiline ()
6136 char *buffer
= filebuf
.buffer
;
6140 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6144 if (!rp
->multi_line
)
6145 continue; /* skip normal regexps */
6147 /* Generic initialisations before parsing file from memory. */
6148 lineno
= 1; /* reset global line number */
6149 charno
= 0; /* reset global char number */
6150 linecharno
= 0; /* reset global char number of line start */
6152 /* Only use generic regexps or those for the current language. */
6153 if (rp
->lang
!= NULL
&& rp
->lang
!= curfdp
->lang
)
6156 while (match
>= 0 && match
< filebuf
.len
)
6158 match
= re_search (rp
->pat
, buffer
, filebuf
.len
, charno
,
6159 filebuf
.len
- match
, &rp
->regs
);
6164 if (!rp
->error_signaled
)
6166 error ("regexp stack overflow while matching \"%s\"",
6168 rp
->error_signaled
= TRUE
;
6175 if (match
== rp
->regs
.end
[0])
6177 if (!rp
->error_signaled
)
6179 error ("regexp matches the empty string: \"%s\"",
6181 rp
->error_signaled
= TRUE
;
6183 match
= -3; /* exit from while loop */
6187 /* Match occurred. Construct a tag. */
6188 while (charno
< rp
->regs
.end
[0])
6189 if (buffer
[charno
++] == '\n')
6190 lineno
++, linecharno
= charno
;
6192 if (name
[0] == '\0')
6194 else /* make a named tag */
6195 name
= substitute (buffer
, rp
->name
, &rp
->regs
);
6196 if (rp
->force_explicit_name
)
6197 /* Force explicit tag name, if a name is there. */
6198 pfnote (name
, TRUE
, buffer
+ linecharno
,
6199 charno
- linecharno
+ 1, lineno
, linecharno
);
6201 make_tag (name
, strlen (name
), TRUE
, buffer
+ linecharno
,
6202 charno
- linecharno
+ 1, lineno
, linecharno
);
6214 register int len
= 0;
6216 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
6218 if (*cp
== '\0' && !intoken (dbp
[len
]))
6227 get_tag (bp
, namepp
)
6231 register char *cp
= bp
;
6235 /* Go till you get to white space or a syntactic break */
6236 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
6238 make_tag (bp
, cp
- bp
, TRUE
,
6239 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
6243 *namepp
= savenstr (bp
, cp
- bp
);
6247 * Read a line of text from `stream' into `lbp', excluding the
6248 * newline or CR-NL, if any. Return the number of characters read from
6249 * `stream', which is the length of the line including the newline.
6251 * On DOS or Windows we do not count the CR character, if any before the
6252 * NL, in the returned length; this mirrors the behavior of Emacs on those
6253 * platforms (for text files, it translates CR-NL to NL as it reads in the
6256 * If multi-line regular expressions are requested, each line read is
6257 * appended to `filebuf'.
6260 readline_internal (lbp
, stream
)
6262 register FILE *stream
;
6264 char *buffer
= lbp
->buffer
;
6265 register char *p
= lbp
->buffer
;
6266 register char *pend
;
6269 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
6273 register int c
= getc (stream
);
6276 /* We're at the end of linebuffer: expand it. */
6278 xrnew (buffer
, lbp
->size
, char);
6279 p
+= buffer
- lbp
->buffer
;
6280 pend
= buffer
+ lbp
->size
;
6281 lbp
->buffer
= buffer
;
6291 if (p
> buffer
&& p
[-1] == '\r')
6295 /* Assume CRLF->LF translation will be performed by Emacs
6296 when loading this file, so CRs won't appear in the buffer.
6297 It would be cleaner to compensate within Emacs;
6298 however, Emacs does not know how many CRs were deleted
6299 before any given point in the file. */
6314 lbp
->len
= p
- buffer
;
6316 if (need_filebuf
/* we need filebuf for multi-line regexps */
6317 && chars_deleted
> 0) /* not at EOF */
6319 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
6321 /* Expand filebuf. */
6323 xrnew (filebuf
.buffer
, filebuf
.size
, char);
6325 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
6326 filebuf
.len
+= lbp
->len
;
6327 filebuf
.buffer
[filebuf
.len
++] = '\n';
6328 filebuf
.buffer
[filebuf
.len
] = '\0';
6331 return lbp
->len
+ chars_deleted
;
6335 * Like readline_internal, above, but in addition try to match the
6336 * input line against relevant regular expressions and manage #line
6340 readline (lbp
, stream
)
6346 linecharno
= charno
; /* update global char number of line start */
6347 result
= readline_internal (lbp
, stream
); /* read line */
6348 lineno
+= 1; /* increment global line number */
6349 charno
+= result
; /* increment global char number */
6351 /* Honour #line directives. */
6352 if (!no_line_directive
)
6354 static bool discard_until_line_directive
;
6356 /* Check whether this is a #line directive. */
6357 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
6362 if (sscanf (lbp
->buffer
, "#line %u \"%n", &lno
, &start
) >= 1
6363 && start
> 0) /* double quote character found */
6365 char *endp
= lbp
->buffer
+ start
;
6367 while ((endp
= etags_strchr (endp
, '"')) != NULL
6368 && endp
[-1] == '\\')
6371 /* Ok, this is a real #line directive. Let's deal with it. */
6373 char *taggedabsname
; /* absolute name of original file */
6374 char *taggedfname
; /* name of original file as given */
6375 char *name
; /* temp var */
6377 discard_until_line_directive
= FALSE
; /* found it */
6378 name
= lbp
->buffer
+ start
;
6380 canonicalize_filename (name
); /* for DOS */
6381 taggedabsname
= absolute_filename (name
, tagfiledir
);
6382 if (filename_is_absolute (name
)
6383 || filename_is_absolute (curfdp
->infname
))
6384 taggedfname
= savestr (taggedabsname
);
6386 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
6388 if (streq (curfdp
->taggedfname
, taggedfname
))
6389 /* The #line directive is only a line number change. We
6390 deal with this afterwards. */
6393 /* The tags following this #line directive should be
6394 attributed to taggedfname. In order to do this, set
6395 curfdp accordingly. */
6397 fdesc
*fdp
; /* file description pointer */
6399 /* Go look for a file description already set up for the
6400 file indicated in the #line directive. If there is
6401 one, use it from now until the next #line
6403 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6404 if (streq (fdp
->infname
, curfdp
->infname
)
6405 && streq (fdp
->taggedfname
, taggedfname
))
6406 /* If we remove the second test above (after the &&)
6407 then all entries pertaining to the same file are
6408 coalesced in the tags file. If we use it, then
6409 entries pertaining to the same file but generated
6410 from different files (via #line directives) will
6411 go into separate sections in the tags file. These
6412 alternatives look equivalent. The first one
6413 destroys some apparently useless information. */
6419 /* Else, if we already tagged the real file, skip all
6420 input lines until the next #line directive. */
6421 if (fdp
== NULL
) /* not found */
6422 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6423 if (streq (fdp
->infabsname
, taggedabsname
))
6425 discard_until_line_directive
= TRUE
;
6429 /* Else create a new file description and use that from
6430 now on, until the next #line directive. */
6431 if (fdp
== NULL
) /* not found */
6434 fdhead
= xnew (1, fdesc
);
6435 *fdhead
= *curfdp
; /* copy curr. file description */
6437 fdhead
->infname
= savestr (curfdp
->infname
);
6438 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
6439 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
6440 fdhead
->taggedfname
= taggedfname
;
6441 fdhead
->usecharno
= FALSE
;
6442 fdhead
->prop
= NULL
;
6443 fdhead
->written
= FALSE
;
6447 free (taggedabsname
);
6449 readline (lbp
, stream
);
6451 } /* if a real #line directive */
6452 } /* if #line is followed by a a number */
6453 } /* if line begins with "#line " */
6455 /* If we are here, no #line directive was found. */
6456 if (discard_until_line_directive
)
6460 /* Do a tail recursion on ourselves, thus discarding the contents
6461 of the line buffer. */
6462 readline (lbp
, stream
);
6466 discard_until_line_directive
= FALSE
;
6469 } /* if #line directives should be considered */
6476 /* Match against relevant regexps. */
6478 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6480 /* Only use generic regexps or those for the current language.
6481 Also do not use multiline regexps, which is the job of
6482 regex_tag_multiline. */
6483 if ((rp
->lang
!= NULL
&& rp
->lang
!= fdhead
->lang
)
6487 match
= re_match (rp
->pat
, lbp
->buffer
, lbp
->len
, 0, &rp
->regs
);
6492 if (!rp
->error_signaled
)
6494 error ("regexp stack overflow while matching \"%s\"",
6496 rp
->error_signaled
= TRUE
;
6503 /* Empty string matched. */
6504 if (!rp
->error_signaled
)
6506 error ("regexp matches the empty string: \"%s\"", rp
->pattern
);
6507 rp
->error_signaled
= TRUE
;
6511 /* Match occurred. Construct a tag. */
6513 if (name
[0] == '\0')
6515 else /* make a named tag */
6516 name
= substitute (lbp
->buffer
, rp
->name
, &rp
->regs
);
6517 if (rp
->force_explicit_name
)
6518 /* Force explicit tag name, if a name is there. */
6519 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
6521 make_tag (name
, strlen (name
), TRUE
,
6522 lbp
->buffer
, match
, lineno
, linecharno
);
6531 * Return a pointer to a space of size strlen(cp)+1 allocated
6532 * with xnew where the string CP has been copied.
6538 return savenstr (cp
, strlen (cp
));
6542 * Return a pointer to a space of size LEN+1 allocated with xnew where
6543 * the string CP has been copied for at most the first LEN characters.
6552 dp
= xnew (len
+ 1, char);
6553 strncpy (dp
, cp
, len
);
6559 * Return the ptr in sp at which the character c last
6560 * appears; NULL if not found
6562 * Identical to POSIX strrchr, included for portability.
6565 etags_strrchr (sp
, c
)
6566 register const char *sp
;
6569 register const char *r
;
6581 * Return the ptr in sp at which the character c first
6582 * appears; NULL if not found
6584 * Identical to POSIX strchr, included for portability.
6587 etags_strchr (sp
, c
)
6588 register const char *sp
;
6600 * Compare two strings, ignoring case for alphabetic characters.
6602 * Same as BSD's strcasecmp, included for portability.
6605 etags_strcasecmp (s1
, s2
)
6606 register const char *s1
;
6607 register const char *s2
;
6610 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6611 ? lowcase (*s1
) == lowcase (*s2
)
6615 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6616 ? lowcase (*s1
) - lowcase (*s2
)
6621 * Compare two strings, ignoring case for alphabetic characters.
6622 * Stop after a given number of characters
6624 * Same as BSD's strncasecmp, included for portability.
6627 etags_strncasecmp (s1
, s2
, n
)
6628 register const char *s1
;
6629 register const char *s2
;
6632 while (*s1
!= '\0' && n
-- > 0
6633 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6634 ? lowcase (*s1
) == lowcase (*s2
)
6641 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6642 ? lowcase (*s1
) - lowcase (*s2
)
6646 /* Skip spaces (end of string is not space), return new pointer. */
6651 while (iswhite (*cp
))
6656 /* Skip non spaces, except end of string, return new pointer. */
6658 skip_non_spaces (cp
)
6661 while (*cp
!= '\0' && !iswhite (*cp
))
6666 /* Print error message and exit. */
6672 exit (EXIT_FAILURE
);
6680 exit (EXIT_FAILURE
);
6684 suggest_asking_for_help ()
6686 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6687 progname
, NO_LONG_OPTIONS
? "-h" : "--help");
6688 exit (EXIT_FAILURE
);
6691 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6694 const char *s1
, *s2
;
6696 fprintf (stderr
, "%s: ", progname
);
6697 fprintf (stderr
, s1
, s2
);
6698 fprintf (stderr
, "\n");
6701 /* Return a newly-allocated string whose contents
6702 concatenate those of s1, s2, s3. */
6707 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6708 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6710 strcpy (result
, s1
);
6711 strcpy (result
+ len1
, s2
);
6712 strcpy (result
+ len1
+ len2
, s3
);
6713 result
[len1
+ len2
+ len3
] = '\0';
6719 /* Does the same work as the system V getcwd, but does not need to
6720 guess the buffer size in advance. */
6726 char *path
= xnew (bufsize
, char);
6728 while (getcwd (path
, bufsize
) == NULL
)
6730 if (errno
!= ERANGE
)
6734 path
= xnew (bufsize
, char);
6737 canonicalize_filename (path
);
6740 #else /* not HAVE_GETCWD */
6743 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6747 for (p
= path
; *p
!= '\0'; p
++)
6753 return strdup (path
);
6754 #else /* not MSDOS */
6758 linebuffer_init (&path
);
6759 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6760 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6765 #endif /* not MSDOS */
6766 #endif /* not HAVE_GETCWD */
6769 /* Return a newly allocated string containing the file name of FILE
6770 relative to the absolute directory DIR (which should end with a slash). */
6772 relative_filename (file
, dir
)
6775 char *fp
, *dp
, *afn
, *res
;
6778 /* Find the common root of file and dir (with a trailing slash). */
6779 afn
= absolute_filename (file
, cwd
);
6782 while (*fp
++ == *dp
++)
6784 fp
--, dp
--; /* back to the first differing char */
6786 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6789 do /* look at the equal chars until '/' */
6793 /* Build a sequence of "../" strings for the resulting relative file name. */
6795 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6797 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6800 strcat (res
, "../");
6802 /* Add the file name relative to the common root of file and dir. */
6803 strcat (res
, fp
+ 1);
6809 /* Return a newly allocated string containing the absolute file name
6810 of FILE given DIR (which should end with a slash). */
6812 absolute_filename (file
, dir
)
6815 char *slashp
, *cp
, *res
;
6817 if (filename_is_absolute (file
))
6818 res
= savestr (file
);
6820 /* We don't support non-absolute file names with a drive
6821 letter, like `d:NAME' (it's too much hassle). */
6822 else if (file
[1] == ':')
6823 fatal ("%s: relative file names with drive letters not supported", file
);
6826 res
= concat (dir
, file
, "");
6828 /* Delete the "/dirname/.." and "/." substrings. */
6829 slashp
= etags_strchr (res
, '/');
6830 while (slashp
!= NULL
&& slashp
[0] != '\0')
6832 if (slashp
[1] == '.')
6834 if (slashp
[2] == '.'
6835 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6840 while (cp
>= res
&& !filename_is_absolute (cp
));
6842 cp
= slashp
; /* the absolute name begins with "/.." */
6844 /* Under MSDOS and NT we get `d:/NAME' as absolute
6845 file name, so the luser could say `d:/../NAME'.
6846 We silently treat this as `d:/NAME'. */
6847 else if (cp
[0] != '/')
6850 strcpy (cp
, slashp
+ 3);
6854 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6856 strcpy (slashp
, slashp
+ 2);
6861 slashp
= etags_strchr (slashp
+ 1, '/');
6864 if (res
[0] == '\0') /* just a safety net: should never happen */
6867 return savestr ("/");
6873 /* Return a newly allocated string containing the absolute
6874 file name of dir where FILE resides given DIR (which should
6875 end with a slash). */
6877 absolute_dirname (file
, dir
)
6883 canonicalize_filename (file
);
6884 slashp
= etags_strrchr (file
, '/');
6886 return savestr (dir
);
6889 res
= absolute_filename (file
, dir
);
6895 /* Whether the argument string is an absolute file name. The argument
6896 string must have been canonicalized with canonicalize_filename. */
6898 filename_is_absolute (fn
)
6901 return (fn
[0] == '/'
6903 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6908 /* Translate backslashes into slashes. Works in place. */
6910 canonicalize_filename (fn
)
6914 /* Canonicalize drive letter case. */
6915 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6916 fn
[0] = upcase (fn
[0]);
6917 /* Convert backslashes to slashes. */
6918 for (; *fn
!= '\0'; fn
++)
6923 fn
= NULL
; /* shut up the compiler */
6928 /* Initialize a linebuffer for use */
6930 linebuffer_init (lbp
)
6933 lbp
->size
= (DEBUG
) ? 3 : 200;
6934 lbp
->buffer
= xnew (lbp
->size
, char);
6935 lbp
->buffer
[0] = '\0';
6939 /* Set the minimum size of a string contained in a linebuffer. */
6941 linebuffer_setlen (lbp
, toksize
)
6945 while (lbp
->size
<= toksize
)
6948 xrnew (lbp
->buffer
, lbp
->size
, char);
6953 /* Like malloc but get fatal error if memory is exhausted. */
6958 PTR result
= (PTR
) malloc (size
);
6960 fatal ("virtual memory exhausted", (char *)NULL
);
6965 xrealloc (ptr
, size
)
6969 PTR result
= (PTR
) realloc (ptr
, size
);
6971 fatal ("virtual memory exhausted", (char *)NULL
);
6977 * indent-tabs-mode: t
6980 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")
6981 * c-file-style: "gnu"
6985 /* arch-tag: 8a9b748d-390c-4922-99db-2eeefa921051
6986 (do not change this comment) */
6988 /* etags.c ends here */