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
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 * Ctags originally by Ken Arnold.
65 * Fortran added by Jim Kleckner.
66 * Ed Pelegri-Llopart added C typedefs.
67 * Gnu Emacs TAGS format and modifications by RMS?
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.26";
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 ();
165 # define EXIT_SUCCESS 1
166 # define EXIT_FAILURE 0
168 # define EXIT_SUCCESS 0
169 # define EXIT_FAILURE 1
172 #endif /* !WINDOWSNT */
177 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
178 extern char *getcwd (char *buf
, size_t size
);
180 #endif /* HAVE_UNISTD_H */
188 #include <sys/types.h>
189 #include <sys/stat.h>
193 # undef assert /* some systems have a buggy assert.h */
194 # define assert(x) ((void) 0)
197 #if !defined (S_ISREG) && defined (S_IFREG)
198 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
201 #ifdef NO_LONG_OPTIONS /* define this if you don't have GNU getopt */
202 # define NO_LONG_OPTIONS TRUE
203 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
205 extern int optind
, opterr
;
207 # define NO_LONG_OPTIONS FALSE
209 #endif /* NO_LONG_OPTIONS */
211 #ifndef HAVE_CONFIG_H /* this is a standalone compilation */
212 # ifdef __CYGWIN__ /* compiling on Cygwin */
214 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
215 If you want regular expression support
, you should
delete this notice
and
216 arrange to use the GNU regex
.h
and regex
.c
.
221 /* Define CTAGS to make the program "ctags" compatible with the usual one.
222 Leave it undefined to make the program "etags", which makes emacs-style
223 tag tables and tags typedefs, #defines and struct/union/enum by default. */
231 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
232 #define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
233 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
234 #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
236 #define CHARS 256 /* 2^sizeof(char) */
237 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
238 #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
239 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
240 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
241 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
242 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
244 #define ISALNUM(c) isalnum (CHAR(c))
245 #define ISALPHA(c) isalpha (CHAR(c))
246 #define ISDIGIT(c) isdigit (CHAR(c))
247 #define ISLOWER(c) islower (CHAR(c))
249 #define lowcase(c) tolower (CHAR(c))
250 #define upcase(c) toupper (CHAR(c))
254 * xnew, xrnew -- allocate, reallocate storage
256 * SYNOPSIS: Type *xnew (int n, Type);
257 * void xrnew (OldPointer, int n, Type);
260 # include "chkmalloc.h"
261 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
262 (n) * sizeof (Type)))
263 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
264 (char *) (op), (n) * sizeof (Type)))
266 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
267 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
268 (char *) (op), (n) * sizeof (Type)))
273 typedef void Lang_function
__P((FILE *));
277 char *suffix
; /* file name suffix for this compressor */
278 char *command
; /* takes one arg and decompresses to stdout */
283 char *name
; /* language name */
284 char *help
; /* detailed help for the language */
285 Lang_function
*function
; /* parse function */
286 char **suffixes
; /* name suffixes of this language's files */
287 char **filenames
; /* names of this language's files */
288 char **interpreters
; /* interpreters for this language */
289 bool metasource
; /* source used to generate other sources */
294 struct fdesc
*next
; /* for the linked list */
295 char *infname
; /* uncompressed input file name */
296 char *infabsname
; /* absolute uncompressed input file name */
297 char *infabsdir
; /* absolute dir of input file */
298 char *taggedfname
; /* file name to write in tagfile */
299 language
*lang
; /* language of file */
300 char *prop
; /* file properties to write in tagfile */
301 bool usecharno
; /* etags tags shall contain char number */
302 bool written
; /* entry written in the tags file */
305 typedef struct node_st
306 { /* sorting structure */
307 struct node_st
*left
, *right
; /* left and right sons */
308 fdesc
*fdp
; /* description of file to whom tag belongs */
309 char *name
; /* tag name */
310 char *regex
; /* search regexp */
311 bool valid
; /* write this tag on the tag file */
312 bool is_func
; /* function tag: use regexp in CTAGS mode */
313 bool been_warned
; /* warning already given for duplicated tag */
314 int lno
; /* line number tag is on */
315 long cno
; /* character number line starts on */
319 * A `linebuffer' is a structure which holds a line of text.
320 * `readline_internal' reads a line from a stream into a linebuffer
321 * and works regardless of the length of the line.
322 * SIZE is the size of BUFFER, LEN is the length of the string in
323 * BUFFER after readline reads it.
332 /* Used to support mixing of --lang and file names. */
336 at_language
, /* a language specification */
337 at_regexp
, /* a regular expression */
338 at_filename
, /* a file name */
339 at_stdin
, /* read from stdin here */
340 at_end
/* stop parsing the list */
341 } arg_type
; /* argument type */
342 language
*lang
; /* language associated with the argument */
343 char *what
; /* the argument itself */
346 /* Structure defining a regular expression. */
347 typedef struct regexp
349 struct regexp
*p_next
; /* pointer to next in list */
350 language
*lang
; /* if set, use only for this language */
351 char *pattern
; /* the regexp pattern */
352 char *name
; /* tag name */
353 struct re_pattern_buffer
*pat
; /* the compiled pattern */
354 struct re_registers regs
; /* re registers */
355 bool error_signaled
; /* already signaled for this regexp */
356 bool force_explicit_name
; /* do not allow implict tag name */
357 bool ignore_case
; /* ignore case when matching */
358 bool multi_line
; /* do a multi-line match on the whole file */
362 /* Many compilers barf on this:
363 Lang_function Ada_funcs;
364 so let's write it this way */
365 static void Ada_funcs
__P((FILE *));
366 static void Asm_labels
__P((FILE *));
367 static void C_entries
__P((int c_ext
, FILE *));
368 static void default_C_entries
__P((FILE *));
369 static void plain_C_entries
__P((FILE *));
370 static void Cjava_entries
__P((FILE *));
371 static void Cobol_paragraphs
__P((FILE *));
372 static void Cplusplus_entries
__P((FILE *));
373 static void Cstar_entries
__P((FILE *));
374 static void Erlang_functions
__P((FILE *));
375 static void Forth_words
__P((FILE *));
376 static void Fortran_functions
__P((FILE *));
377 static void HTML_labels
__P((FILE *));
378 static void Lisp_functions
__P((FILE *));
379 static void Lua_functions
__P((FILE *));
380 static void Makefile_targets
__P((FILE *));
381 static void Pascal_functions
__P((FILE *));
382 static void Perl_functions
__P((FILE *));
383 static void PHP_functions
__P((FILE *));
384 static void PS_functions
__P((FILE *));
385 static void Prolog_functions
__P((FILE *));
386 static void Python_functions
__P((FILE *));
387 static void Scheme_functions
__P((FILE *));
388 static void TeX_commands
__P((FILE *));
389 static void Texinfo_nodes
__P((FILE *));
390 static void Yacc_entries
__P((FILE *));
391 static void just_read_file
__P((FILE *));
393 static void print_language_names
__P((void));
394 static void print_version
__P((void));
395 static void print_help
__P((argument
*));
396 int main
__P((int, char **));
398 static compressor
*get_compressor_from_suffix
__P((char *, char **));
399 static language
*get_language_from_langname
__P((const char *));
400 static language
*get_language_from_interpreter
__P((char *));
401 static language
*get_language_from_filename
__P((char *, bool));
402 static void readline
__P((linebuffer
*, FILE *));
403 static long readline_internal
__P((linebuffer
*, FILE *));
404 static bool nocase_tail
__P((char *));
405 static void get_tag
__P((char *, char **));
407 static void analyse_regex
__P((char *));
408 static void free_regexps
__P((void));
409 static void regex_tag_multiline
__P((void));
410 static void error
__P((const char *, const char *));
411 static void suggest_asking_for_help
__P((void));
412 void fatal
__P((char *, char *));
413 static void pfatal
__P((char *));
414 static void add_node
__P((node
*, node
**));
416 static void init
__P((void));
417 static void process_file_name
__P((char *, language
*));
418 static void process_file
__P((FILE *, char *, language
*));
419 static void find_entries
__P((FILE *));
420 static void free_tree
__P((node
*));
421 static void free_fdesc
__P((fdesc
*));
422 static void pfnote
__P((char *, bool, char *, int, int, long));
423 static void make_tag
__P((char *, int, bool, char *, int, int, long));
424 static void invalidate_nodes
__P((fdesc
*, node
**));
425 static void put_entries
__P((node
*));
427 static char *concat
__P((char *, char *, char *));
428 static char *skip_spaces
__P((char *));
429 static char *skip_non_spaces
__P((char *));
430 static char *savenstr
__P((char *, int));
431 static char *savestr
__P((char *));
432 static char *etags_strchr
__P((const char *, int));
433 static char *etags_strrchr
__P((const char *, int));
434 static int etags_strcasecmp
__P((const char *, const char *));
435 static int etags_strncasecmp
__P((const char *, const char *, int));
436 static char *etags_getcwd
__P((void));
437 static char *relative_filename
__P((char *, char *));
438 static char *absolute_filename
__P((char *, char *));
439 static char *absolute_dirname
__P((char *, char *));
440 static bool filename_is_absolute
__P((char *f
));
441 static void canonicalize_filename
__P((char *));
442 static void linebuffer_init
__P((linebuffer
*));
443 static void linebuffer_setlen
__P((linebuffer
*, int));
444 static PTR xmalloc
__P((unsigned int));
445 static PTR xrealloc
__P((char *, unsigned int));
448 static char searchar
= '/'; /* use /.../ searches */
450 static char *tagfile
; /* output file */
451 static char *progname
; /* name this program was invoked with */
452 static char *cwd
; /* current working directory */
453 static char *tagfiledir
; /* directory of tagfile */
454 static FILE *tagf
; /* ioptr for tags file */
456 static fdesc
*fdhead
; /* head of file description list */
457 static fdesc
*curfdp
; /* current file description */
458 static int lineno
; /* line number of current line */
459 static long charno
; /* current character number */
460 static long linecharno
; /* charno of start of current line */
461 static char *dbp
; /* pointer to start of current tag */
463 static const int invalidcharno
= -1;
465 static node
*nodehead
; /* the head of the binary tree of tags */
466 static node
*last_node
; /* the last node created */
468 static linebuffer lb
; /* the current line */
469 static linebuffer filebuf
; /* a buffer containing the whole file */
470 static linebuffer token_name
; /* a buffer containing a tag name */
472 /* boolean "functions" (see init) */
473 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
476 *white
= " \f\t\n\r\v",
478 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
479 /* token ending chars */
480 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
481 /* token starting chars */
482 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
483 /* valid in-token chars */
484 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
486 static bool append_to_tagfile
; /* -a: append to tags */
487 /* The next four default to TRUE for etags, but to FALSE for ctags. */
488 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
489 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
490 /* 0 struct/enum/union decls, and C++ */
491 /* member functions. */
492 static bool constantypedefs
; /* -d: create tags for C #define, enum */
493 /* constants and variables. */
494 /* -D: opposite of -d. Default under ctags. */
495 static bool globals
; /* create tags for global variables */
496 static bool members
; /* create tags for C member variables */
497 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
498 static bool no_line_directive
; /* ignore #line directives (undocumented) */
499 static bool no_duplicates
; /* no duplicate tags for ctags (undocumented) */
500 static bool update
; /* -u: update tags */
501 static bool vgrind_style
; /* -v: create vgrind style index output */
502 static bool no_warnings
; /* -w: suppress warnings (undocumented) */
503 static bool cxref_style
; /* -x: create cxref style output */
504 static bool cplusplus
; /* .[hc] means C++, not C */
505 static bool ignoreindent
; /* -I: ignore indentation in C */
506 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
508 /* STDIN is defined in LynxOS system headers */
513 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
514 static bool parsing_stdin
; /* --parse-stdin used */
516 static regexp
*p_head
; /* list of all regexps */
517 static bool need_filebuf
; /* some regexes are multi-line */
519 static struct option longopts
[] =
521 { "append", no_argument
, NULL
, 'a' },
522 { "packages-only", no_argument
, &packages_only
, TRUE
},
523 { "c++", no_argument
, NULL
, 'C' },
524 { "declarations", no_argument
, &declarations
, TRUE
},
525 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
526 { "no-duplicates", no_argument
, &no_duplicates
, TRUE
},
527 { "help", no_argument
, NULL
, 'h' },
528 { "help", no_argument
, NULL
, 'H' },
529 { "ignore-indentation", no_argument
, NULL
, 'I' },
530 { "language", required_argument
, NULL
, 'l' },
531 { "members", no_argument
, &members
, TRUE
},
532 { "no-members", no_argument
, &members
, FALSE
},
533 { "output", required_argument
, NULL
, 'o' },
534 { "regex", required_argument
, NULL
, 'r' },
535 { "no-regex", no_argument
, NULL
, 'R' },
536 { "ignore-case-regex", required_argument
, NULL
, 'c' },
537 { "parse-stdin", required_argument
, NULL
, STDIN
},
538 { "version", no_argument
, NULL
, 'V' },
540 #if CTAGS /* Ctags options */
541 { "backward-search", no_argument
, NULL
, 'B' },
542 { "cxref", no_argument
, NULL
, 'x' },
543 { "defines", no_argument
, NULL
, 'd' },
544 { "globals", no_argument
, &globals
, TRUE
},
545 { "typedefs", no_argument
, NULL
, 't' },
546 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
547 { "update", no_argument
, NULL
, 'u' },
548 { "vgrind", no_argument
, NULL
, 'v' },
549 { "no-warn", no_argument
, NULL
, 'w' },
551 #else /* Etags options */
552 { "no-defines", no_argument
, NULL
, 'D' },
553 { "no-globals", no_argument
, &globals
, FALSE
},
554 { "include", required_argument
, NULL
, 'i' },
559 static compressor compressors
[] =
561 { "z", "gzip -d -c"},
562 { "Z", "gzip -d -c"},
563 { "gz", "gzip -d -c"},
564 { "GZ", "gzip -d -c"},
565 { "bz2", "bzip2 -d -c" },
574 static char *Ada_suffixes
[] =
575 { "ads", "adb", "ada", NULL
};
576 static char Ada_help
[] =
577 "In Ada code, functions, procedures, packages, tasks and types are\n\
578 tags. Use the `--packages-only' option to create tags for\n\
580 Ada tag names have suffixes indicating the type of entity:\n\
581 Entity type: Qualifier:\n\
582 ------------ ----------\n\
589 Thus, `M-x find-tag <RET> bidule/b <RET>' will go directly to the\n\
590 body of the package `bidule', while `M-x find-tag <RET> bidule <RET>'\n\
591 will just search for any tag `bidule'.";
594 static char *Asm_suffixes
[] =
595 { "a", /* Unix assembler */
596 "asm", /* Microcontroller assembly */
597 "def", /* BSO/Tasking definition includes */
598 "inc", /* Microcontroller include files */
599 "ins", /* Microcontroller include files */
600 "s", "sa", /* Unix assembler */
601 "S", /* cpp-processed Unix assembler */
602 "src", /* BSO/Tasking C compiler output */
605 static char Asm_help
[] =
606 "In assembler code, labels appearing at the beginning of a line,\n\
607 followed by a colon, are tags.";
610 /* Note that .c and .h can be considered C++, if the --c++ flag was
611 given, or if the `class' or `template' keyowrds are met inside the file.
612 That is why default_C_entries is called for these. */
613 static char *default_C_suffixes
[] =
615 static char default_C_help
[] =
616 "In C code, any C function or typedef is a tag, and so are\n\
617 definitions of `struct', `union' and `enum'. `#define' macro\n\
618 definitions and `enum' constants are tags unless you specify\n\
619 `--no-defines'. Global variables are tags unless you specify\n\
620 `--no-globals' and so are struct members unless you specify\n\
621 `--no-members'. Use of `--no-globals', `--no-defines' and\n\
622 `--no-members' can make the tags table file much smaller.\n\
623 You can tag function declarations and external variables by\n\
624 using `--declarations'.";
626 static char *Cplusplus_suffixes
[] =
627 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
628 "M", /* Objective C++ */
629 "pdb", /* Postscript with C syntax */
631 static char Cplusplus_help
[] =
632 "In C++ code, all the tag constructs of C code are tagged. (Use\n\
633 --help --lang=c --lang=c++ for full help.)\n\
634 In addition to C tags, member functions are also recognized. Member\n\
635 variables are recognized unless you use the `--no-members' option.\n\
636 Tags for variables and functions in classes are named `CLASS::VARIABLE'\n\
637 and `CLASS::FUNCTION'. `operator' definitions have tag names like\n\
640 static char *Cjava_suffixes
[] =
642 static char Cjava_help
[] =
643 "In Java code, all the tags constructs of C and C++ code are\n\
644 tagged. (Use --help --lang=c --lang=c++ --lang=java for full help.)";
647 static char *Cobol_suffixes
[] =
648 { "COB", "cob", NULL
};
649 static char Cobol_help
[] =
650 "In Cobol code, tags are paragraph names; that is, any word\n\
651 starting in column 8 and followed by a period.";
653 static char *Cstar_suffixes
[] =
654 { "cs", "hs", NULL
};
656 static char *Erlang_suffixes
[] =
657 { "erl", "hrl", NULL
};
658 static char Erlang_help
[] =
659 "In Erlang code, the tags are the functions, records and macros\n\
660 defined in the file.";
662 char *Forth_suffixes
[] =
663 { "fth", "tok", NULL
};
664 static char Forth_help
[] =
665 "In Forth code, tags are words defined by `:',\n\
666 constant, code, create, defer, value, variable, buffer:, field.";
668 static char *Fortran_suffixes
[] =
669 { "F", "f", "f90", "for", NULL
};
670 static char Fortran_help
[] =
671 "In Fortran code, functions, subroutines and block data are tags.";
673 static char *HTML_suffixes
[] =
674 { "htm", "html", "shtml", NULL
};
675 static char HTML_help
[] =
676 "In HTML input files, the tags are the `title' and the `h1', `h2',\n\
677 `h3' headers. Also, tags are `name=' in anchors and all\n\
678 occurrences of `id='.";
680 static char *Lisp_suffixes
[] =
681 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
682 static char Lisp_help
[] =
683 "In Lisp code, any function defined with `defun', any variable\n\
684 defined with `defvar' or `defconst', and in general the first\n\
685 argument of any expression that starts with `(def' in column zero\n\
688 static char *Lua_suffixes
[] =
689 { "lua", "LUA", NULL
};
690 static char Lua_help
[] =
691 "In Lua scripts, all functions are tags.";
693 static char *Makefile_filenames
[] =
694 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
695 static char Makefile_help
[] =
696 "In makefiles, targets are tags; additionally, variables are tags\n\
697 unless you specify `--no-globals'.";
699 static char *Objc_suffixes
[] =
700 { "lm", /* Objective lex file */
701 "m", /* Objective C file */
703 static char Objc_help
[] =
704 "In Objective C code, tags include Objective C definitions for classes,\n\
705 class categories, methods and protocols. Tags for variables and\n\
706 functions in classes are named `CLASS::VARIABLE' and `CLASS::FUNCTION'.\n\
707 (Use --help --lang=c --lang=objc --lang=java for full help.)";
709 static char *Pascal_suffixes
[] =
710 { "p", "pas", NULL
};
711 static char Pascal_help
[] =
712 "In Pascal code, the tags are the functions and procedures defined\n\
714 /* " // this is for working around an Emacs highlighting bug... */
716 static char *Perl_suffixes
[] =
717 { "pl", "pm", NULL
};
718 static char *Perl_interpreters
[] =
719 { "perl", "@PERL@", NULL
};
720 static char Perl_help
[] =
721 "In Perl code, the tags are the packages, subroutines and variables\n\
722 defined by the `package', `sub', `my' and `local' keywords. Use\n\
723 `--globals' if you want to tag global variables. Tags for\n\
724 subroutines are named `PACKAGE::SUB'. The name for subroutines\n\
725 defined in the default package is `main::SUB'.";
727 static char *PHP_suffixes
[] =
728 { "php", "php3", "php4", NULL
};
729 static char PHP_help
[] =
730 "In PHP code, tags are functions, classes and defines. Unless you use\n\
731 the `--no-members' option, vars are tags too.";
733 static char *plain_C_suffixes
[] =
734 { "pc", /* Pro*C file */
737 static char *PS_suffixes
[] =
738 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
739 static char PS_help
[] =
740 "In PostScript code, the tags are the functions.";
742 static char *Prolog_suffixes
[] =
744 static char Prolog_help
[] =
745 "In Prolog code, tags are predicates and rules at the beginning of\n\
748 static char *Python_suffixes
[] =
750 static char Python_help
[] =
751 "In Python code, `def' or `class' at the beginning of a line\n\
754 /* Can't do the `SCM' or `scm' prefix with a version number. */
755 static char *Scheme_suffixes
[] =
756 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
757 static char Scheme_help
[] =
758 "In Scheme code, tags include anything defined with `def' or with a\n\
759 construct whose name starts with `def'. They also include\n\
760 variables set with `set!' at top level in the file.";
762 static char *TeX_suffixes
[] =
763 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
764 static char TeX_help
[] =
765 "In LaTeX text, the argument of any of the commands `\\chapter',\n\
766 `\\section', `\\subsection', `\\subsubsection', `\\eqno', `\\label',\n\
767 `\\ref', `\\cite', `\\bibitem', `\\part', `\\appendix', `\\entry',\n\
768 `\\index', `\\def', `\\newcommand', `\\renewcommand',\n\
769 `\\newenvironment' or `\\renewenvironment' is a tag.\n\
771 Other commands can be specified by setting the environment variable\n\
772 `TEXTAGS' to a colon-separated list like, for example,\n\
773 TEXTAGS=\"mycommand:myothercommand\".";
776 static char *Texinfo_suffixes
[] =
777 { "texi", "texinfo", "txi", NULL
};
778 static char Texinfo_help
[] =
779 "for texinfo files, lines starting with @node are tagged.";
781 static char *Yacc_suffixes
[] =
782 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
783 static char Yacc_help
[] =
784 "In Bison or Yacc input files, each rule defines as a tag the\n\
785 nonterminal it constructs. The portions of the file that contain\n\
786 C code are parsed as C code (use --help --lang=c --lang=yacc\n\
789 static char auto_help
[] =
790 "`auto' is not a real language, it indicates to use\n\
791 a default language for files base on file name suffix and file contents.";
793 static char none_help
[] =
794 "`none' is not a real language, it indicates to only do\n\
795 regexp processing on files.";
797 static char no_lang_help
[] =
798 "No detailed help available for this language.";
802 * Table of languages.
804 * It is ok for a given function to be listed under more than one
805 * name. I just didn't.
808 static language lang_names
[] =
810 { "ada", Ada_help
, Ada_funcs
, Ada_suffixes
},
811 { "asm", Asm_help
, Asm_labels
, Asm_suffixes
},
812 { "c", default_C_help
, default_C_entries
, default_C_suffixes
},
813 { "c++", Cplusplus_help
, Cplusplus_entries
, Cplusplus_suffixes
},
814 { "c*", no_lang_help
, Cstar_entries
, Cstar_suffixes
},
815 { "cobol", Cobol_help
, Cobol_paragraphs
, Cobol_suffixes
},
816 { "erlang", Erlang_help
, Erlang_functions
, Erlang_suffixes
},
817 { "forth", Forth_help
, Forth_words
, Forth_suffixes
},
818 { "fortran", Fortran_help
, Fortran_functions
, Fortran_suffixes
},
819 { "html", HTML_help
, HTML_labels
, HTML_suffixes
},
820 { "java", Cjava_help
, Cjava_entries
, Cjava_suffixes
},
821 { "lisp", Lisp_help
, Lisp_functions
, Lisp_suffixes
},
822 { "lua", Lua_help
, Lua_functions
, Lua_suffixes
},
823 { "makefile", Makefile_help
,Makefile_targets
,NULL
,Makefile_filenames
},
824 { "objc", Objc_help
, plain_C_entries
, Objc_suffixes
},
825 { "pascal", Pascal_help
, Pascal_functions
, Pascal_suffixes
},
826 { "perl",Perl_help
,Perl_functions
,Perl_suffixes
,NULL
,Perl_interpreters
},
827 { "php", PHP_help
, PHP_functions
, PHP_suffixes
},
828 { "postscript",PS_help
, PS_functions
, PS_suffixes
},
829 { "proc", no_lang_help
, plain_C_entries
, plain_C_suffixes
},
830 { "prolog", Prolog_help
, Prolog_functions
, Prolog_suffixes
},
831 { "python", Python_help
, Python_functions
, Python_suffixes
},
832 { "scheme", Scheme_help
, Scheme_functions
, Scheme_suffixes
},
833 { "tex", TeX_help
, TeX_commands
, TeX_suffixes
},
834 { "texinfo", Texinfo_help
, Texinfo_nodes
, Texinfo_suffixes
},
835 { "yacc", Yacc_help
,Yacc_entries
,Yacc_suffixes
,NULL
,NULL
,TRUE
},
836 { "auto", auto_help
}, /* default guessing scheme */
837 { "none", none_help
, just_read_file
}, /* regexp matching only */
838 { NULL
} /* end of list */
843 print_language_names ()
848 puts ("\nThese are the currently supported languages, along with the\n\
849 default file names and dot suffixes:");
850 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
852 printf (" %-*s", 10, lang
->name
);
853 if (lang
->filenames
!= NULL
)
854 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
855 printf (" %s", *name
);
856 if (lang
->suffixes
!= NULL
)
857 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
858 printf (" .%s", *ext
);
861 puts ("where `auto' means use default language for files based on file\n\
862 name suffix, and `none' means only do regexp processing on files.\n\
863 If no language is specified and no matching suffix is found,\n\
864 the first line of the file is read for a sharp-bang (#!) sequence\n\
865 followed by the name of an interpreter. If no such sequence is found,\n\
866 Fortran is tried first; if no tags are found, C is tried next.\n\
867 When parsing any C file, a \"class\" or \"template\" keyword\n\
869 puts ("Compressed files are supported using gzip and bzip2.\n\
871 For detailed help on a given language use, for example,\n\
872 etags --help --lang=ada.");
876 # define EMACS_NAME "standalone"
879 # define VERSION "version"
884 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
885 puts ("Copyright (C) 2007 Free Software Foundation, Inc.");
886 puts ("This program is distributed under the terms in ETAGS.README");
892 print_help (argbuffer
)
895 bool help_for_lang
= FALSE
;
897 for (; argbuffer
->arg_type
!= at_end
; argbuffer
++)
898 if (argbuffer
->arg_type
== at_language
)
902 puts (argbuffer
->lang
->help
);
903 help_for_lang
= TRUE
;
909 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
911 These are the options accepted by %s.\n", progname
, progname
);
913 puts ("WARNING: long option names do not work with this executable,\n\
914 as it is not linked with GNU getopt.");
916 puts ("You may use unambiguous abbreviations for the long option names.");
917 puts (" A - as file name means read names from stdin (one per line).\n\
918 Absolute names are stored in the output file as they are.\n\
919 Relative ones are stored relative to the output file's directory.\n");
921 puts ("-a, --append\n\
922 Append tag entries to existing tags file.");
924 puts ("--packages-only\n\
925 For Ada files, only generate tags for packages.");
928 puts ("-B, --backward-search\n\
929 Write the search commands for the tag entries using '?', the\n\
930 backward-search command instead of '/', the forward-search command.");
932 /* This option is mostly obsolete, because etags can now automatically
933 detect C++. Retained for backward compatibility and for debugging and
934 experimentation. In principle, we could want to tag as C++ even
935 before any "class" or "template" keyword.
937 Treat files whose name suffix defaults to C language as C++ files.");
940 puts ("--declarations\n\
941 In C and derived languages, create tags for function declarations,");
943 puts ("\tand create tags for extern variables if --globals is used.");
946 ("\tand create tags for extern variables unless --no-globals is used.");
949 puts ("-d, --defines\n\
950 Create tag entries for C #define constants and enum constants, too.");
952 puts ("-D, --no-defines\n\
953 Don't create tag entries for C #define constants and enum constants.\n\
954 This makes the tags file smaller.");
957 puts ("-i FILE, --include=FILE\n\
958 Include a note in tag file indicating that, when searching for\n\
959 a tag, one should also consult the tags file FILE after\n\
960 checking the current file.");
962 puts ("-l LANG, --language=LANG\n\
963 Force the following files to be considered as written in the\n\
964 named language up to the next --language=LANG option.");
968 Create tag entries for global variables in some languages.");
970 puts ("--no-globals\n\
971 Do not create tag entries for global variables in some\n\
972 languages. This makes the tags file smaller.");
973 puts ("--no-members\n\
974 Do not create tag entries for members of structures\n\
975 in some languages.");
977 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
978 Make a tag for each line matching a regular expression pattern\n\
979 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
980 files only. REGEXFILE is a file containing one REGEXP per line.\n\
981 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
982 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
983 puts (" If TAGNAME/ is present, the tags created are named.\n\
984 For example Tcl named tags can be created with:\n\
985 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
986 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
987 `m' means to allow multi-line matches, `s' implies `m' and\n\
988 causes dot to match any character, including newline.");
989 puts ("-R, --no-regex\n\
990 Don't create tags from regexps for the following files.");
991 puts ("-I, --ignore-indentation\n\
992 In C and C++ do not assume that a closing brace in the first\n\
993 column is the final brace of a function or structure definition.");
994 puts ("-o FILE, --output=FILE\n\
995 Write the tags to FILE.");
996 puts ("--parse-stdin=NAME\n\
997 Read from standard input and record tags as belonging to file NAME.");
1001 puts ("-t, --typedefs\n\
1002 Generate tag entries for C and Ada typedefs.");
1003 puts ("-T, --typedefs-and-c++\n\
1004 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
1005 and C++ member functions.");
1009 puts ("-u, --update\n\
1010 Update the tag entries for the given files, leaving tag\n\
1011 entries for other files in place. Currently, this is\n\
1012 implemented by deleting the existing entries for the given\n\
1013 files and then rewriting the new entries at the end of the\n\
1014 tags file. It is often faster to simply rebuild the entire\n\
1015 tag file than to use this.");
1019 puts ("-v, --vgrind\n\
1020 Print on the standard output an index of items intended for\n\
1021 human consumption, similar to the output of vgrind. The index\n\
1022 is sorted, and gives the page number of each item.");
1023 # if PRINT_UNDOCUMENTED_OPTIONS_HELP
1024 puts ("-w, --no-duplicates\n\
1025 Do not create duplicate tag entries, for compatibility with\n\
1026 traditional ctags.");
1027 puts ("-w, --no-warn\n\
1028 Suppress warning messages about duplicate tag entries.");
1029 # endif /* PRINT_UNDOCUMENTED_OPTIONS_HELP */
1030 puts ("-x, --cxref\n\
1031 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
1032 The output uses line numbers instead of page numbers, but\n\
1033 beyond that the differences are cosmetic; try both to see\n\
1037 puts ("-V, --version\n\
1038 Print the version of the program.\n\
1040 Print this help message.\n\
1041 Followed by one or more `--language' options prints detailed\n\
1042 help about tag generation for the specified languages.");
1044 print_language_names ();
1047 puts ("Report bugs to bug-gnu-emacs@gnu.org");
1049 exit (EXIT_SUCCESS
);
1053 #ifdef VMS /* VMS specific functions */
1057 /* This is a BUG! ANY arbitrary limit is a BUG!
1058 Won't someone please fix this? */
1059 #define MAX_FILE_SPEC_LEN 255
1062 char body
[MAX_FILE_SPEC_LEN
+ 1];
1066 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
1067 returning in each successive call the next file name matching the input
1068 spec. The function expects that each in_spec passed
1069 to it will be processed to completion; in particular, up to and
1070 including the call following that in which the last matching name
1071 is returned, the function ignores the value of in_spec, and will
1072 only start processing a new spec with the following call.
1073 If an error occurs, on return out_spec contains the value
1074 of in_spec when the error occurred.
1076 With each successive file name returned in out_spec, the
1077 function's return value is one. When there are no more matching
1078 names the function returns zero. If on the first call no file
1079 matches in_spec, or there is any other error, -1 is returned.
1083 #include <descrip.h>
1084 #define OUTSIZE MAX_FILE_SPEC_LEN
1090 static long context
= 0;
1091 static struct dsc$descriptor_s o
;
1092 static struct dsc$descriptor_s i
;
1093 static bool pass1
= TRUE
;
1100 o
.dsc$a_pointer
= (char *) out
;
1101 o
.dsc$w_length
= (short)OUTSIZE
;
1102 i
.dsc$a_pointer
= in
;
1103 i
.dsc$w_length
= (short)strlen(in
);
1104 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
1105 i
.dsc$b_class
= DSC$K_CLASS_S
;
1106 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
1107 o
.dsc$b_class
= DSC$K_CLASS_VS
;
1109 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
1111 out
->body
[out
->curlen
] = EOS
;
1114 else if (status
== RMS$_NMF
)
1118 strcpy(out
->body
, in
);
1121 lib$
find_file_end(&context
);
1127 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
1128 name of each file specified by the provided arg expanding wildcards.
1131 gfnames (arg
, p_error
)
1135 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
1137 switch (fn_exp (&filename
, arg
))
1141 return filename
.body
;
1147 return filename
.body
;
1151 #ifndef OLD /* Newer versions of VMS do provide `system'. */
1155 error ("%s", "system() function not implemented under VMS");
1159 #define VERSION_DELIM ';'
1160 char *massage_name (s
)
1166 if (*s
== VERSION_DELIM
)
1184 unsigned int nincluded_files
;
1185 char **included_files
;
1186 argument
*argbuffer
;
1187 int current_arg
, file_count
;
1188 linebuffer filename_lb
;
1189 bool help_asked
= FALSE
;
1198 _fmode
= O_BINARY
; /* all of files are treated as binary files */
1202 nincluded_files
= 0;
1203 included_files
= xnew (argc
, char *);
1207 /* Allocate enough no matter what happens. Overkill, but each one
1209 argbuffer
= xnew (argc
, argument
);
1212 * If etags, always find typedefs and structure tags. Why not?
1213 * Also default to find macro constants, enum constants, struct
1214 * members and global variables.
1218 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1222 /* When the optstring begins with a '-' getopt_long does not rearrange the
1223 non-options arguments to be at the end, but leaves them alone. */
1224 optstring
= concat (NO_LONG_OPTIONS
? "" : "-",
1225 "ac:Cf:Il:o:r:RSVhH",
1226 (CTAGS
) ? "BxdtTuvw" : "Di:");
1228 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, NULL
)) != EOF
)
1232 /* If getopt returns 0, then it has already processed a
1233 long-named option. We should do nothing. */
1237 /* This means that a file name has been seen. Record it. */
1238 argbuffer
[current_arg
].arg_type
= at_filename
;
1239 argbuffer
[current_arg
].what
= optarg
;
1245 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1246 argbuffer
[current_arg
].arg_type
= at_stdin
;
1247 argbuffer
[current_arg
].what
= optarg
;
1251 fatal ("cannot parse standard input more than once", (char *)NULL
);
1252 parsing_stdin
= TRUE
;
1255 /* Common options. */
1256 case 'a': append_to_tagfile
= TRUE
; break;
1257 case 'C': cplusplus
= TRUE
; break;
1258 case 'f': /* for compatibility with old makefiles */
1262 error ("-o option may only be given once.", (char *)NULL
);
1263 suggest_asking_for_help ();
1269 case 'S': /* for backward compatibility */
1270 ignoreindent
= TRUE
;
1274 language
*lang
= get_language_from_langname (optarg
);
1277 argbuffer
[current_arg
].lang
= lang
;
1278 argbuffer
[current_arg
].arg_type
= at_language
;
1284 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1285 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1288 argbuffer
[current_arg
].arg_type
= at_regexp
;
1289 argbuffer
[current_arg
].what
= optarg
;
1293 argbuffer
[current_arg
].arg_type
= at_regexp
;
1294 argbuffer
[current_arg
].what
= NULL
;
1306 case 'D': constantypedefs
= FALSE
; break;
1307 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1309 /* Ctags options. */
1310 case 'B': searchar
= '?'; break;
1311 case 'd': constantypedefs
= TRUE
; break;
1312 case 't': typedefs
= TRUE
; break;
1313 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1314 case 'u': update
= TRUE
; break;
1315 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1316 case 'x': cxref_style
= TRUE
; break;
1317 case 'w': no_warnings
= TRUE
; break;
1319 suggest_asking_for_help ();
1323 /* No more options. Store the rest of arguments. */
1324 for (; optind
< argc
; optind
++)
1326 argbuffer
[current_arg
].arg_type
= at_filename
;
1327 argbuffer
[current_arg
].what
= argv
[optind
];
1332 argbuffer
[current_arg
].arg_type
= at_end
;
1335 print_help (argbuffer
);
1338 if (nincluded_files
== 0 && file_count
== 0)
1340 error ("no input files specified.", (char *)NULL
);
1341 suggest_asking_for_help ();
1345 if (tagfile
== NULL
)
1346 tagfile
= CTAGS
? "tags" : "TAGS";
1347 cwd
= etags_getcwd (); /* the current working directory */
1348 if (cwd
[strlen (cwd
) - 1] != '/')
1351 cwd
= concat (oldcwd
, "/", "");
1354 /* Relative file names are made relative to the current directory. */
1355 if (streq (tagfile
, "-")
1356 || strneq (tagfile
, "/dev/", 5))
1359 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1361 init (); /* set up boolean "functions" */
1363 linebuffer_init (&lb
);
1364 linebuffer_init (&filename_lb
);
1365 linebuffer_init (&filebuf
);
1366 linebuffer_init (&token_name
);
1370 if (streq (tagfile
, "-"))
1374 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1375 doesn't take effect until after `stdout' is already open). */
1376 if (!isatty (fileno (stdout
)))
1377 setmode (fileno (stdout
), O_BINARY
);
1381 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1387 * Loop through files finding functions.
1389 for (i
= 0; i
< current_arg
; i
++)
1391 static language
*lang
; /* non-NULL if language is forced */
1394 switch (argbuffer
[i
].arg_type
)
1397 lang
= argbuffer
[i
].lang
;
1400 analyse_regex (argbuffer
[i
].what
);
1404 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1408 error ("can't find file %s\n", this_file
);
1413 this_file
= massage_name (this_file
);
1416 this_file
= argbuffer
[i
].what
;
1418 /* Input file named "-" means read file names from stdin
1419 (one per line) and use them. */
1420 if (streq (this_file
, "-"))
1423 fatal ("cannot parse standard input AND read file names from it",
1425 while (readline_internal (&filename_lb
, stdin
) > 0)
1426 process_file_name (filename_lb
.buffer
, lang
);
1429 process_file_name (this_file
, lang
);
1435 this_file
= argbuffer
[i
].what
;
1436 process_file (stdin
, this_file
, lang
);
1443 free (filebuf
.buffer
);
1444 free (token_name
.buffer
);
1446 if (!CTAGS
|| cxref_style
)
1448 /* Write the remaining tags to tagf (ETAGS) or stdout (CXREF). */
1449 put_entries (nodehead
);
1450 free_tree (nodehead
);
1456 /* Output file entries that have no tags. */
1457 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1459 fprintf (tagf
, "\f\n%s,0\n", fdp
->taggedfname
);
1461 while (nincluded_files
-- > 0)
1462 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1464 if (fclose (tagf
) == EOF
)
1468 exit (EXIT_SUCCESS
);
1474 for (i
= 0; i
< current_arg
; ++i
)
1476 switch (argbuffer
[i
].arg_type
)
1482 continue; /* the for loop */
1485 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1486 tagfile
, argbuffer
[i
].what
, tagfile
);
1487 if (system (cmd
) != EXIT_SUCCESS
)
1488 fatal ("failed to execute shell command", (char *)NULL
);
1490 append_to_tagfile
= TRUE
;
1493 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1496 put_entries (nodehead
); /* write all the tags (CTAGS) */
1497 free_tree (nodehead
);
1499 if (fclose (tagf
) == EOF
)
1503 if (append_to_tagfile
|| update
)
1505 char cmd
[2*BUFSIZ
+20];
1506 /* Maybe these should be used:
1507 setenv ("LC_COLLATE", "C", 1);
1508 setenv ("LC_ALL", "C", 1); */
1509 sprintf (cmd
, "sort -u -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1510 exit (system (cmd
));
1512 return EXIT_SUCCESS
;
1517 * Return a compressor given the file name. If EXTPTR is non-zero,
1518 * return a pointer into FILE where the compressor-specific
1519 * extension begins. If no compressor is found, NULL is returned
1520 * and EXTPTR is not significant.
1521 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1524 get_compressor_from_suffix (file
, extptr
)
1529 char *slash
, *suffix
;
1531 /* This relies on FN to be after canonicalize_filename,
1532 so we don't need to consider backslashes on DOS_NT. */
1533 slash
= etags_strrchr (file
, '/');
1534 suffix
= etags_strrchr (file
, '.');
1535 if (suffix
== NULL
|| suffix
< slash
)
1540 /* Let those poor souls who live with DOS 8+3 file name limits get
1541 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1542 Only the first do loop is run if not MSDOS */
1545 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1546 if (streq (compr
->suffix
, suffix
))
1549 break; /* do it only once: not really a loop */
1552 } while (*suffix
!= '\0');
1559 * Return a language given the name.
1562 get_language_from_langname (name
)
1568 error ("empty language name", (char *)NULL
);
1571 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1572 if (streq (name
, lang
->name
))
1574 error ("unknown language \"%s\"", name
);
1582 * Return a language given the interpreter name.
1585 get_language_from_interpreter (interpreter
)
1591 if (interpreter
== NULL
)
1593 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1594 if (lang
->interpreters
!= NULL
)
1595 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1596 if (streq (*iname
, interpreter
))
1605 * Return a language given the file name.
1608 get_language_from_filename (file
, case_sensitive
)
1610 bool case_sensitive
;
1613 char **name
, **ext
, *suffix
;
1615 /* Try whole file name first. */
1616 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1617 if (lang
->filenames
!= NULL
)
1618 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1619 if ((case_sensitive
)
1620 ? streq (*name
, file
)
1621 : strcaseeq (*name
, file
))
1624 /* If not found, try suffix after last dot. */
1625 suffix
= etags_strrchr (file
, '.');
1629 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1630 if (lang
->suffixes
!= NULL
)
1631 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1632 if ((case_sensitive
)
1633 ? streq (*ext
, suffix
)
1634 : strcaseeq (*ext
, suffix
))
1641 * This routine is called on each file argument.
1644 process_file_name (file
, lang
)
1648 struct stat stat_buf
;
1652 char *compressed_name
, *uncompressed_name
;
1653 char *ext
, *real_name
;
1656 canonicalize_filename (file
);
1657 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1659 error ("skipping inclusion of %s in self.", file
);
1662 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1664 compressed_name
= NULL
;
1665 real_name
= uncompressed_name
= savestr (file
);
1669 real_name
= compressed_name
= savestr (file
);
1670 uncompressed_name
= savenstr (file
, ext
- file
);
1673 /* If the canonicalized uncompressed name
1674 has already been dealt with, skip it silently. */
1675 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1677 assert (fdp
->infname
!= NULL
);
1678 if (streq (uncompressed_name
, fdp
->infname
))
1682 if (stat (real_name
, &stat_buf
) != 0)
1684 /* Reset real_name and try with a different name. */
1686 if (compressed_name
!= NULL
) /* try with the given suffix */
1688 if (stat (uncompressed_name
, &stat_buf
) == 0)
1689 real_name
= uncompressed_name
;
1691 else /* try all possible suffixes */
1693 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1695 compressed_name
= concat (file
, ".", compr
->suffix
);
1696 if (stat (compressed_name
, &stat_buf
) != 0)
1700 char *suf
= compressed_name
+ strlen (file
);
1701 size_t suflen
= strlen (compr
->suffix
) + 1;
1702 for ( ; suf
[1]; suf
++, suflen
--)
1704 memmove (suf
, suf
+ 1, suflen
);
1705 if (stat (compressed_name
, &stat_buf
) == 0)
1707 real_name
= compressed_name
;
1711 if (real_name
!= NULL
)
1714 free (compressed_name
);
1715 compressed_name
= NULL
;
1719 real_name
= compressed_name
;
1724 if (real_name
== NULL
)
1729 } /* try with a different name */
1731 if (!S_ISREG (stat_buf
.st_mode
))
1733 error ("skipping %s: it is not a regular file.", real_name
);
1736 if (real_name
== compressed_name
)
1738 char *cmd
= concat (compr
->command
, " ", real_name
);
1739 inf
= (FILE *) popen (cmd
, "r");
1743 inf
= fopen (real_name
, "r");
1750 process_file (inf
, uncompressed_name
, lang
);
1752 if (real_name
== compressed_name
)
1753 retval
= pclose (inf
);
1755 retval
= fclose (inf
);
1760 if (compressed_name
) free (compressed_name
);
1761 if (uncompressed_name
) free (uncompressed_name
);
1768 process_file (fh
, fn
, lang
)
1773 static const fdesc emptyfdesc
;
1776 /* Create a new input file description entry. */
1777 fdp
= xnew (1, fdesc
);
1780 fdp
->infname
= savestr (fn
);
1782 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1783 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1784 if (filename_is_absolute (fn
))
1786 /* An absolute file name. Canonicalize it. */
1787 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1791 /* A file name relative to cwd. Make it relative
1792 to the directory of the tags file. */
1793 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1795 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1797 fdp
->written
= FALSE
; /* not written on tags file yet */
1800 curfdp
= fdhead
; /* the current file description */
1804 /* If not Ctags, and if this is not metasource and if it contained no #line
1805 directives, we can write the tags and free all nodes pointing to
1808 && curfdp
->usecharno
/* no #line directives in this file */
1809 && !curfdp
->lang
->metasource
)
1813 /* Look for the head of the sublist relative to this file. See add_node
1814 for the structure of the node tree. */
1816 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1817 if (np
->fdp
== curfdp
)
1820 /* If we generated tags for this file, write and delete them. */
1823 /* This is the head of the last sublist, if any. The following
1824 instructions depend on this being true. */
1825 assert (np
->left
== NULL
);
1827 assert (fdhead
== curfdp
);
1828 assert (last_node
->fdp
== curfdp
);
1829 put_entries (np
); /* write tags for file curfdp->taggedfname */
1830 free_tree (np
); /* remove the written nodes */
1832 nodehead
= NULL
; /* no nodes left */
1834 prev
->left
= NULL
; /* delete the pointer to the sublist */
1840 * This routine sets up the boolean pseudo-functions which work
1841 * by setting boolean flags dependent upon the corresponding character.
1842 * Every char which is NOT in that string is not a white char. Therefore,
1843 * all of the array "_wht" is set to FALSE, and then the elements
1844 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1845 * of a char is TRUE if it is the string "white", else FALSE.
1853 for (i
= 0; i
< CHARS
; i
++)
1854 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1855 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1856 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1857 notinname('\0') = notinname('\n');
1858 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1859 begtoken('\0') = begtoken('\n');
1860 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1861 intoken('\0') = intoken('\n');
1862 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1863 endtoken('\0') = endtoken('\n');
1867 * This routine opens the specified file and calls the function
1868 * which finds the function and type definitions.
1875 language
*lang
= curfdp
->lang
;
1876 Lang_function
*parser
= NULL
;
1878 /* If user specified a language, use it. */
1879 if (lang
!= NULL
&& lang
->function
!= NULL
)
1881 parser
= lang
->function
;
1884 /* Else try to guess the language given the file name. */
1887 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1888 if (lang
!= NULL
&& lang
->function
!= NULL
)
1890 curfdp
->lang
= lang
;
1891 parser
= lang
->function
;
1895 /* Else look for sharp-bang as the first two characters. */
1897 && readline_internal (&lb
, inf
) > 0
1899 && lb
.buffer
[0] == '#'
1900 && lb
.buffer
[1] == '!')
1904 /* Set lp to point at the first char after the last slash in the
1905 line or, if no slashes, at the first nonblank. Then set cp to
1906 the first successive blank and terminate the string. */
1907 lp
= etags_strrchr (lb
.buffer
+2, '/');
1911 lp
= skip_spaces (lb
.buffer
+ 2);
1912 cp
= skip_non_spaces (lp
);
1915 if (strlen (lp
) > 0)
1917 lang
= get_language_from_interpreter (lp
);
1918 if (lang
!= NULL
&& lang
->function
!= NULL
)
1920 curfdp
->lang
= lang
;
1921 parser
= lang
->function
;
1926 /* We rewind here, even if inf may be a pipe. We fail if the
1927 length of the first line is longer than the pipe block size,
1928 which is unlikely. */
1931 /* Else try to guess the language given the case insensitive file name. */
1934 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1935 if (lang
!= NULL
&& lang
->function
!= NULL
)
1937 curfdp
->lang
= lang
;
1938 parser
= lang
->function
;
1942 /* Else try Fortran or C. */
1945 node
*old_last_node
= last_node
;
1947 curfdp
->lang
= get_language_from_langname ("fortran");
1950 if (old_last_node
== last_node
)
1951 /* No Fortran entries found. Try C. */
1953 /* We do not tag if rewind fails.
1954 Only the file name will be recorded in the tags file. */
1956 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1962 if (!no_line_directive
1963 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1964 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1965 file, or anyway we parsed a file that is automatically generated from
1966 this one. If this is the case, the bingo.c file contained #line
1967 directives that generated tags pointing to this file. Let's delete
1968 them all before parsing this file, which is the real source. */
1970 fdesc
**fdpp
= &fdhead
;
1971 while (*fdpp
!= NULL
)
1973 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1974 /* We found one of those! We must delete both the file description
1975 and all tags referring to it. */
1977 fdesc
*badfdp
= *fdpp
;
1979 /* Delete the tags referring to badfdp->taggedfname
1980 that were obtained from badfdp->infname. */
1981 invalidate_nodes (badfdp
, &nodehead
);
1983 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1984 free_fdesc (badfdp
);
1987 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1990 assert (parser
!= NULL
);
1992 /* Generic initialisations before reading from file. */
1993 linebuffer_setlen (&filebuf
, 0); /* reset the file buffer */
1995 /* Generic initialisations before parsing file with readline. */
1996 lineno
= 0; /* reset global line number */
1997 charno
= 0; /* reset global char number */
1998 linecharno
= 0; /* reset global char number of line start */
2002 regex_tag_multiline ();
2007 * Check whether an implicitly named tag should be created,
2008 * then call `pfnote'.
2009 * NAME is a string that is internally copied by this function.
2011 * TAGS format specification
2012 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
2013 * The following is explained in some more detail in etc/ETAGS.EBNF.
2015 * make_tag creates tags with "implicit tag names" (unnamed tags)
2016 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
2017 * 1. NAME does not contain any of the characters in NONAM;
2018 * 2. LINESTART contains name as either a rightmost, or rightmost but
2019 * one character, substring;
2020 * 3. the character, if any, immediately before NAME in LINESTART must
2021 * be a character in NONAM;
2022 * 4. the character, if any, immediately after NAME in LINESTART must
2023 * also be a character in NONAM.
2025 * The implementation uses the notinname() macro, which recognises the
2026 * characters stored in the string `nonam'.
2027 * etags.el needs to use the same characters that are in NONAM.
2030 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
2031 char *name
; /* tag name, or NULL if unnamed */
2032 int namelen
; /* tag length */
2033 bool is_func
; /* tag is a function */
2034 char *linestart
; /* start of the line where tag is */
2035 int linelen
; /* length of the line where tag is */
2036 int lno
; /* line number */
2037 long cno
; /* character number */
2039 bool named
= (name
!= NULL
&& namelen
> 0);
2041 if (!CTAGS
&& named
) /* maybe set named to false */
2042 /* Let's try to make an implicit tag name, that is, create an unnamed tag
2043 such that etags.el can guess a name from it. */
2046 register char *cp
= name
;
2048 for (i
= 0; i
< namelen
; i
++)
2049 if (notinname (*cp
++))
2051 if (i
== namelen
) /* rule #1 */
2053 cp
= linestart
+ linelen
- namelen
;
2054 if (notinname (linestart
[linelen
-1]))
2055 cp
-= 1; /* rule #4 */
2056 if (cp
>= linestart
/* rule #2 */
2058 || notinname (cp
[-1])) /* rule #3 */
2059 && strneq (name
, cp
, namelen
)) /* rule #2 */
2060 named
= FALSE
; /* use implicit tag name */
2065 name
= savenstr (name
, namelen
);
2068 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
2073 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
2074 char *name
; /* tag name, or NULL if unnamed */
2075 bool is_func
; /* tag is a function */
2076 char *linestart
; /* start of the line where tag is */
2077 int linelen
; /* length of the line where tag is */
2078 int lno
; /* line number */
2079 long cno
; /* character number */
2083 assert (name
== NULL
|| name
[0] != '\0');
2084 if (CTAGS
&& name
== NULL
)
2087 np
= xnew (1, node
);
2089 /* If ctags mode, change name "main" to M<thisfilename>. */
2090 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
2092 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
2093 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
2094 fp
= etags_strrchr (np
->name
, '.');
2095 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
2101 np
->been_warned
= FALSE
;
2103 np
->is_func
= is_func
;
2105 if (np
->fdp
->usecharno
)
2106 /* Our char numbers are 0-base, because of C language tradition?
2107 ctags compatibility? old versions compatibility? I don't know.
2108 Anyway, since emacs's are 1-base we expect etags.el to take care
2109 of the difference. If we wanted to have 1-based numbers, we would
2110 uncomment the +1 below. */
2111 np
->cno
= cno
/* + 1 */ ;
2113 np
->cno
= invalidcharno
;
2114 np
->left
= np
->right
= NULL
;
2115 if (CTAGS
&& !cxref_style
)
2117 if (strlen (linestart
) < 50)
2118 np
->regex
= concat (linestart
, "$", "");
2120 np
->regex
= savenstr (linestart
, 50);
2123 np
->regex
= savenstr (linestart
, linelen
);
2125 add_node (np
, &nodehead
);
2130 * recurse on left children, iterate on right children.
2138 register node
*node_right
= np
->right
;
2139 free_tree (np
->left
);
2140 if (np
->name
!= NULL
)
2150 * delete a file description
2154 register fdesc
*fdp
;
2156 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
2157 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
2158 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
2159 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
2160 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
2166 * Adds a node to the tree of nodes. In etags mode, sort by file
2167 * name. In ctags mode, sort by tag name. Make no attempt at
2170 * add_node is the only function allowed to add nodes, so it can
2174 add_node (np
, cur_node_p
)
2175 node
*np
, **cur_node_p
;
2178 register node
*cur_node
= *cur_node_p
;
2180 if (cur_node
== NULL
)
2190 /* For each file name, tags are in a linked sublist on the right
2191 pointer. The first tags of different files are a linked list
2192 on the left pointer. last_node points to the end of the last
2194 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
2196 /* Let's use the same sublist as the last added node. */
2197 assert (last_node
->right
== NULL
);
2198 last_node
->right
= np
;
2201 else if (cur_node
->fdp
== np
->fdp
)
2203 /* Scanning the list we found the head of a sublist which is
2204 good for us. Let's scan this sublist. */
2205 add_node (np
, &cur_node
->right
);
2208 /* The head of this sublist is not good for us. Let's try the
2210 add_node (np
, &cur_node
->left
);
2211 } /* if ETAGS mode */
2216 dif
= strcmp (np
->name
, cur_node
->name
);
2219 * If this tag name matches an existing one, then
2220 * do not add the node, but maybe print a warning.
2222 if (no_duplicates
&& !dif
)
2224 if (np
->fdp
== cur_node
->fdp
)
2228 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
2229 np
->fdp
->infname
, lineno
, np
->name
);
2230 fprintf (stderr
, "Second entry ignored\n");
2233 else if (!cur_node
->been_warned
&& !no_warnings
)
2237 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2238 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2239 cur_node
->been_warned
= TRUE
;
2244 /* Actually add the node */
2245 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2246 } /* if CTAGS mode */
2250 * invalidate_nodes ()
2251 * Scan the node tree and invalidate all nodes pointing to the
2252 * given file description (CTAGS case) or free them (ETAGS case).
2255 invalidate_nodes (badfdp
, npp
)
2266 if (np
->left
!= NULL
)
2267 invalidate_nodes (badfdp
, &np
->left
);
2268 if (np
->fdp
== badfdp
)
2270 if (np
->right
!= NULL
)
2271 invalidate_nodes (badfdp
, &np
->right
);
2275 assert (np
->fdp
!= NULL
);
2276 if (np
->fdp
== badfdp
)
2278 *npp
= np
->left
; /* detach the sublist from the list */
2279 np
->left
= NULL
; /* isolate it */
2280 free_tree (np
); /* free it */
2281 invalidate_nodes (badfdp
, npp
);
2284 invalidate_nodes (badfdp
, &np
->left
);
2289 static int total_size_of_entries
__P((node
*));
2290 static int number_len
__P((long));
2292 /* Length of a non-negative number's decimal representation. */
2298 while ((num
/= 10) > 0)
2304 * Return total number of characters that put_entries will output for
2305 * the nodes in the linked list at the right of the specified node.
2306 * This count is irrelevant with etags.el since emacs 19.34 at least,
2307 * but is still supplied for backward compatibility.
2310 total_size_of_entries (np
)
2313 register int total
= 0;
2315 for (; np
!= NULL
; np
= np
->right
)
2318 total
+= strlen (np
->regex
) + 1; /* pat\177 */
2319 if (np
->name
!= NULL
)
2320 total
+= strlen (np
->name
) + 1; /* name\001 */
2321 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2322 if (np
->cno
!= invalidcharno
) /* cno */
2323 total
+= number_len (np
->cno
);
2324 total
+= 1; /* newline */
2335 static fdesc
*fdp
= NULL
;
2340 /* Output subentries that precede this one */
2342 put_entries (np
->left
);
2344 /* Output this entry */
2353 fprintf (tagf
, "\f\n%s,%d\n",
2354 fdp
->taggedfname
, total_size_of_entries (np
));
2355 fdp
->written
= TRUE
;
2357 fputs (np
->regex
, tagf
);
2358 fputc ('\177', tagf
);
2359 if (np
->name
!= NULL
)
2361 fputs (np
->name
, tagf
);
2362 fputc ('\001', tagf
);
2364 fprintf (tagf
, "%d,", np
->lno
);
2365 if (np
->cno
!= invalidcharno
)
2366 fprintf (tagf
, "%ld", np
->cno
);
2372 if (np
->name
== NULL
)
2373 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2378 fprintf (stdout
, "%s %s %d\n",
2379 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2381 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2382 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->regex
);
2386 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2389 { /* function or #define macro with args */
2390 putc (searchar
, tagf
);
2393 for (sp
= np
->regex
; *sp
; sp
++)
2395 if (*sp
== '\\' || *sp
== searchar
)
2399 putc (searchar
, tagf
);
2402 { /* anything else; text pattern inadequate */
2403 fprintf (tagf
, "%d", np
->lno
);
2408 } /* if this node contains a valid tag */
2410 /* Output subentries that follow this one */
2411 put_entries (np
->right
);
2413 put_entries (np
->left
);
2418 #define C_EXT 0x00fff /* C extensions */
2419 #define C_PLAIN 0x00000 /* C */
2420 #define C_PLPL 0x00001 /* C++ */
2421 #define C_STAR 0x00003 /* C* */
2422 #define C_JAVA 0x00005 /* JAVA */
2423 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2424 #define YACC 0x10000 /* yacc file */
2427 * The C symbol tables.
2432 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2434 st_C_ignore
, st_C_attribute
,
2437 st_C_class
, st_C_template
,
2438 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
2441 static unsigned int hash
__P((const char *, unsigned int));
2442 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2443 static enum sym_type C_symtype
__P((char *, int, int));
2445 /* Feed stuff between (but not including) %[ and %] lines to:
2451 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2455 while, 0, st_C_ignore
2456 switch, 0, st_C_ignore
2457 return, 0, st_C_ignore
2458 __attribute__, 0, st_C_attribute
2459 @interface, 0, st_C_objprot
2460 @protocol, 0, st_C_objprot
2461 @implementation,0, st_C_objimpl
2462 @end, 0, st_C_objend
2463 import, (C_JAVA & ~C_PLPL), st_C_ignore
2464 package, (C_JAVA & ~C_PLPL), st_C_ignore
2465 friend, C_PLPL, st_C_ignore
2466 extends, (C_JAVA & ~C_PLPL), st_C_javastruct
2467 implements, (C_JAVA & ~C_PLPL), st_C_javastruct
2468 interface, (C_JAVA & ~C_PLPL), st_C_struct
2469 class, 0, st_C_class
2470 namespace, C_PLPL, st_C_struct
2471 domain, C_STAR, st_C_struct
2472 union, 0, st_C_struct
2473 struct, 0, st_C_struct
2474 extern, 0, st_C_extern
2476 typedef, 0, st_C_typedef
2477 define, 0, st_C_define
2478 undef, 0, st_C_define
2479 operator, C_PLPL, st_C_operator
2480 template, 0, st_C_template
2481 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2482 DEFUN, 0, st_C_gnumacro
2483 SYSCALL, 0, st_C_gnumacro
2484 ENTRY, 0, st_C_gnumacro
2485 PSEUDO, 0, st_C_gnumacro
2486 # These are defined inside C functions, so currently they are not met.
2487 # EXFUN used in glibc, DEFVAR_* in emacs.
2488 #EXFUN, 0, st_C_gnumacro
2489 #DEFVAR_, 0, st_C_gnumacro
2491 and replace lines between %< and %> with its output, then:
2492 - remove the #if characterset check
2493 - make in_word_set static and not inline. */
2495 /* C code produced by gperf version 3.0.1 */
2496 /* Command-line: gperf -m 5 */
2497 /* Computed positions: -k'2-3' */
2499 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2500 /* maximum key range = 33, duplicates = 0 */
2511 register const char *str
;
2512 register unsigned int len
;
2514 static unsigned char asso_values
[] =
2516 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2517 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2518 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2519 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2520 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2521 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2522 35, 35, 35, 35, 35, 35, 35, 35, 35, 15,
2523 14, 35, 35, 35, 35, 35, 35, 35, 14, 35,
2524 35, 35, 35, 12, 13, 35, 35, 35, 35, 12,
2525 35, 35, 35, 35, 35, 1, 35, 16, 35, 6,
2526 23, 0, 0, 35, 22, 0, 35, 35, 5, 0,
2527 0, 15, 1, 35, 6, 35, 8, 19, 35, 16,
2528 4, 5, 35, 35, 35, 35, 35, 35, 35, 35,
2529 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2530 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2531 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2532 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2533 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2534 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2535 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2536 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2537 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2538 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2539 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2540 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
2541 35, 35, 35, 35, 35, 35
2543 register int hval
= len
;
2548 hval
+= asso_values
[(unsigned char)str
[2]];
2551 hval
+= asso_values
[(unsigned char)str
[1]];
2557 static struct C_stab_entry
*
2558 in_word_set (str
, len
)
2559 register const char *str
;
2560 register unsigned int len
;
2564 TOTAL_KEYWORDS
= 32,
2565 MIN_WORD_LENGTH
= 2,
2566 MAX_WORD_LENGTH
= 15,
2571 static struct C_stab_entry wordlist
[] =
2574 {"if", 0, st_C_ignore
},
2576 {"@end", 0, st_C_objend
},
2577 {"union", 0, st_C_struct
},
2578 {"define", 0, st_C_define
},
2579 {"import", (C_JAVA
& ~C_PLPL
), st_C_ignore
},
2580 {"template", 0, st_C_template
},
2581 {"operator", C_PLPL
, st_C_operator
},
2582 {"@interface", 0, st_C_objprot
},
2583 {"implements", (C_JAVA
& ~C_PLPL
), st_C_javastruct
},
2584 {"friend", C_PLPL
, st_C_ignore
},
2585 {"typedef", 0, st_C_typedef
},
2586 {"return", 0, st_C_ignore
},
2587 {"@implementation",0, st_C_objimpl
},
2588 {"@protocol", 0, st_C_objprot
},
2589 {"interface", (C_JAVA
& ~C_PLPL
), st_C_struct
},
2590 {"extern", 0, st_C_extern
},
2591 {"extends", (C_JAVA
& ~C_PLPL
), st_C_javastruct
},
2592 {"struct", 0, st_C_struct
},
2593 {"domain", C_STAR
, st_C_struct
},
2594 {"switch", 0, st_C_ignore
},
2595 {"enum", 0, st_C_enum
},
2596 {"for", 0, st_C_ignore
},
2597 {"namespace", C_PLPL
, st_C_struct
},
2598 {"class", 0, st_C_class
},
2599 {"while", 0, st_C_ignore
},
2600 {"undef", 0, st_C_define
},
2601 {"package", (C_JAVA
& ~C_PLPL
), st_C_ignore
},
2602 {"__attribute__", 0, st_C_attribute
},
2603 {"SYSCALL", 0, st_C_gnumacro
},
2604 {"ENTRY", 0, st_C_gnumacro
},
2605 {"PSEUDO", 0, st_C_gnumacro
},
2606 {"DEFUN", 0, st_C_gnumacro
}
2609 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2611 register int key
= hash (str
, len
);
2613 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2615 register const char *s
= wordlist
[key
].name
;
2617 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1) && s
[len
] == '\0')
2618 return &wordlist
[key
];
2625 static enum sym_type
2626 C_symtype (str
, len
, c_ext
)
2631 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2633 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2640 * Ignoring __attribute__ ((list))
2642 static bool inattribute
; /* looking at an __attribute__ construct */
2645 * C functions and variables are recognized using a simple
2646 * finite automaton. fvdef is its state variable.
2650 fvnone
, /* nothing seen */
2651 fdefunkey
, /* Emacs DEFUN keyword seen */
2652 fdefunname
, /* Emacs DEFUN name seen */
2653 foperator
, /* func: operator keyword seen (cplpl) */
2654 fvnameseen
, /* function or variable name seen */
2655 fstartlist
, /* func: just after open parenthesis */
2656 finlist
, /* func: in parameter list */
2657 flistseen
, /* func: after parameter list */
2658 fignore
, /* func: before open brace */
2659 vignore
/* var-like: ignore until ';' */
2662 static bool fvextern
; /* func or var: extern keyword seen; */
2665 * typedefs are recognized using a simple finite automaton.
2666 * typdef is its state variable.
2670 tnone
, /* nothing seen */
2671 tkeyseen
, /* typedef keyword seen */
2672 ttypeseen
, /* defined type seen */
2673 tinbody
, /* inside typedef body */
2674 tend
, /* just before typedef tag */
2675 tignore
/* junk after typedef tag */
2679 * struct-like structures (enum, struct and union) are recognized
2680 * using another simple finite automaton. `structdef' is its state
2685 snone
, /* nothing seen yet,
2686 or in struct body if bracelev > 0 */
2687 skeyseen
, /* struct-like keyword seen */
2688 stagseen
, /* struct-like tag seen */
2689 scolonseen
/* colon seen after struct-like tag */
2693 * When objdef is different from onone, objtag is the name of the class.
2695 static char *objtag
= "<uninited>";
2698 * Yet another little state machine to deal with preprocessor lines.
2702 dnone
, /* nothing seen */
2703 dsharpseen
, /* '#' seen as first char on line */
2704 ddefineseen
, /* '#' and 'define' seen */
2705 dignorerest
/* ignore rest of line */
2709 * State machine for Objective C protocols and implementations.
2710 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2714 onone
, /* nothing seen */
2715 oprotocol
, /* @interface or @protocol seen */
2716 oimplementation
, /* @implementations seen */
2717 otagseen
, /* class name seen */
2718 oparenseen
, /* parenthesis before category seen */
2719 ocatseen
, /* category name seen */
2720 oinbody
, /* in @implementation body */
2721 omethodsign
, /* in @implementation body, after +/- */
2722 omethodtag
, /* after method name */
2723 omethodcolon
, /* after method colon */
2724 omethodparm
, /* after method parameter */
2725 oignore
/* wait for @end */
2730 * Use this structure to keep info about the token read, and how it
2731 * should be tagged. Used by the make_C_tag function to build a tag.
2735 char *line
; /* string containing the token */
2736 int offset
; /* where the token starts in LINE */
2737 int length
; /* token length */
2739 The previous members can be used to pass strings around for generic
2740 purposes. The following ones specifically refer to creating tags. In this
2741 case the token contained here is the pattern that will be used to create a
2744 bool valid
; /* do not create a tag; the token should be
2745 invalidated whenever a state machine is
2746 reset prematurely */
2747 bool named
; /* create a named tag */
2748 int lineno
; /* source line number of tag */
2749 long linepos
; /* source char number of tag */
2750 } token
; /* latest token read */
2753 * Variables and functions for dealing with nested structures.
2754 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2756 static void pushclass_above
__P((int, char *, int));
2757 static void popclass_above
__P((int));
2758 static void write_classname
__P((linebuffer
*, char *qualifier
));
2761 char **cname
; /* nested class names */
2762 int *bracelev
; /* nested class brace level */
2763 int nl
; /* class nesting level (elements used) */
2764 int size
; /* length of the array */
2765 } cstack
; /* stack for nested declaration tags */
2766 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2767 #define nestlev (cstack.nl)
2768 /* After struct keyword or in struct body, not inside a nested function. */
2769 #define instruct (structdef == snone && nestlev > 0 \
2770 && bracelev == cstack.bracelev[nestlev-1] + 1)
2773 pushclass_above (bracelev
, str
, len
)
2780 popclass_above (bracelev
);
2782 if (nl
>= cstack
.size
)
2784 int size
= cstack
.size
*= 2;
2785 xrnew (cstack
.cname
, size
, char *);
2786 xrnew (cstack
.bracelev
, size
, int);
2788 assert (nl
== 0 || cstack
.bracelev
[nl
-1] < bracelev
);
2789 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2790 cstack
.bracelev
[nl
] = bracelev
;
2795 popclass_above (bracelev
)
2800 for (nl
= cstack
.nl
- 1;
2801 nl
>= 0 && cstack
.bracelev
[nl
] >= bracelev
;
2804 if (cstack
.cname
[nl
] != NULL
)
2805 free (cstack
.cname
[nl
]);
2811 write_classname (cn
, qualifier
)
2816 int qlen
= strlen (qualifier
);
2818 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2822 cn
->buffer
[0] = '\0';
2826 len
= strlen (cstack
.cname
[0]);
2827 linebuffer_setlen (cn
, len
);
2828 strcpy (cn
->buffer
, cstack
.cname
[0]);
2830 for (i
= 1; i
< cstack
.nl
; i
++)
2835 s
= cstack
.cname
[i
];
2840 linebuffer_setlen (cn
, len
);
2841 strncat (cn
->buffer
, qualifier
, qlen
);
2842 strncat (cn
->buffer
, s
, slen
);
2847 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2848 static void make_C_tag
__P((bool));
2852 * checks to see if the current token is at the start of a
2853 * function or variable, or corresponds to a typedef, or
2854 * is a struct/union/enum tag, or #define, or an enum constant.
2856 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2857 * with args. C_EXTP points to which language we are looking at.
2868 consider_token (str
, len
, c
, c_extp
, bracelev
, parlev
, is_func_or_var
)
2869 register char *str
; /* IN: token pointer */
2870 register int len
; /* IN: token length */
2871 register int c
; /* IN: first char after the token */
2872 int *c_extp
; /* IN, OUT: C extensions mask */
2873 int bracelev
; /* IN: brace level */
2874 int parlev
; /* IN: parenthesis level */
2875 bool *is_func_or_var
; /* OUT: function or variable found */
2877 /* When structdef is stagseen, scolonseen, or snone with bracelev > 0,
2878 structtype is the type of the preceding struct-like keyword, and
2879 structbracelev is the brace level where it has been seen. */
2880 static enum sym_type structtype
;
2881 static int structbracelev
;
2882 static enum sym_type toktype
;
2885 toktype
= C_symtype (str
, len
, *c_extp
);
2888 * Skip __attribute__
2890 if (toktype
== st_C_attribute
)
2897 * Advance the definedef state machine.
2902 /* We're not on a preprocessor line. */
2903 if (toktype
== st_C_gnumacro
)
2910 if (toktype
== st_C_define
)
2912 definedef
= ddefineseen
;
2916 definedef
= dignorerest
;
2921 * Make a tag for any macro, unless it is a constant
2922 * and constantypedefs is FALSE.
2924 definedef
= dignorerest
;
2925 *is_func_or_var
= (c
== '(');
2926 if (!*is_func_or_var
&& !constantypedefs
)
2933 error ("internal error: definedef value.", (char *)NULL
);
2942 if (toktype
== st_C_typedef
)
2962 if (structdef
== snone
&& fvdef
== fvnone
)
2980 * This structdef business is NOT invoked when we are ctags and the
2981 * file is plain C. This is because a struct tag may have the same
2982 * name as another tag, and this loses with ctags.
2986 case st_C_javastruct
:
2987 if (structdef
== stagseen
)
2988 structdef
= scolonseen
;
2992 if ((*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2994 && definedef
== dnone
&& structdef
== snone
2995 && typdef
== tnone
&& fvdef
== fvnone
)
2996 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2997 if (toktype
== st_C_template
)
3004 && (typdef
== tkeyseen
3005 || (typedefs_or_cplusplus
&& structdef
== snone
)))
3007 structdef
= skeyseen
;
3008 structtype
= toktype
;
3009 structbracelev
= bracelev
;
3010 if (fvdef
== fvnameseen
)
3016 if (structdef
== skeyseen
)
3018 structdef
= stagseen
;
3022 if (typdef
!= tnone
)
3025 /* Detect Objective C constructs. */
3035 objdef
= oimplementation
;
3039 case oimplementation
:
3040 /* Save the class tag for functions or variables defined inside. */
3041 objtag
= savenstr (str
, len
);
3045 /* Save the class tag for categories. */
3046 objtag
= savenstr (str
, len
);
3048 *is_func_or_var
= TRUE
;
3052 *is_func_or_var
= TRUE
;
3060 objdef
= omethodtag
;
3061 linebuffer_setlen (&token_name
, len
);
3062 strncpy (token_name
.buffer
, str
, len
);
3063 token_name
.buffer
[len
] = '\0';
3069 objdef
= omethodparm
;
3075 objdef
= omethodtag
;
3076 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
3077 strncat (token_name
.buffer
, str
, len
);
3082 if (toktype
== st_C_objend
)
3084 /* Memory leakage here: the string pointed by objtag is
3085 never released, because many tests would be needed to
3086 avoid breaking on incorrect input code. The amount of
3087 memory leaked here is the sum of the lengths of the
3095 /* A function, variable or enum constant? */
3117 *is_func_or_var
= TRUE
;
3121 && structdef
== snone
3122 && structtype
== st_C_enum
&& bracelev
> structbracelev
)
3123 return TRUE
; /* enum constant */
3129 fvdef
= fdefunname
; /* GNU macro */
3130 *is_func_or_var
= TRUE
;
3138 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
3139 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
3148 if (len
>= 10 && strneq (str
+len
-10, "::operator", 10))
3150 if (*c_extp
& C_AUTO
) /* automatic detection of C++ */
3151 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
3153 *is_func_or_var
= TRUE
;
3156 if (bracelev
> 0 && !instruct
)
3158 fvdef
= fvnameseen
; /* function or variable */
3159 *is_func_or_var
= TRUE
;
3170 * C_entries often keeps pointers to tokens or lines which are older than
3171 * the line currently read. By keeping two line buffers, and switching
3172 * them at end of line, it is possible to use those pointers.
3180 #define current_lb_is_new (newndx == curndx)
3181 #define switch_line_buffers() (curndx = 1 - curndx)
3183 #define curlb (lbs[curndx].lb)
3184 #define newlb (lbs[newndx].lb)
3185 #define curlinepos (lbs[curndx].linepos)
3186 #define newlinepos (lbs[newndx].linepos)
3188 #define plainc ((c_ext & C_EXT) == C_PLAIN)
3189 #define cplpl (c_ext & C_PLPL)
3190 #define cjava ((c_ext & C_JAVA) == C_JAVA)
3192 #define CNL_SAVE_DEFINEDEF() \
3194 curlinepos = charno; \
3195 readline (&curlb, inf); \
3196 lp = curlb.buffer; \
3203 CNL_SAVE_DEFINEDEF(); \
3204 if (savetoken.valid) \
3206 token = savetoken; \
3207 savetoken.valid = FALSE; \
3209 definedef = dnone; \
3217 /* This function is never called when token.valid is FALSE, but
3218 we must protect against invalid input or internal errors. */
3219 if (!DEBUG
&& !token
.valid
)
3223 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3224 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3225 else /* this case is optimised away if !DEBUG */
3226 make_tag (concat ("INVALID TOKEN:-->", token_name
.buffer
, ""),
3227 token_name
.len
+ 17, isfun
, token
.line
,
3228 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3230 token
.valid
= FALSE
;
3236 * This routine finds functions, variables, typedefs,
3237 * #define's, enum constants and struct/union/enum definitions in
3238 * C syntax and adds them to the list.
3241 C_entries (c_ext
, inf
)
3242 int c_ext
; /* extension of C */
3243 FILE *inf
; /* input file */
3245 register char c
; /* latest char read; '\0' for end of line */
3246 register char *lp
; /* pointer one beyond the character `c' */
3247 int curndx
, newndx
; /* indices for current and new lb */
3248 register int tokoff
; /* offset in line of start of current token */
3249 register int toklen
; /* length of current token */
3250 char *qualifier
; /* string used to qualify names */
3251 int qlen
; /* length of qualifier */
3252 int bracelev
; /* current brace level */
3253 int bracketlev
; /* current bracket level */
3254 int parlev
; /* current parenthesis level */
3255 int attrparlev
; /* __attribute__ parenthesis level */
3256 int templatelev
; /* current template level */
3257 int typdefbracelev
; /* bracelev where a typedef struct body begun */
3258 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3259 bool yacc_rules
; /* in the rules part of a yacc file */
3260 struct tok savetoken
= {0}; /* token saved during preprocessor handling */
3263 linebuffer_init (&lbs
[0].lb
);
3264 linebuffer_init (&lbs
[1].lb
);
3265 if (cstack
.size
== 0)
3267 cstack
.size
= (DEBUG
) ? 1 : 4;
3269 cstack
.cname
= xnew (cstack
.size
, char *);
3270 cstack
.bracelev
= xnew (cstack
.size
, int);
3273 tokoff
= toklen
= typdefbracelev
= 0; /* keep compiler quiet */
3274 curndx
= newndx
= 0;
3278 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3279 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3281 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3282 token
.valid
= savetoken
.valid
= FALSE
;
3283 bracelev
= bracketlev
= parlev
= attrparlev
= templatelev
= 0;
3285 { qualifier
= "."; qlen
= 1; }
3287 { qualifier
= "::"; qlen
= 2; }
3295 /* If we are at the end of the line, the next character is a
3296 '\0'; do not skip it, because it is what tells us
3297 to read the next line. */
3318 /* Newlines inside comments do not end macro definitions in
3320 CNL_SAVE_DEFINEDEF ();
3333 /* Newlines inside strings do not end macro definitions
3334 in traditional cpp, even though compilers don't
3335 usually accept them. */
3336 CNL_SAVE_DEFINEDEF ();
3346 /* Hmmm, something went wrong. */
3355 else if (bracketlev
> 0)
3360 if (--bracketlev
> 0)
3364 CNL_SAVE_DEFINEDEF ();
3392 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3405 else if (/* cplpl && */ *lp
== '/')
3413 if ((c_ext
& YACC
) && *lp
== '%')
3415 /* Entering or exiting rules section in yacc file. */
3417 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3418 typdef
= tnone
; structdef
= snone
;
3419 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3421 yacc_rules
= !yacc_rules
;
3427 if (definedef
== dnone
)
3430 bool cpptoken
= TRUE
;
3432 /* Look back on this line. If all blanks, or nonblanks
3433 followed by an end of comment, this is a preprocessor
3435 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3438 if (*cp
== '*' && *(cp
+1) == '/')
3447 definedef
= dsharpseen
;
3448 } /* if (definedef == dnone) */
3456 /* Consider token only if some involved conditions are satisfied. */
3457 if (typdef
!= tignore
3458 && definedef
!= dignorerest
3461 && (definedef
!= dnone
3462 || structdef
!= scolonseen
)
3469 if (c
== ':' && *lp
== ':' && begtoken (lp
[1]))
3470 /* This handles :: in the middle,
3471 but not at the beginning of an identifier.
3472 Also, space-separated :: is not recognised. */
3474 if (c_ext
& C_AUTO
) /* automatic detection of C++ */
3475 c_ext
= (c_ext
| C_PLPL
) & ~C_AUTO
;
3479 goto still_in_token
;
3483 bool funorvar
= FALSE
;
3486 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3487 &c_ext
, bracelev
, parlev
,
3490 if (fvdef
== foperator
)
3493 lp
= skip_spaces (lp
-1);
3497 && !iswhite (*lp
) && *lp
!= '(')
3500 toklen
+= lp
- oldlp
;
3502 token
.named
= FALSE
;
3504 && nestlev
> 0 && definedef
== dnone
)
3505 /* in struct body */
3507 write_classname (&token_name
, qualifier
);
3508 linebuffer_setlen (&token_name
,
3509 token_name
.len
+qlen
+toklen
);
3510 strcat (token_name
.buffer
, qualifier
);
3511 strncat (token_name
.buffer
,
3512 newlb
.buffer
+ tokoff
, toklen
);
3515 else if (objdef
== ocatseen
)
3516 /* Objective C category */
3518 int len
= strlen (objtag
) + 2 + toklen
;
3519 linebuffer_setlen (&token_name
, len
);
3520 strcpy (token_name
.buffer
, objtag
);
3521 strcat (token_name
.buffer
, "(");
3522 strncat (token_name
.buffer
,
3523 newlb
.buffer
+ tokoff
, toklen
);
3524 strcat (token_name
.buffer
, ")");
3527 else if (objdef
== omethodtag
3528 || objdef
== omethodparm
)
3529 /* Objective C method */
3533 else if (fvdef
== fdefunname
)
3534 /* GNU DEFUN and similar macros */
3536 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3540 /* Rewrite the tag so that emacs lisp DEFUNs
3541 can be found by their elisp name */
3547 linebuffer_setlen (&token_name
, len
);
3548 strncpy (token_name
.buffer
,
3549 newlb
.buffer
+ off
, len
);
3550 token_name
.buffer
[len
] = '\0';
3553 if (token_name
.buffer
[len
] == '_')
3554 token_name
.buffer
[len
] = '-';
3555 token
.named
= defun
;
3559 linebuffer_setlen (&token_name
, toklen
);
3560 strncpy (token_name
.buffer
,
3561 newlb
.buffer
+ tokoff
, toklen
);
3562 token_name
.buffer
[toklen
] = '\0';
3563 /* Name macros and members. */
3564 token
.named
= (structdef
== stagseen
3565 || typdef
== ttypeseen
3568 && definedef
== dignorerest
)
3570 && definedef
== dnone
3571 && structdef
== snone
3574 token
.lineno
= lineno
;
3575 token
.offset
= tokoff
;
3576 token
.length
= toklen
;
3577 token
.line
= newlb
.buffer
;
3578 token
.linepos
= newlinepos
;
3581 if (definedef
== dnone
3582 && (fvdef
== fvnameseen
3583 || fvdef
== foperator
3584 || structdef
== stagseen
3586 || typdef
== ttypeseen
3587 || objdef
!= onone
))
3589 if (current_lb_is_new
)
3590 switch_line_buffers ();
3592 else if (definedef
!= dnone
3593 || fvdef
== fdefunname
3595 make_C_tag (funorvar
);
3597 else /* not yacc and consider_token failed */
3599 if (inattribute
&& fvdef
== fignore
)
3601 /* We have just met __attribute__ after a
3602 function parameter list: do not tag the
3609 } /* if (endtoken (c)) */
3610 else if (intoken (c
))
3616 } /* if (midtoken) */
3617 else if (begtoken (c
))
3625 /* This prevents tagging fb in
3626 void (__attribute__((noreturn)) *fb) (void);
3627 Fixing this is not easy and not very important. */
3631 if (plainc
|| declarations
)
3633 make_C_tag (TRUE
); /* a function */
3638 if (structdef
== stagseen
&& !cjava
)
3640 popclass_above (bracelev
);
3648 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3650 tokoff
= lp
- 1 - newlb
.buffer
;
3655 } /* if (begtoken) */
3656 } /* if must look at token */
3659 /* Detect end of line, colon, comma, semicolon and various braces
3660 after having handled a token.*/
3666 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3668 make_C_tag (FALSE
); /* a yacc function */
3671 if (definedef
!= dnone
)
3677 make_C_tag (TRUE
); /* an Objective C class */
3681 objdef
= omethodcolon
;
3682 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3683 strcat (token_name
.buffer
, ":");
3686 if (structdef
== stagseen
)
3688 structdef
= scolonseen
;
3691 /* Should be useless, but may be work as a safety net. */
3692 if (cplpl
&& fvdef
== flistseen
)
3694 make_C_tag (TRUE
); /* a function */
3700 if (definedef
!= dnone
|| inattribute
)
3706 make_C_tag (FALSE
); /* a typedef */
3716 if (typdef
== tignore
|| cplpl
)
3720 if ((globals
&& bracelev
== 0 && (!fvextern
|| declarations
))
3721 || (members
&& instruct
))
3722 make_C_tag (FALSE
); /* a variable */
3725 token
.valid
= FALSE
;
3729 && (cplpl
|| !instruct
)
3730 && (typdef
== tnone
|| (typdef
!= tignore
&& instruct
)))
3732 && plainc
&& instruct
))
3733 make_C_tag (TRUE
); /* a function */
3739 && cplpl
&& structdef
== stagseen
)
3740 make_C_tag (FALSE
); /* forward declaration */
3742 token
.valid
= FALSE
;
3743 } /* switch (fvdef) */
3749 if (structdef
== stagseen
)
3753 if (definedef
!= dnone
|| inattribute
)
3759 make_C_tag (TRUE
); /* an Objective C method */
3780 && (!fvextern
|| declarations
))
3781 || (members
&& instruct
)))
3782 make_C_tag (FALSE
); /* a variable */
3785 if ((declarations
&& typdef
== tnone
&& !instruct
)
3786 || (members
&& typdef
!= tignore
&& instruct
))
3788 make_C_tag (TRUE
); /* a function */
3791 else if (!declarations
)
3793 token
.valid
= FALSE
;
3798 if (structdef
== stagseen
)
3802 if (definedef
!= dnone
|| inattribute
)
3804 if (structdef
== stagseen
)
3811 make_C_tag (FALSE
); /* a typedef */
3823 if ((members
&& bracelev
== 1)
3824 || (globals
&& bracelev
== 0
3825 && (!fvextern
|| declarations
)))
3826 make_C_tag (FALSE
); /* a variable */
3840 if (definedef
!= dnone
)
3842 if (objdef
== otagseen
&& parlev
== 0)
3843 objdef
= oparenseen
;
3847 if (typdef
== ttypeseen
3851 /* This handles constructs like:
3852 typedef void OperatorFun (int fun); */
3871 if (--attrparlev
== 0)
3872 inattribute
= FALSE
;
3875 if (definedef
!= dnone
)
3877 if (objdef
== ocatseen
&& parlev
== 1)
3879 make_C_tag (TRUE
); /* an Objective C category */
3893 || typdef
== ttypeseen
))
3896 make_C_tag (FALSE
); /* a typedef */
3899 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3903 if (definedef
!= dnone
)
3905 if (typdef
== ttypeseen
)
3907 /* Whenever typdef is set to tinbody (currently only
3908 here), typdefbracelev should be set to bracelev. */
3910 typdefbracelev
= bracelev
;
3915 make_C_tag (TRUE
); /* a function */
3924 make_C_tag (TRUE
); /* an Objective C class */
3929 make_C_tag (TRUE
); /* an Objective C method */
3933 /* Neutralize `extern "C" {' grot. */
3934 if (bracelev
== 0 && structdef
== snone
&& nestlev
== 0
3942 case skeyseen
: /* unnamed struct */
3943 pushclass_above (bracelev
, NULL
, 0);
3946 case stagseen
: /* named struct or enum */
3947 case scolonseen
: /* a class */
3948 pushclass_above (bracelev
,token
.line
+token
.offset
, token
.length
);
3950 make_C_tag (FALSE
); /* a struct or enum */
3956 if (definedef
!= dnone
)
3958 if (fvdef
== fstartlist
)
3960 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3961 token
.valid
= FALSE
;
3965 if (definedef
!= dnone
)
3967 if (!ignoreindent
&& lp
== newlb
.buffer
+ 1)
3970 token
.valid
= FALSE
;
3971 bracelev
= 0; /* reset brace level if first column */
3972 parlev
= 0; /* also reset paren level, just in case... */
3974 else if (bracelev
> 0)
3977 token
.valid
= FALSE
; /* something gone amiss, token unreliable */
3978 popclass_above (bracelev
);
3980 /* Only if typdef == tinbody is typdefbracelev significant. */
3981 if (typdef
== tinbody
&& bracelev
<= typdefbracelev
)
3983 assert (bracelev
== typdefbracelev
);
3988 if (definedef
!= dnone
)
3998 if ((members
&& bracelev
== 1)
3999 || (globals
&& bracelev
== 0 && (!fvextern
|| declarations
)))
4000 make_C_tag (FALSE
); /* a variable */
4008 && (structdef
== stagseen
|| fvdef
== fvnameseen
))
4015 if (templatelev
> 0)
4023 if (objdef
== oinbody
&& bracelev
== 0)
4025 objdef
= omethodsign
;
4030 case '#': case '~': case '&': case '%': case '/':
4031 case '|': case '^': case '!': case '.': case '?':
4032 if (definedef
!= dnone
)
4034 /* These surely cannot follow a function tag in C. */
4047 if (objdef
== otagseen
)
4049 make_C_tag (TRUE
); /* an Objective C class */
4052 /* If a macro spans multiple lines don't reset its state. */
4054 CNL_SAVE_DEFINEDEF ();
4060 } /* while not eof */
4062 free (lbs
[0].lb
.buffer
);
4063 free (lbs
[1].lb
.buffer
);
4067 * Process either a C++ file or a C file depending on the setting
4071 default_C_entries (inf
)
4074 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
4077 /* Always do plain C. */
4079 plain_C_entries (inf
)
4085 /* Always do C++. */
4087 Cplusplus_entries (inf
)
4090 C_entries (C_PLPL
, inf
);
4093 /* Always do Java. */
4098 C_entries (C_JAVA
, inf
);
4106 C_entries (C_STAR
, inf
);
4109 /* Always do Yacc. */
4114 C_entries (YACC
, inf
);
4118 /* Useful macros. */
4119 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
4120 for (; /* loop initialization */ \
4121 !feof (file_pointer) /* loop test */ \
4122 && /* instructions at start of loop */ \
4123 (readline (&line_buffer, file_pointer), \
4124 char_pointer = line_buffer.buffer, \
4128 #define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \
4129 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \
4130 && strneq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4131 && notinname ((cp)[sizeof(kw)-1]) /* end of kw */ \
4132 && ((cp) = skip_spaces((cp)+sizeof(kw)-1))) /* skip spaces */
4134 /* Similar to LOOKING_AT but does not use notinname, does not skip */
4135 #define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */ \
4136 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \
4137 && strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4138 && ((cp) += sizeof(kw)-1)) /* skip spaces */
4141 * Read a file, but do no processing. This is used to do regexp
4142 * matching on files that have no language defined.
4145 just_read_file (inf
)
4148 register char *dummy
;
4150 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
4155 /* Fortran parsing */
4157 static void F_takeprec
__P((void));
4158 static void F_getit
__P((FILE *));
4163 dbp
= skip_spaces (dbp
);
4167 dbp
= skip_spaces (dbp
);
4168 if (strneq (dbp
, "(*)", 3))
4173 if (!ISDIGIT (*dbp
))
4175 --dbp
; /* force failure */
4180 while (ISDIGIT (*dbp
));
4189 dbp
= skip_spaces (dbp
);
4192 readline (&lb
, inf
);
4197 dbp
= skip_spaces (dbp
);
4199 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
4201 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
4203 make_tag (dbp
, cp
-dbp
, TRUE
,
4204 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4209 Fortran_functions (inf
)
4212 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4215 dbp
++; /* Ratfor escape to fortran */
4216 dbp
= skip_spaces (dbp
);
4219 switch (lowcase (*dbp
))
4222 if (nocase_tail ("integer"))
4226 if (nocase_tail ("real"))
4230 if (nocase_tail ("logical"))
4234 if (nocase_tail ("complex") || nocase_tail ("character"))
4238 if (nocase_tail ("double"))
4240 dbp
= skip_spaces (dbp
);
4243 if (nocase_tail ("precision"))
4249 dbp
= skip_spaces (dbp
);
4252 switch (lowcase (*dbp
))
4255 if (nocase_tail ("function"))
4259 if (nocase_tail ("subroutine"))
4263 if (nocase_tail ("entry"))
4267 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
4269 dbp
= skip_spaces (dbp
);
4270 if (*dbp
== '\0') /* assume un-named */
4271 make_tag ("blockdata", 9, TRUE
,
4272 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
4274 F_getit (inf
); /* look for name */
4285 * Philippe Waroquiers (1998)
4288 static void Ada_getit
__P((FILE *, char *));
4290 /* Once we are positioned after an "interesting" keyword, let's get
4291 the real tag value necessary. */
4293 Ada_getit (inf
, name_qualifier
)
4295 char *name_qualifier
;
4303 dbp
= skip_spaces (dbp
);
4305 || (dbp
[0] == '-' && dbp
[1] == '-'))
4307 readline (&lb
, inf
);
4310 switch (lowcase(*dbp
))
4313 if (nocase_tail ("body"))
4315 /* Skipping body of procedure body or package body or ....
4316 resetting qualifier to body instead of spec. */
4317 name_qualifier
= "/b";
4322 /* Skipping type of task type or protected type ... */
4323 if (nocase_tail ("type"))
4330 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4335 dbp
= skip_spaces (dbp
);
4338 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4346 name
= concat (dbp
, name_qualifier
, "");
4348 make_tag (name
, strlen (name
), TRUE
,
4349 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4361 bool inquote
= FALSE
;
4362 bool skip_till_semicolumn
= FALSE
;
4364 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4366 while (*dbp
!= '\0')
4368 /* Skip a string i.e. "abcd". */
4369 if (inquote
|| (*dbp
== '"'))
4371 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4376 continue; /* advance char */
4381 break; /* advance line */
4385 /* Skip comments. */
4386 if (dbp
[0] == '-' && dbp
[1] == '-')
4387 break; /* advance line */
4389 /* Skip character enclosed in single quote i.e. 'a'
4390 and skip single quote starting an attribute i.e. 'Image. */
4399 if (skip_till_semicolumn
)
4402 skip_till_semicolumn
= FALSE
;
4404 continue; /* advance char */
4407 /* Search for beginning of a token. */
4408 if (!begtoken (*dbp
))
4411 continue; /* advance char */
4414 /* We are at the beginning of a token. */
4415 switch (lowcase(*dbp
))
4418 if (!packages_only
&& nocase_tail ("function"))
4419 Ada_getit (inf
, "/f");
4421 break; /* from switch */
4422 continue; /* advance char */
4424 if (!packages_only
&& nocase_tail ("procedure"))
4425 Ada_getit (inf
, "/p");
4426 else if (nocase_tail ("package"))
4427 Ada_getit (inf
, "/s");
4428 else if (nocase_tail ("protected")) /* protected type */
4429 Ada_getit (inf
, "/t");
4431 break; /* from switch */
4432 continue; /* advance char */
4435 if (typedefs
&& !packages_only
&& nocase_tail ("use"))
4437 /* when tagging types, avoid tagging use type Pack.Typename;
4438 for this, we will skip everything till a ; */
4439 skip_till_semicolumn
= TRUE
;
4440 continue; /* advance char */
4444 if (!packages_only
&& nocase_tail ("task"))
4445 Ada_getit (inf
, "/k");
4446 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4448 Ada_getit (inf
, "/t");
4449 while (*dbp
!= '\0')
4453 break; /* from switch */
4454 continue; /* advance char */
4457 /* Look for the end of the token. */
4458 while (!endtoken (*dbp
))
4461 } /* advance char */
4462 } /* advance line */
4467 * Unix and microcontroller assembly tag handling
4468 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4469 * Idea by Bob Weiner, Motorola Inc. (1994)
4477 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4479 /* If first char is alphabetic or one of [_.$], test for colon
4480 following identifier. */
4481 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4483 /* Read past label. */
4485 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4487 if (*cp
== ':' || iswhite (*cp
))
4488 /* Found end of label, so copy it and add it to the table. */
4489 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4490 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4498 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4499 * Perl variable names: /^(my|local).../
4500 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4501 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4502 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4505 Perl_functions (inf
)
4508 char *package
= savestr ("main"); /* current package name */
4511 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4515 if (LOOKING_AT (cp
, "package"))
4518 get_tag (cp
, &package
);
4520 else if (LOOKING_AT (cp
, "sub"))
4525 while (!notinname (*cp
))
4528 continue; /* nothing found */
4529 if ((pos
= etags_strchr (sp
, ':')) != NULL
4530 && pos
< cp
&& pos
[1] == ':')
4531 /* The name is already qualified. */
4532 make_tag (sp
, cp
- sp
, TRUE
,
4533 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4537 char savechar
, *name
;
4541 name
= concat (package
, "::", sp
);
4543 make_tag (name
, strlen(name
), TRUE
,
4544 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4548 else if (globals
) /* only if we are tagging global vars */
4550 /* Skip a qualifier, if any. */
4551 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4552 /* After "my" or "local", but before any following paren or space. */
4553 char *varstart
= cp
;
4555 if (qual
/* should this be removed? If yes, how? */
4556 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4561 while (ISALNUM (*cp
) || *cp
== '_');
4565 /* Should be examining a variable list at this point;
4566 could insist on seeing an open parenthesis. */
4567 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4573 make_tag (varstart
, cp
- varstart
, FALSE
,
4574 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4583 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4584 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4585 * More ideas by seb bacon <seb@jamkit.com> (2002)
4588 Python_functions (inf
)
4593 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4595 cp
= skip_spaces (cp
);
4596 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4599 while (!notinname (*cp
) && *cp
!= ':')
4601 make_tag (name
, cp
- name
, TRUE
,
4602 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4611 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4612 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4613 * - /^[ \t]*define\(\"[^\"]+/
4614 * Only with --members:
4615 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4616 * Idea by Diez B. Roggisch (2001)
4622 register char *cp
, *name
;
4623 bool search_identifier
= FALSE
;
4625 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4627 cp
= skip_spaces (cp
);
4629 if (search_identifier
4632 while (!notinname (*cp
))
4634 make_tag (name
, cp
- name
, TRUE
,
4635 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4636 search_identifier
= FALSE
;
4638 else if (LOOKING_AT (cp
, "function"))
4641 cp
= skip_spaces (cp
+1);
4645 while (!notinname (*cp
))
4647 make_tag (name
, cp
- name
, TRUE
,
4648 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4651 search_identifier
= TRUE
;
4653 else if (LOOKING_AT (cp
, "class"))
4658 while (*cp
!= '\0' && !iswhite (*cp
))
4660 make_tag (name
, cp
- name
, FALSE
,
4661 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4664 search_identifier
= TRUE
;
4666 else if (strneq (cp
, "define", 6)
4667 && (cp
= skip_spaces (cp
+6))
4669 && (*cp
== '"' || *cp
== '\''))
4673 while (*cp
!= quote
&& *cp
!= '\0')
4675 make_tag (name
, cp
- name
, FALSE
,
4676 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4679 && LOOKING_AT (cp
, "var")
4683 while (!notinname(*cp
))
4685 make_tag (name
, cp
- name
, FALSE
,
4686 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4693 * Cobol tag functions
4694 * We could look for anything that could be a paragraph name.
4695 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4696 * Idea by Corny de Souza (1993)
4699 Cobol_paragraphs (inf
)
4702 register char *bp
, *ep
;
4704 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4710 /* If eoln, compiler option or comment ignore whole line. */
4711 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4714 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4717 make_tag (bp
, ep
- bp
, TRUE
,
4718 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4725 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4728 Makefile_targets (inf
)
4733 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4735 if (*bp
== '\t' || *bp
== '#')
4737 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4739 if (*bp
== ':' || (globals
&& *bp
== '='))
4741 /* We should detect if there is more than one tag, but we do not.
4742 We just skip initial and final spaces. */
4743 char * namestart
= skip_spaces (lb
.buffer
);
4744 while (--bp
> namestart
)
4745 if (!notinname (*bp
))
4747 make_tag (namestart
, bp
- namestart
+ 1, TRUE
,
4748 lb
.buffer
, bp
- lb
.buffer
+ 2, lineno
, linecharno
);
4756 * Original code by Mosur K. Mohan (1989)
4758 * Locates tags for procedures & functions. Doesn't do any type- or
4759 * var-definitions. It does look for the keyword "extern" or
4760 * "forward" immediately following the procedure statement; if found,
4761 * the tag is skipped.
4764 Pascal_functions (inf
)
4767 linebuffer tline
; /* mostly copied from C_entries */
4769 int save_lineno
, namelen
, taglen
;
4772 bool /* each of these flags is TRUE iff: */
4773 incomment
, /* point is inside a comment */
4774 inquote
, /* point is inside '..' string */
4775 get_tagname
, /* point is after PROCEDURE/FUNCTION
4776 keyword, so next item = potential tag */
4777 found_tag
, /* point is after a potential tag */
4778 inparms
, /* point is within parameter-list */
4779 verify_tag
; /* point has passed the parm-list, so the
4780 next token will determine whether this
4781 is a FORWARD/EXTERN to be ignored, or
4782 whether it is a real tag */
4784 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4785 name
= NULL
; /* keep compiler quiet */
4788 linebuffer_init (&tline
);
4790 incomment
= inquote
= FALSE
;
4791 found_tag
= FALSE
; /* have a proc name; check if extern */
4792 get_tagname
= FALSE
; /* found "procedure" keyword */
4793 inparms
= FALSE
; /* found '(' after "proc" */
4794 verify_tag
= FALSE
; /* check if "extern" is ahead */
4797 while (!feof (inf
)) /* long main loop to get next char */
4800 if (c
== '\0') /* if end of line */
4802 readline (&lb
, inf
);
4806 if (!((found_tag
&& verify_tag
)
4808 c
= *dbp
++; /* only if don't need *dbp pointing
4809 to the beginning of the name of
4810 the procedure or function */
4814 if (c
== '}') /* within { } comments */
4816 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4833 inquote
= TRUE
; /* found first quote */
4835 case '{': /* found open { comment */
4839 if (*dbp
== '*') /* found open (* comment */
4844 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4847 case ')': /* end of parms list */
4852 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4859 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4861 /* Check if this is an "extern" declaration. */
4864 if (lowcase (*dbp
== 'e'))
4866 if (nocase_tail ("extern")) /* superfluous, really! */
4872 else if (lowcase (*dbp
) == 'f')
4874 if (nocase_tail ("forward")) /* check for forward reference */
4880 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4884 make_tag (name
, namelen
, TRUE
,
4885 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4889 if (get_tagname
) /* grab name of proc or fn */
4896 /* Find block name. */
4897 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4900 /* Save all values for later tagging. */
4901 linebuffer_setlen (&tline
, lb
.len
);
4902 strcpy (tline
.buffer
, lb
.buffer
);
4903 save_lineno
= lineno
;
4904 save_lcno
= linecharno
;
4905 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4907 taglen
= cp
- lb
.buffer
+ 1;
4909 dbp
= cp
; /* set dbp to e-o-token */
4910 get_tagname
= FALSE
;
4914 /* And proceed to check for "extern". */
4916 else if (!incomment
&& !inquote
&& !found_tag
)
4918 /* Check for proc/fn keywords. */
4919 switch (lowcase (c
))
4922 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4926 if (nocase_tail ("unction"))
4931 } /* while not eof */
4933 free (tline
.buffer
);
4938 * Lisp tag functions
4939 * look for (def or (DEF, quote or QUOTE
4942 static void L_getit
__P((void));
4947 if (*dbp
== '\'') /* Skip prefix quote */
4949 else if (*dbp
== '(')
4952 /* Try to skip "(quote " */
4953 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4954 /* Ok, then skip "(" before name in (defstruct (foo)) */
4955 dbp
= skip_spaces (dbp
);
4957 get_tag (dbp
, NULL
);
4961 Lisp_functions (inf
)
4964 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4969 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4971 dbp
= skip_non_spaces (dbp
);
4972 dbp
= skip_spaces (dbp
);
4977 /* Check for (foo::defmumble name-defined ... */
4980 while (!notinname (*dbp
) && *dbp
!= ':');
4985 while (*dbp
== ':');
4987 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4989 dbp
= skip_non_spaces (dbp
);
4990 dbp
= skip_spaces (dbp
);
5000 * Lua script language parsing
5001 * Original code by David A. Capello <dacap@users.sourceforge.net> (2004)
5003 * "function" and "local function" are tags if they start at column 1.
5011 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5013 if (bp
[0] != 'f' && bp
[0] != 'l')
5016 (void)LOOKING_AT (bp
, "local"); /* skip possible "local" */
5018 if (LOOKING_AT (bp
, "function"))
5026 * Just look for lines where the first character is '/'
5027 * Also look at "defineps" for PSWrap
5029 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
5030 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
5036 register char *bp
, *ep
;
5038 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5043 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
5046 make_tag (bp
, ep
- bp
, TRUE
,
5047 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
5049 else if (LOOKING_AT (bp
, "defineps"))
5057 * Ignore anything after \ followed by space or in ( )
5058 * Look for words defined by :
5059 * Look for constant, code, create, defer, value, and variable
5060 * OBP extensions: Look for buffer:, field,
5061 * Ideas by Eduardo Horvath <eeh@netbsd.org> (2004)
5069 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5070 while ((bp
= skip_spaces (bp
))[0] != '\0')
5071 if (bp
[0] == '\\' && iswhite(bp
[1]))
5072 break; /* read next line */
5073 else if (bp
[0] == '(' && iswhite(bp
[1]))
5074 do /* skip to ) or eol */
5076 while (*bp
!= ')' && *bp
!= '\0');
5077 else if ((bp
[0] == ':' && iswhite(bp
[1]) && bp
++)
5078 || LOOKING_AT_NOCASE (bp
, "constant")
5079 || LOOKING_AT_NOCASE (bp
, "code")
5080 || LOOKING_AT_NOCASE (bp
, "create")
5081 || LOOKING_AT_NOCASE (bp
, "defer")
5082 || LOOKING_AT_NOCASE (bp
, "value")
5083 || LOOKING_AT_NOCASE (bp
, "variable")
5084 || LOOKING_AT_NOCASE (bp
, "buffer:")
5085 || LOOKING_AT_NOCASE (bp
, "field"))
5086 get_tag (skip_spaces (bp
), NULL
); /* Yay! A definition! */
5088 bp
= skip_non_spaces (bp
);
5093 * Scheme tag functions
5094 * look for (def... xyzzy
5096 * (def ... ((...(xyzzy ....
5098 * Original code by Ken Haase (1985?)
5101 Scheme_functions (inf
)
5106 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
5108 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
5110 bp
= skip_non_spaces (bp
+4);
5111 /* Skip over open parens and white space */
5112 while (notinname (*bp
))
5116 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
5122 /* Find tags in TeX and LaTeX input files. */
5124 /* TEX_toktab is a table of TeX control sequences that define tags.
5125 * Each entry records one such control sequence.
5127 * Original code from who knows whom.
5129 * Stefan Monnier (2002)
5132 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
5134 /* Default set of control sequences to put into TEX_toktab.
5135 The value of environment var TEXTAGS is prepended to this. */
5136 static char *TEX_defenv
= "\
5137 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
5138 :part:appendix:entry:index:def\
5139 :newcommand:renewcommand:newenvironment:renewenvironment";
5141 static void TEX_mode
__P((FILE *));
5142 static void TEX_decode_env
__P((char *, char *));
5144 static char TEX_esc
= '\\';
5145 static char TEX_opgrp
= '{';
5146 static char TEX_clgrp
= '}';
5149 * TeX/LaTeX scanning loop.
5158 /* Select either \ or ! as escape character. */
5161 /* Initialize token table once from environment. */
5162 if (TEX_toktab
== NULL
)
5163 TEX_decode_env ("TEXTAGS", TEX_defenv
);
5165 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5167 /* Look at each TEX keyword in line. */
5170 /* Look for a TEX escape. */
5171 while (*cp
++ != TEX_esc
)
5172 if (cp
[-1] == '\0' || cp
[-1] == '%')
5175 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
5176 if (strneq (cp
, key
->buffer
, key
->len
))
5179 int namelen
, linelen
;
5182 cp
= skip_spaces (cp
+ key
->len
);
5183 if (*cp
== TEX_opgrp
)
5189 (!iswhite (*p
) && *p
!= '#' &&
5190 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
5195 if (!opgrp
|| *p
== TEX_clgrp
)
5197 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
5199 linelen
= p
- lb
.buffer
+ 1;
5201 make_tag (cp
, namelen
, TRUE
,
5202 lb
.buffer
, linelen
, lineno
, linecharno
);
5203 goto tex_next_line
; /* We only tag a line once */
5211 #define TEX_LESC '\\'
5212 #define TEX_SESC '!'
5214 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
5215 chars accordingly. */
5222 while ((c
= getc (inf
)) != EOF
)
5224 /* Skip to next line if we hit the TeX comment char. */
5226 while (c
!= '\n' && c
!= EOF
)
5228 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
5244 /* If the input file is compressed, inf is a pipe, and rewind may fail.
5245 No attempt is made to correct the situation. */
5249 /* Read environment and prepend it to the default string.
5250 Build token table. */
5252 TEX_decode_env (evarname
, defenv
)
5256 register char *env
, *p
;
5259 /* Append default string to environment. */
5260 env
= getenv (evarname
);
5266 env
= concat (oldenv
, defenv
, "");
5269 /* Allocate a token table */
5270 for (len
= 1, p
= env
; p
;)
5271 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
5273 TEX_toktab
= xnew (len
, linebuffer
);
5275 /* Unpack environment string into token table. Be careful about */
5276 /* zero-length strings (leading ':', "::" and trailing ':') */
5277 for (i
= 0; *env
!= '\0';)
5279 p
= etags_strchr (env
, ':');
5280 if (!p
) /* End of environment string. */
5281 p
= env
+ strlen (env
);
5283 { /* Only non-zero strings. */
5284 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
5285 TEX_toktab
[i
].len
= p
- env
;
5292 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
5293 TEX_toktab
[i
].len
= 0;
5300 /* Texinfo support. Dave Love, Mar. 2000. */
5306 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5307 if (LOOKING_AT (cp
, "@node"))
5310 while (*cp
!= '\0' && *cp
!= ',')
5312 make_tag (start
, cp
- start
, TRUE
,
5313 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5320 * Contents of <title>, <h1>, <h2>, <h3> are tags.
5321 * Contents of <a name=xxx> are tags with name xxx.
5323 * Francesco Potortì, 2002.
5329 bool getnext
= FALSE
; /* next text outside of HTML tags is a tag */
5330 bool skiptag
= FALSE
; /* skip to the end of the current HTML tag */
5331 bool intag
= FALSE
; /* inside an html tag, looking for ID= */
5332 bool inanchor
= FALSE
; /* when INTAG, is an anchor, look for NAME= */
5336 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5338 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5339 for (;;) /* loop on the same line */
5341 if (skiptag
) /* skip HTML tag */
5343 while (*dbp
!= '\0' && *dbp
!= '>')
5349 continue; /* look on the same line */
5351 break; /* go to next line */
5354 else if (intag
) /* look for "name=" or "id=" */
5356 while (*dbp
!= '\0' && *dbp
!= '>'
5357 && lowcase (*dbp
) != 'n' && lowcase (*dbp
) != 'i')
5360 break; /* go to next line */
5365 continue; /* look on the same line */
5367 if ((inanchor
&& LOOKING_AT_NOCASE (dbp
, "name="))
5368 || LOOKING_AT_NOCASE (dbp
, "id="))
5370 bool quoted
= (dbp
[0] == '"');
5373 for (end
= ++dbp
; *end
!= '\0' && *end
!= '"'; end
++)
5376 for (end
= dbp
; *end
!= '\0' && intoken (*end
); end
++)
5378 linebuffer_setlen (&token_name
, end
- dbp
);
5379 strncpy (token_name
.buffer
, dbp
, end
- dbp
);
5380 token_name
.buffer
[end
- dbp
] = '\0';
5383 intag
= FALSE
; /* we found what we looked for */
5384 skiptag
= TRUE
; /* skip to the end of the tag */
5385 getnext
= TRUE
; /* then grab the text */
5386 continue; /* look on the same line */
5391 else if (getnext
) /* grab next tokens and tag them */
5393 dbp
= skip_spaces (dbp
);
5395 break; /* go to next line */
5399 inanchor
= (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]));
5400 continue; /* look on the same line */
5403 for (end
= dbp
+ 1; *end
!= '\0' && *end
!= '<'; end
++)
5405 make_tag (token_name
.buffer
, token_name
.len
, TRUE
,
5406 dbp
, end
- dbp
, lineno
, linecharno
);
5407 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5409 break; /* go to next line */
5412 else /* look for an interesting HTML tag */
5414 while (*dbp
!= '\0' && *dbp
!= '<')
5417 break; /* go to next line */
5419 if (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]))
5422 continue; /* look on the same line */
5424 else if (LOOKING_AT_NOCASE (dbp
, "<title>")
5425 || LOOKING_AT_NOCASE (dbp
, "<h1>")
5426 || LOOKING_AT_NOCASE (dbp
, "<h2>")
5427 || LOOKING_AT_NOCASE (dbp
, "<h3>"))
5431 continue; /* look on the same line */
5442 * Assumes that the predicate or rule starts at column 0.
5443 * Only the first clause of a predicate or rule is added.
5444 * Original code by Sunichirou Sugou (1989)
5445 * Rewritten by Anders Lindgren (1996)
5447 static int prolog_pr
__P((char *, char *));
5448 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
5449 static int prolog_atom
__P((char *, int));
5452 Prolog_functions (inf
)
5463 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5465 if (cp
[0] == '\0') /* Empty line */
5467 else if (iswhite (cp
[0])) /* Not a predicate */
5469 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
5470 prolog_skip_comment (&lb
, inf
);
5471 else if ((len
= prolog_pr (cp
, last
)) > 0)
5473 /* Predicate or rule. Store the function name so that we
5474 only generate a tag for the first clause. */
5476 last
= xnew(len
+ 1, char);
5477 else if (len
+ 1 > allocated
)
5478 xrnew (last
, len
+ 1, char);
5479 allocated
= len
+ 1;
5480 strncpy (last
, cp
, len
);
5490 prolog_skip_comment (plb
, inf
)
5498 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
5499 if (cp
[0] == '*' && cp
[1] == '/')
5501 readline (plb
, inf
);
5507 * A predicate or rule definition is added if it matches:
5508 * <beginning of line><Prolog Atom><whitespace>(
5509 * or <beginning of line><Prolog Atom><whitespace>:-
5511 * It is added to the tags database if it doesn't match the
5512 * name of the previous clause header.
5514 * Return the size of the name of the predicate or rule, or 0 if no
5520 char *last
; /* Name of last clause. */
5525 pos
= prolog_atom (s
, 0);
5530 pos
= skip_spaces (s
+ pos
) - s
;
5533 || (s
[pos
] == '(' && (pos
+= 1))
5534 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5535 && (last
== NULL
/* save only the first clause */
5536 || len
!= (int)strlen (last
)
5537 || !strneq (s
, last
, len
)))
5539 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5547 * Consume a Prolog atom.
5548 * Return the number of bytes consumed, or -1 if there was an error.
5550 * A prolog atom, in this context, could be one of:
5551 * - An alphanumeric sequence, starting with a lower case letter.
5552 * - A quoted arbitrary string. Single quotes can escape themselves.
5553 * Backslash quotes everything.
5556 prolog_atom (s
, pos
)
5564 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5566 /* The atom is unquoted. */
5568 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5572 return pos
- origpos
;
5574 else if (s
[pos
] == '\'')
5585 pos
++; /* A double quote */
5587 else if (s
[pos
] == '\0')
5588 /* Multiline quoted atoms are ignored. */
5590 else if (s
[pos
] == '\\')
5592 if (s
[pos
+1] == '\0')
5599 return pos
- origpos
;
5607 * Support for Erlang
5609 * Generates tags for functions, defines, and records.
5610 * Assumes that Erlang functions start at column 0.
5611 * Original code by Anders Lindgren (1996)
5613 static int erlang_func
__P((char *, char *));
5614 static void erlang_attribute
__P((char *));
5615 static int erlang_atom
__P((char *));
5618 Erlang_functions (inf
)
5629 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5631 if (cp
[0] == '\0') /* Empty line */
5633 else if (iswhite (cp
[0])) /* Not function nor attribute */
5635 else if (cp
[0] == '%') /* comment */
5637 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5639 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5641 erlang_attribute (cp
);
5648 else if ((len
= erlang_func (cp
, last
)) > 0)
5651 * Function. Store the function name so that we only
5652 * generates a tag for the first clause.
5655 last
= xnew (len
+ 1, char);
5656 else if (len
+ 1 > allocated
)
5657 xrnew (last
, len
+ 1, char);
5658 allocated
= len
+ 1;
5659 strncpy (last
, cp
, len
);
5669 * A function definition is added if it matches:
5670 * <beginning of line><Erlang Atom><whitespace>(
5672 * It is added to the tags database if it doesn't match the
5673 * name of the previous clause header.
5675 * Return the size of the name of the function, or 0 if no function
5679 erlang_func (s
, last
)
5681 char *last
; /* Name of last clause. */
5686 pos
= erlang_atom (s
);
5691 pos
= skip_spaces (s
+ pos
) - s
;
5693 /* Save only the first clause. */
5696 || len
!= (int)strlen (last
)
5697 || !strneq (s
, last
, len
)))
5699 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5708 * Handle attributes. Currently, tags are generated for defines
5711 * They are on the form:
5712 * -define(foo, bar).
5713 * -define(Foo(M, N), M+N).
5714 * -record(graph, {vtab = notable, cyclic = true}).
5717 erlang_attribute (s
)
5722 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5725 int len
= erlang_atom (skip_spaces (cp
));
5727 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5734 * Consume an Erlang atom (or variable).
5735 * Return the number of bytes consumed, or -1 if there was an error.
5743 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5745 /* The atom is unquoted. */
5748 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5750 else if (s
[pos
] == '\'')
5752 for (pos
++; s
[pos
] != '\''; pos
++)
5753 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5754 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5763 static char *scan_separators
__P((char *));
5764 static void add_regex
__P((char *, language
*));
5765 static char *substitute
__P((char *, char *, struct re_registers
*));
5768 * Take a string like "/blah/" and turn it into "blah", verifying
5769 * that the first and last characters are the same, and handling
5770 * quoted separator characters. Actually, stops on the occurrence of
5771 * an unquoted separator. Also process \t, \n, etc. and turn into
5772 * appropriate characters. Works in place. Null terminates name string.
5773 * Returns pointer to terminating separator, or NULL for
5774 * unterminated regexps.
5777 scan_separators (name
)
5781 char *copyto
= name
;
5782 bool quoted
= FALSE
;
5784 for (++name
; *name
!= '\0'; ++name
)
5790 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5791 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5792 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5793 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5794 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5795 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5796 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5797 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5798 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5804 /* Something else is quoted, so preserve the quote. */
5812 else if (*name
== '\\')
5814 else if (*name
== sep
)
5820 name
= NULL
; /* signal unterminated regexp */
5822 /* Terminate copied string. */
5827 /* Look at the argument of --regex or --no-regex and do the right
5828 thing. Same for each line of a regexp file. */
5830 analyse_regex (regex_arg
)
5833 if (regex_arg
== NULL
)
5835 free_regexps (); /* --no-regex: remove existing regexps */
5839 /* A real --regexp option or a line in a regexp file. */
5840 switch (regex_arg
[0])
5842 /* Comments in regexp file or null arg to --regex. */
5848 /* Read a regex file. This is recursive and may result in a
5849 loop, which will stop when the file descriptors are exhausted. */
5853 linebuffer regexbuf
;
5854 char *regexfile
= regex_arg
+ 1;
5856 /* regexfile is a file containing regexps, one per line. */
5857 regexfp
= fopen (regexfile
, "r");
5858 if (regexfp
== NULL
)
5863 linebuffer_init (®exbuf
);
5864 while (readline_internal (®exbuf
, regexfp
) > 0)
5865 analyse_regex (regexbuf
.buffer
);
5866 free (regexbuf
.buffer
);
5871 /* Regexp to be used for a specific language only. */
5875 char *lang_name
= regex_arg
+ 1;
5878 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5881 error ("unterminated language name in regex: %s", regex_arg
);
5885 lang
= get_language_from_langname (lang_name
);
5888 add_regex (cp
, lang
);
5892 /* Regexp to be used for any language. */
5894 add_regex (regex_arg
, NULL
);
5899 /* Separate the regexp pattern, compile it,
5900 and care for optional name and modifiers. */
5902 add_regex (regexp_pattern
, lang
)
5903 char *regexp_pattern
;
5906 static struct re_pattern_buffer zeropattern
;
5907 char sep
, *pat
, *name
, *modifiers
;
5909 struct re_pattern_buffer
*patbuf
;
5912 force_explicit_name
= TRUE
, /* do not use implicit tag names */
5913 ignore_case
= FALSE
, /* case is significant */
5914 multi_line
= FALSE
, /* matches are done one line at a time */
5915 single_line
= FALSE
; /* dot does not match newline */
5918 if (strlen(regexp_pattern
) < 3)
5920 error ("null regexp", (char *)NULL
);
5923 sep
= regexp_pattern
[0];
5924 name
= scan_separators (regexp_pattern
);
5927 error ("%s: unterminated regexp", regexp_pattern
);
5932 error ("null name for regexp \"%s\"", regexp_pattern
);
5935 modifiers
= scan_separators (name
);
5936 if (modifiers
== NULL
) /* no terminating separator --> no name */
5942 modifiers
+= 1; /* skip separator */
5944 /* Parse regex modifiers. */
5945 for (; modifiers
[0] != '\0'; modifiers
++)
5946 switch (modifiers
[0])
5949 if (modifiers
== name
)
5950 error ("forcing explicit tag name but no name, ignoring", NULL
);
5951 force_explicit_name
= TRUE
;
5961 need_filebuf
= TRUE
;
5966 wrongmod
[0] = modifiers
[0];
5968 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
5973 patbuf
= xnew (1, struct re_pattern_buffer
);
5974 *patbuf
= zeropattern
;
5977 static char lc_trans
[CHARS
];
5979 for (i
= 0; i
< CHARS
; i
++)
5980 lc_trans
[i
] = lowcase (i
);
5981 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5985 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
5987 pat
= regexp_pattern
;
5990 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
5992 re_set_syntax (RE_SYNTAX_EMACS
);
5994 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
5999 error ("%s while compiling pattern", err
);
6004 p_head
= xnew (1, regexp
);
6005 p_head
->pattern
= savestr (regexp_pattern
);
6006 p_head
->p_next
= rp
;
6007 p_head
->lang
= lang
;
6008 p_head
->pat
= patbuf
;
6009 p_head
->name
= savestr (name
);
6010 p_head
->error_signaled
= FALSE
;
6011 p_head
->force_explicit_name
= force_explicit_name
;
6012 p_head
->ignore_case
= ignore_case
;
6013 p_head
->multi_line
= multi_line
;
6017 * Do the substitutions indicated by the regular expression and
6021 substitute (in
, out
, regs
)
6023 struct re_registers
*regs
;
6026 int size
, dig
, diglen
;
6029 size
= strlen (out
);
6031 /* Pass 1: figure out how much to allocate by finding all \N strings. */
6032 if (out
[size
- 1] == '\\')
6033 fatal ("pattern error in \"%s\"", out
);
6034 for (t
= etags_strchr (out
, '\\');
6036 t
= etags_strchr (t
+ 2, '\\'))
6040 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
6046 /* Allocate space and do the substitutions. */
6048 result
= xnew (size
+ 1, char);
6050 for (t
= result
; *out
!= '\0'; out
++)
6051 if (*out
== '\\' && ISDIGIT (*++out
))
6054 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
6055 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
6062 assert (t
<= result
+ size
);
6063 assert (t
- result
== (int)strlen (result
));
6068 /* Deallocate all regexps. */
6073 while (p_head
!= NULL
)
6075 rp
= p_head
->p_next
;
6076 free (p_head
->pattern
);
6077 free (p_head
->name
);
6085 * Reads the whole file as a single string from `filebuf' and looks for
6086 * multi-line regular expressions, creating tags on matches.
6087 * readline already dealt with normal regexps.
6089 * Idea by Ben Wing <ben@666.com> (2002).
6092 regex_tag_multiline ()
6094 char *buffer
= filebuf
.buffer
;
6098 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6102 if (!rp
->multi_line
)
6103 continue; /* skip normal regexps */
6105 /* Generic initialisations before parsing file from memory. */
6106 lineno
= 1; /* reset global line number */
6107 charno
= 0; /* reset global char number */
6108 linecharno
= 0; /* reset global char number of line start */
6110 /* Only use generic regexps or those for the current language. */
6111 if (rp
->lang
!= NULL
&& rp
->lang
!= curfdp
->lang
)
6114 while (match
>= 0 && match
< filebuf
.len
)
6116 match
= re_search (rp
->pat
, buffer
, filebuf
.len
, charno
,
6117 filebuf
.len
- match
, &rp
->regs
);
6122 if (!rp
->error_signaled
)
6124 error ("regexp stack overflow while matching \"%s\"",
6126 rp
->error_signaled
= TRUE
;
6133 if (match
== rp
->regs
.end
[0])
6135 if (!rp
->error_signaled
)
6137 error ("regexp matches the empty string: \"%s\"",
6139 rp
->error_signaled
= TRUE
;
6141 match
= -3; /* exit from while loop */
6145 /* Match occurred. Construct a tag. */
6146 while (charno
< rp
->regs
.end
[0])
6147 if (buffer
[charno
++] == '\n')
6148 lineno
++, linecharno
= charno
;
6150 if (name
[0] == '\0')
6152 else /* make a named tag */
6153 name
= substitute (buffer
, rp
->name
, &rp
->regs
);
6154 if (rp
->force_explicit_name
)
6155 /* Force explicit tag name, if a name is there. */
6156 pfnote (name
, TRUE
, buffer
+ linecharno
,
6157 charno
- linecharno
+ 1, lineno
, linecharno
);
6159 make_tag (name
, strlen (name
), TRUE
, buffer
+ linecharno
,
6160 charno
- linecharno
+ 1, lineno
, linecharno
);
6172 register int len
= 0;
6174 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
6176 if (*cp
== '\0' && !intoken (dbp
[len
]))
6185 get_tag (bp
, namepp
)
6189 register char *cp
= bp
;
6193 /* Go till you get to white space or a syntactic break */
6194 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
6196 make_tag (bp
, cp
- bp
, TRUE
,
6197 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
6201 *namepp
= savenstr (bp
, cp
- bp
);
6205 * Read a line of text from `stream' into `lbp', excluding the
6206 * newline or CR-NL, if any. Return the number of characters read from
6207 * `stream', which is the length of the line including the newline.
6209 * On DOS or Windows we do not count the CR character, if any before the
6210 * NL, in the returned length; this mirrors the behavior of Emacs on those
6211 * platforms (for text files, it translates CR-NL to NL as it reads in the
6214 * If multi-line regular expressions are requested, each line read is
6215 * appended to `filebuf'.
6218 readline_internal (lbp
, stream
)
6220 register FILE *stream
;
6222 char *buffer
= lbp
->buffer
;
6223 register char *p
= lbp
->buffer
;
6224 register char *pend
;
6227 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
6231 register int c
= getc (stream
);
6234 /* We're at the end of linebuffer: expand it. */
6236 xrnew (buffer
, lbp
->size
, char);
6237 p
+= buffer
- lbp
->buffer
;
6238 pend
= buffer
+ lbp
->size
;
6239 lbp
->buffer
= buffer
;
6249 if (p
> buffer
&& p
[-1] == '\r')
6253 /* Assume CRLF->LF translation will be performed by Emacs
6254 when loading this file, so CRs won't appear in the buffer.
6255 It would be cleaner to compensate within Emacs;
6256 however, Emacs does not know how many CRs were deleted
6257 before any given point in the file. */
6272 lbp
->len
= p
- buffer
;
6274 if (need_filebuf
/* we need filebuf for multi-line regexps */
6275 && chars_deleted
> 0) /* not at EOF */
6277 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
6279 /* Expand filebuf. */
6281 xrnew (filebuf
.buffer
, filebuf
.size
, char);
6283 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
6284 filebuf
.len
+= lbp
->len
;
6285 filebuf
.buffer
[filebuf
.len
++] = '\n';
6286 filebuf
.buffer
[filebuf
.len
] = '\0';
6289 return lbp
->len
+ chars_deleted
;
6293 * Like readline_internal, above, but in addition try to match the
6294 * input line against relevant regular expressions and manage #line
6298 readline (lbp
, stream
)
6304 linecharno
= charno
; /* update global char number of line start */
6305 result
= readline_internal (lbp
, stream
); /* read line */
6306 lineno
+= 1; /* increment global line number */
6307 charno
+= result
; /* increment global char number */
6309 /* Honour #line directives. */
6310 if (!no_line_directive
)
6312 static bool discard_until_line_directive
;
6314 /* Check whether this is a #line directive. */
6315 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
6320 if (sscanf (lbp
->buffer
, "#line %u \"%n", &lno
, &start
) >= 1
6321 && start
> 0) /* double quote character found */
6323 char *endp
= lbp
->buffer
+ start
;
6325 while ((endp
= etags_strchr (endp
, '"')) != NULL
6326 && endp
[-1] == '\\')
6329 /* Ok, this is a real #line directive. Let's deal with it. */
6331 char *taggedabsname
; /* absolute name of original file */
6332 char *taggedfname
; /* name of original file as given */
6333 char *name
; /* temp var */
6335 discard_until_line_directive
= FALSE
; /* found it */
6336 name
= lbp
->buffer
+ start
;
6338 canonicalize_filename (name
); /* for DOS */
6339 taggedabsname
= absolute_filename (name
, tagfiledir
);
6340 if (filename_is_absolute (name
)
6341 || filename_is_absolute (curfdp
->infname
))
6342 taggedfname
= savestr (taggedabsname
);
6344 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
6346 if (streq (curfdp
->taggedfname
, taggedfname
))
6347 /* The #line directive is only a line number change. We
6348 deal with this afterwards. */
6351 /* The tags following this #line directive should be
6352 attributed to taggedfname. In order to do this, set
6353 curfdp accordingly. */
6355 fdesc
*fdp
; /* file description pointer */
6357 /* Go look for a file description already set up for the
6358 file indicated in the #line directive. If there is
6359 one, use it from now until the next #line
6361 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6362 if (streq (fdp
->infname
, curfdp
->infname
)
6363 && streq (fdp
->taggedfname
, taggedfname
))
6364 /* If we remove the second test above (after the &&)
6365 then all entries pertaining to the same file are
6366 coalesced in the tags file. If we use it, then
6367 entries pertaining to the same file but generated
6368 from different files (via #line directives) will
6369 go into separate sections in the tags file. These
6370 alternatives look equivalent. The first one
6371 destroys some apparently useless information. */
6377 /* Else, if we already tagged the real file, skip all
6378 input lines until the next #line directive. */
6379 if (fdp
== NULL
) /* not found */
6380 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6381 if (streq (fdp
->infabsname
, taggedabsname
))
6383 discard_until_line_directive
= TRUE
;
6387 /* Else create a new file description and use that from
6388 now on, until the next #line directive. */
6389 if (fdp
== NULL
) /* not found */
6392 fdhead
= xnew (1, fdesc
);
6393 *fdhead
= *curfdp
; /* copy curr. file description */
6395 fdhead
->infname
= savestr (curfdp
->infname
);
6396 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
6397 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
6398 fdhead
->taggedfname
= taggedfname
;
6399 fdhead
->usecharno
= FALSE
;
6400 fdhead
->prop
= NULL
;
6401 fdhead
->written
= FALSE
;
6405 free (taggedabsname
);
6407 readline (lbp
, stream
);
6409 } /* if a real #line directive */
6410 } /* if #line is followed by a a number */
6411 } /* if line begins with "#line " */
6413 /* If we are here, no #line directive was found. */
6414 if (discard_until_line_directive
)
6418 /* Do a tail recursion on ourselves, thus discarding the contents
6419 of the line buffer. */
6420 readline (lbp
, stream
);
6424 discard_until_line_directive
= FALSE
;
6427 } /* if #line directives should be considered */
6434 /* Match against relevant regexps. */
6436 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6438 /* Only use generic regexps or those for the current language.
6439 Also do not use multiline regexps, which is the job of
6440 regex_tag_multiline. */
6441 if ((rp
->lang
!= NULL
&& rp
->lang
!= fdhead
->lang
)
6445 match
= re_match (rp
->pat
, lbp
->buffer
, lbp
->len
, 0, &rp
->regs
);
6450 if (!rp
->error_signaled
)
6452 error ("regexp stack overflow while matching \"%s\"",
6454 rp
->error_signaled
= TRUE
;
6461 /* Empty string matched. */
6462 if (!rp
->error_signaled
)
6464 error ("regexp matches the empty string: \"%s\"", rp
->pattern
);
6465 rp
->error_signaled
= TRUE
;
6469 /* Match occurred. Construct a tag. */
6471 if (name
[0] == '\0')
6473 else /* make a named tag */
6474 name
= substitute (lbp
->buffer
, rp
->name
, &rp
->regs
);
6475 if (rp
->force_explicit_name
)
6476 /* Force explicit tag name, if a name is there. */
6477 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
6479 make_tag (name
, strlen (name
), TRUE
,
6480 lbp
->buffer
, match
, lineno
, linecharno
);
6489 * Return a pointer to a space of size strlen(cp)+1 allocated
6490 * with xnew where the string CP has been copied.
6496 return savenstr (cp
, strlen (cp
));
6500 * Return a pointer to a space of size LEN+1 allocated with xnew where
6501 * the string CP has been copied for at most the first LEN characters.
6510 dp
= xnew (len
+ 1, char);
6511 strncpy (dp
, cp
, len
);
6517 * Return the ptr in sp at which the character c last
6518 * appears; NULL if not found
6520 * Identical to POSIX strrchr, included for portability.
6523 etags_strrchr (sp
, c
)
6524 register const char *sp
;
6527 register const char *r
;
6539 * Return the ptr in sp at which the character c first
6540 * appears; NULL if not found
6542 * Identical to POSIX strchr, included for portability.
6545 etags_strchr (sp
, c
)
6546 register const char *sp
;
6558 * Compare two strings, ignoring case for alphabetic characters.
6560 * Same as BSD's strcasecmp, included for portability.
6563 etags_strcasecmp (s1
, s2
)
6564 register const char *s1
;
6565 register const char *s2
;
6568 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6569 ? lowcase (*s1
) == lowcase (*s2
)
6573 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6574 ? lowcase (*s1
) - lowcase (*s2
)
6579 * Compare two strings, ignoring case for alphabetic characters.
6580 * Stop after a given number of characters
6582 * Same as BSD's strncasecmp, included for portability.
6585 etags_strncasecmp (s1
, s2
, n
)
6586 register const char *s1
;
6587 register const char *s2
;
6590 while (*s1
!= '\0' && n
-- > 0
6591 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6592 ? lowcase (*s1
) == lowcase (*s2
)
6599 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6600 ? lowcase (*s1
) - lowcase (*s2
)
6604 /* Skip spaces (end of string is not space), return new pointer. */
6609 while (iswhite (*cp
))
6614 /* Skip non spaces, except end of string, return new pointer. */
6616 skip_non_spaces (cp
)
6619 while (*cp
!= '\0' && !iswhite (*cp
))
6624 /* Print error message and exit. */
6630 exit (EXIT_FAILURE
);
6638 exit (EXIT_FAILURE
);
6642 suggest_asking_for_help ()
6644 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6645 progname
, NO_LONG_OPTIONS
? "-h" : "--help");
6646 exit (EXIT_FAILURE
);
6649 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6652 const char *s1
, *s2
;
6654 fprintf (stderr
, "%s: ", progname
);
6655 fprintf (stderr
, s1
, s2
);
6656 fprintf (stderr
, "\n");
6659 /* Return a newly-allocated string whose contents
6660 concatenate those of s1, s2, s3. */
6665 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6666 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6668 strcpy (result
, s1
);
6669 strcpy (result
+ len1
, s2
);
6670 strcpy (result
+ len1
+ len2
, s3
);
6671 result
[len1
+ len2
+ len3
] = '\0';
6677 /* Does the same work as the system V getcwd, but does not need to
6678 guess the buffer size in advance. */
6684 char *path
= xnew (bufsize
, char);
6686 while (getcwd (path
, bufsize
) == NULL
)
6688 if (errno
!= ERANGE
)
6692 path
= xnew (bufsize
, char);
6695 canonicalize_filename (path
);
6698 #else /* not HAVE_GETCWD */
6701 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6705 for (p
= path
; *p
!= '\0'; p
++)
6711 return strdup (path
);
6712 #else /* not MSDOS */
6716 linebuffer_init (&path
);
6717 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6718 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6723 #endif /* not MSDOS */
6724 #endif /* not HAVE_GETCWD */
6727 /* Return a newly allocated string containing the file name of FILE
6728 relative to the absolute directory DIR (which should end with a slash). */
6730 relative_filename (file
, dir
)
6733 char *fp
, *dp
, *afn
, *res
;
6736 /* Find the common root of file and dir (with a trailing slash). */
6737 afn
= absolute_filename (file
, cwd
);
6740 while (*fp
++ == *dp
++)
6742 fp
--, dp
--; /* back to the first differing char */
6744 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6747 do /* look at the equal chars until '/' */
6751 /* Build a sequence of "../" strings for the resulting relative file name. */
6753 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6755 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6758 strcat (res
, "../");
6760 /* Add the file name relative to the common root of file and dir. */
6761 strcat (res
, fp
+ 1);
6767 /* Return a newly allocated string containing the absolute file name
6768 of FILE given DIR (which should end with a slash). */
6770 absolute_filename (file
, dir
)
6773 char *slashp
, *cp
, *res
;
6775 if (filename_is_absolute (file
))
6776 res
= savestr (file
);
6778 /* We don't support non-absolute file names with a drive
6779 letter, like `d:NAME' (it's too much hassle). */
6780 else if (file
[1] == ':')
6781 fatal ("%s: relative file names with drive letters not supported", file
);
6784 res
= concat (dir
, file
, "");
6786 /* Delete the "/dirname/.." and "/." substrings. */
6787 slashp
= etags_strchr (res
, '/');
6788 while (slashp
!= NULL
&& slashp
[0] != '\0')
6790 if (slashp
[1] == '.')
6792 if (slashp
[2] == '.'
6793 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6798 while (cp
>= res
&& !filename_is_absolute (cp
));
6800 cp
= slashp
; /* the absolute name begins with "/.." */
6802 /* Under MSDOS and NT we get `d:/NAME' as absolute
6803 file name, so the luser could say `d:/../NAME'.
6804 We silently treat this as `d:/NAME'. */
6805 else if (cp
[0] != '/')
6808 strcpy (cp
, slashp
+ 3);
6812 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6814 strcpy (slashp
, slashp
+ 2);
6819 slashp
= etags_strchr (slashp
+ 1, '/');
6822 if (res
[0] == '\0') /* just a safety net: should never happen */
6825 return savestr ("/");
6831 /* Return a newly allocated string containing the absolute
6832 file name of dir where FILE resides given DIR (which should
6833 end with a slash). */
6835 absolute_dirname (file
, dir
)
6841 canonicalize_filename (file
);
6842 slashp
= etags_strrchr (file
, '/');
6844 return savestr (dir
);
6847 res
= absolute_filename (file
, dir
);
6853 /* Whether the argument string is an absolute file name. The argument
6854 string must have been canonicalized with canonicalize_filename. */
6856 filename_is_absolute (fn
)
6859 return (fn
[0] == '/'
6861 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6866 /* Translate backslashes into slashes. Works in place. */
6868 canonicalize_filename (fn
)
6872 /* Canonicalize drive letter case. */
6873 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6874 fn
[0] = upcase (fn
[0]);
6875 /* Convert backslashes to slashes. */
6876 for (; *fn
!= '\0'; fn
++)
6881 fn
= NULL
; /* shut up the compiler */
6886 /* Initialize a linebuffer for use */
6888 linebuffer_init (lbp
)
6891 lbp
->size
= (DEBUG
) ? 3 : 200;
6892 lbp
->buffer
= xnew (lbp
->size
, char);
6893 lbp
->buffer
[0] = '\0';
6897 /* Set the minimum size of a string contained in a linebuffer. */
6899 linebuffer_setlen (lbp
, toksize
)
6903 while (lbp
->size
<= toksize
)
6906 xrnew (lbp
->buffer
, lbp
->size
, char);
6911 /* Like malloc but get fatal error if memory is exhausted. */
6916 PTR result
= (PTR
) malloc (size
);
6918 fatal ("virtual memory exhausted", (char *)NULL
);
6923 xrealloc (ptr
, size
)
6927 PTR result
= (PTR
) realloc (ptr
, size
);
6929 fatal ("virtual memory exhausted", (char *)NULL
);
6935 * indent-tabs-mode: t
6938 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")
6939 * c-file-style: "gnu"
6943 /* arch-tag: 8a9b748d-390c-4922-99db-2eeefa921051
6944 (do not change this comment) */
6946 /* etags.c ends here */