1 /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*-
2 Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of GNU Emacs.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Line-by-line regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
32 * 2002 #line directives by Francesco Potortì.
34 * Francesco Potortì <pot@gnu.org> has maintained and improved it since 1993.
38 char pot_etags_version
[] = "@(#) pot revision number is 16.32";
48 # define NDEBUG /* disable assert */
53 /* On some systems, Emacs defines static as nothing for the sake
54 of unexec. We don't want that here since we don't use unexec. */
56 # define ETAGS_REGEXPS /* use the regexp features */
57 # define LONG_OPTIONS /* accept long options */
58 # ifndef PTR /* for Xemacs */
61 # ifndef __P /* for Xemacs */
62 # define __P(args) args
65 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
66 # define __P(args) args /* use prototypes */
67 # define PTR void * /* for generic pointers */
69 # define __P(args) () /* no prototypes */
70 # define const /* remove const for old compilers' sake */
71 # define PTR long * /* don't use void* */
73 #endif /* !HAVE_CONFIG_H */
76 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
79 /* WIN32_NATIVE is for Xemacs.
80 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
85 #endif /* WIN32_NATIVE */
91 # include <sys/param.h>
93 # ifndef HAVE_CONFIG_H
95 # include <sys/config.h>
107 # define MAXPATHLEN _MAX_PATH
113 # endif /* undef HAVE_GETCWD */
114 #else /* !WINDOWSNT */
119 extern char *getenv ();
121 #endif /* !WINDOWSNT */
126 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
127 extern char *getcwd (char *buf
, size_t size
);
129 #endif /* HAVE_UNISTD_H */
137 #include <sys/types.h>
138 #include <sys/stat.h>
142 # undef assert /* some systems have a buggy assert.h */
143 # define assert(x) ((void) 0)
146 #if !defined (S_ISREG) && defined (S_IFREG)
147 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
153 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
155 extern int optind
, opterr
;
156 #endif /* LONG_OPTIONS */
159 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
160 # ifdef __CYGWIN__ /* compiling on Cygwin */
162 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
163 If you want regular expression support
, you should
delete this notice
and
164 arrange to use the GNU regex
.h
and regex
.c
.
168 #endif /* ETAGS_REGEXPS */
170 /* Define CTAGS to make the program "ctags" compatible with the usual one.
171 Leave it undefined to make the program "etags", which makes emacs-style
172 tag tables and tags typedefs, #defines and struct/union/enum by default. */
180 /* Exit codes for success and failure. */
189 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
190 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
192 #define CHARS 256 /* 2^sizeof(char) */
193 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
194 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
195 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
196 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
197 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
198 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
200 #define ISALNUM(c) isalnum (CHAR(c))
201 #define ISALPHA(c) isalpha (CHAR(c))
202 #define ISDIGIT(c) isdigit (CHAR(c))
203 #define ISLOWER(c) islower (CHAR(c))
205 #define lowcase(c) tolower (CHAR(c))
206 #define upcase(c) toupper (CHAR(c))
210 * xnew, xrnew -- allocate, reallocate storage
212 * SYNOPSIS: Type *xnew (int n, Type);
213 * void xrnew (OldPointer, int n, Type);
216 # include "chkmalloc.h"
217 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
218 (n) * sizeof (Type)))
219 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
220 (char *) (op), (n) * sizeof (Type)))
222 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
223 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
224 (char *) (op), (n) * sizeof (Type)))
229 typedef void Lang_function
__P((FILE *));
233 char *suffix
; /* file name suffix for this compressor */
234 char *command
; /* takes one arg and decompresses to stdout */
239 char *name
; /* language name */
240 bool metasource
; /* source used to generate other sources */
241 Lang_function
*function
; /* parse function */
242 char **filenames
; /* names of this language's files */
243 char **suffixes
; /* name suffixes of this language's files */
244 char **interpreters
; /* interpreters for this language */
249 struct fdesc
*next
; /* for the linked list */
250 char *infname
; /* uncompressed input file name */
251 char *infabsname
; /* absolute uncompressed input file name */
252 char *infabsdir
; /* absolute dir of input file */
253 char *taggedfname
; /* file name to write in tagfile */
254 language
*lang
; /* language of file */
255 char *prop
; /* file properties to write in tagfile */
256 bool usecharno
; /* etags tags shall contain char number */
259 typedef struct node_st
260 { /* sorting structure */
261 struct node_st
*left
, *right
; /* left and right sons */
262 fdesc
*fdp
; /* description of file to whom tag belongs */
263 char *name
; /* tag name */
264 char *pat
; /* search pattern */
265 bool valid
; /* write this tag on the tag file */
266 bool is_func
; /* function tag: use pattern in CTAGS mode */
267 bool been_warned
; /* warning already given for duplicated tag */
268 int lno
; /* line number tag is on */
269 long cno
; /* character number line starts on */
273 * A `linebuffer' is a structure which holds a line of text.
274 * `readline_internal' reads a line from a stream into a linebuffer
275 * and works regardless of the length of the line.
276 * SIZE is the size of BUFFER, LEN is the length of the string in
277 * BUFFER after readline reads it.
286 /* Used to support mixing of --lang and file names. */
290 at_language
, /* a language specification */
291 at_regexp
, /* a regular expression */
292 at_filename
, /* a file name */
293 at_stdin
/* read from stdin here */
294 } arg_type
; /* argument type */
295 language
*lang
; /* language associated with the argument */
296 char *what
; /* the argument itself */
300 /* Structure defining a regular expression. */
301 typedef struct pattern
303 struct pattern
*p_next
;
306 struct re_pattern_buffer
*pat
;
307 struct re_registers regs
;
313 #endif /* ETAGS_REGEXPS */
316 /* Many compilers barf on this:
317 Lang_function Ada_funcs;
318 so let's write it this way */
319 static void Ada_funcs
__P((FILE *));
320 static void Asm_labels
__P((FILE *));
321 static void C_entries
__P((int c_ext
, FILE *));
322 static void default_C_entries
__P((FILE *));
323 static void plain_C_entries
__P((FILE *));
324 static void Cjava_entries
__P((FILE *));
325 static void Cobol_paragraphs
__P((FILE *));
326 static void Cplusplus_entries
__P((FILE *));
327 static void Cstar_entries
__P((FILE *));
328 static void Erlang_functions
__P((FILE *));
329 static void Fortran_functions
__P((FILE *));
330 static void Yacc_entries
__P((FILE *));
331 static void Lisp_functions
__P((FILE *));
332 static void Makefile_targets
__P((FILE *));
333 static void Pascal_functions
__P((FILE *));
334 static void Perl_functions
__P((FILE *));
335 static void PHP_functions
__P((FILE *));
336 static void Postscript_functions
__P((FILE *));
337 static void Prolog_functions
__P((FILE *));
338 static void Python_functions
__P((FILE *));
339 static void Scheme_functions
__P((FILE *));
340 static void TeX_commands
__P((FILE *));
341 static void Texinfo_nodes
__P((FILE *));
342 static void just_read_file
__P((FILE *));
344 static void print_language_names
__P((void));
345 static void print_version
__P((void));
346 static void print_help
__P((void));
347 int main
__P((int, char **));
349 static compressor
*get_compressor_from_suffix
__P((char *, char **));
350 static language
*get_language_from_langname
__P((const char *));
351 static language
*get_language_from_interpreter
__P((char *));
352 static language
*get_language_from_filename
__P((char *, bool));
353 static void readline
__P((linebuffer
*, FILE *));
354 static long readline_internal
__P((linebuffer
*, FILE *));
355 static bool nocase_tail
__P((char *));
356 static void get_tag
__P((char *, char **));
359 static void analyse_regex
__P((char *));
360 static void free_patterns
__P((void));
361 static void regex_tag_multiline
__P((void));
362 #endif /* ETAGS_REGEXPS */
363 static void error
__P((const char *, const char *));
364 static void suggest_asking_for_help
__P((void));
365 void fatal
__P((char *, char *));
366 static void pfatal
__P((char *));
367 static void add_node
__P((node
*, node
**));
369 static void init
__P((void));
370 static void initbuffer
__P((linebuffer
*));
371 static void process_file_name
__P((char *, language
*));
372 static void process_file
__P((FILE *, char *, language
*));
373 static void find_entries
__P((FILE *));
374 static void free_tree
__P((node
*));
375 static void free_fdesc
__P((fdesc
*));
376 static void pfnote
__P((char *, bool, char *, int, int, long));
377 static void make_tag
__P((char *, int, bool, char *, int, int, long));
378 static void invalidate_nodes
__P((fdesc
*, node
**));
379 static void put_entries
__P((node
*));
381 static char *concat
__P((char *, char *, char *));
382 static char *skip_spaces
__P((char *));
383 static char *skip_non_spaces
__P((char *));
384 static char *savenstr
__P((char *, int));
385 static char *savestr
__P((char *));
386 static char *etags_strchr
__P((const char *, int));
387 static char *etags_strrchr
__P((const char *, int));
388 static bool strcaseeq
__P((const char *, const char *));
389 static char *etags_getcwd
__P((void));
390 static char *relative_filename
__P((char *, char *));
391 static char *absolute_filename
__P((char *, char *));
392 static char *absolute_dirname
__P((char *, char *));
393 static bool filename_is_absolute
__P((char *f
));
394 static void canonicalize_filename
__P((char *));
395 static void linebuffer_setlen
__P((linebuffer
*, int));
396 static PTR xmalloc
__P((unsigned int));
397 static PTR xrealloc
__P((char *, unsigned int));
400 static char searchar
= '/'; /* use /.../ searches */
402 static char *tagfile
; /* output file */
403 static char *progname
; /* name this program was invoked with */
404 static char *cwd
; /* current working directory */
405 static char *tagfiledir
; /* directory of tagfile */
406 static FILE *tagf
; /* ioptr for tags file */
408 static fdesc
*fdhead
; /* head of file description list */
409 static fdesc
*curfdp
; /* current file description */
410 static int lineno
; /* line number of current line */
411 static long charno
; /* current character number */
412 static long linecharno
; /* charno of start of current line */
413 static char *dbp
; /* pointer to start of current tag */
415 static const int invalidcharno
= -1;
417 static node
*nodehead
; /* the head of the binary tree of tags */
418 static node
*last_node
; /* the last node created */
420 static linebuffer lb
; /* the current line */
421 static linebuffer filebuf
; /* a buffer containing the whole file */
423 /* boolean "functions" (see init) */
424 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
427 *white
= " \f\t\n\r\v",
429 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
430 /* token ending chars */
431 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
432 /* token starting chars */
433 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
434 /* valid in-token chars */
435 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
437 static bool append_to_tagfile
; /* -a: append to tags */
438 /* The next four default to TRUE for etags, but to FALSE for ctags. */
439 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
440 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
441 /* 0 struct/enum/union decls, and C++ */
442 /* member functions. */
443 static bool constantypedefs
; /* -d: create tags for C #define, enum */
444 /* constants and variables. */
445 /* -D: opposite of -d. Default under ctags. */
446 static bool globals
; /* create tags for global variables */
447 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
448 static bool members
; /* create tags for C member variables */
449 static bool no_line_directive
; /* ignore #line directives (undocumented) */
450 static bool update
; /* -u: update tags */
451 static bool vgrind_style
; /* -v: create vgrind style index output */
452 static bool no_warnings
; /* -w: suppress warnings */
453 static bool cxref_style
; /* -x: create cxref style output */
454 static bool cplusplus
; /* .[hc] means C++, not C */
455 static bool noindentypedefs
; /* -I: ignore indentation in C */
456 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
458 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
459 static bool parsing_stdin
; /* --parse-stdin used */
462 static pattern
*p_head
; /* list of all regexps */
463 static bool need_filebuf
; /* some regexes are multi-line */
465 # define need_filebuf FALSE
466 #endif /* ETAGS_REGEXPS */
469 static struct option longopts
[] =
471 { "packages-only", no_argument
, &packages_only
, TRUE
},
472 { "c++", no_argument
, NULL
, 'C' },
473 { "declarations", no_argument
, &declarations
, TRUE
},
474 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
475 { "help", no_argument
, NULL
, 'h' },
476 { "help", no_argument
, NULL
, 'H' },
477 { "ignore-indentation", no_argument
, NULL
, 'I' },
478 { "language", required_argument
, NULL
, 'l' },
479 { "members", no_argument
, &members
, TRUE
},
480 { "no-members", no_argument
, &members
, FALSE
},
481 { "output", required_argument
, NULL
, 'o' },
483 { "regex", required_argument
, NULL
, 'r' },
484 { "no-regex", no_argument
, NULL
, 'R' },
485 { "ignore-case-regex", required_argument
, NULL
, 'c' },
486 #endif /* ETAGS_REGEXPS */
487 { "parse-stdin", required_argument
, NULL
, STDIN
},
488 { "version", no_argument
, NULL
, 'V' },
490 #if CTAGS /* Etags options */
491 { "backward-search", no_argument
, NULL
, 'B' },
492 { "cxref", no_argument
, NULL
, 'x' },
493 { "defines", no_argument
, NULL
, 'd' },
494 { "globals", no_argument
, &globals
, TRUE
},
495 { "typedefs", no_argument
, NULL
, 't' },
496 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
497 { "update", no_argument
, NULL
, 'u' },
498 { "vgrind", no_argument
, NULL
, 'v' },
499 { "no-warn", no_argument
, NULL
, 'w' },
501 #else /* Ctags options */
502 { "append", no_argument
, NULL
, 'a' },
503 { "no-defines", no_argument
, NULL
, 'D' },
504 { "no-globals", no_argument
, &globals
, FALSE
},
505 { "include", required_argument
, NULL
, 'i' },
509 #endif /* LONG_OPTIONS */
511 static compressor compressors
[] =
513 { "z", "gzip -d -c"},
514 { "Z", "gzip -d -c"},
515 { "gz", "gzip -d -c"},
516 { "GZ", "gzip -d -c"},
517 { "bz2", "bzip2 -d -c" },
526 static char *Ada_suffixes
[] =
527 { "ads", "adb", "ada", NULL
};
530 static char *Asm_suffixes
[] =
531 { "a", /* Unix assembler */
532 "asm", /* Microcontroller assembly */
533 "def", /* BSO/Tasking definition includes */
534 "inc", /* Microcontroller include files */
535 "ins", /* Microcontroller include files */
536 "s", "sa", /* Unix assembler */
537 "S", /* cpp-processed Unix assembler */
538 "src", /* BSO/Tasking C compiler output */
542 /* Note that .c and .h can be considered C++, if the --c++ flag was
543 given, or if the `class' keyowrd is met inside the file.
544 That is why default_C_entries is called for these. */
545 static char *default_C_suffixes
[] =
548 static char *Cplusplus_suffixes
[] =
549 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
550 "M", /* Objective C++ */
551 "pdb", /* Postscript with C syntax */
554 static char *Cjava_suffixes
[] =
557 static char *Cobol_suffixes
[] =
558 { "COB", "cob", NULL
};
560 static char *Cstar_suffixes
[] =
561 { "cs", "hs", NULL
};
563 static char *Erlang_suffixes
[] =
564 { "erl", "hrl", NULL
};
566 static char *Fortran_suffixes
[] =
567 { "F", "f", "f90", "for", NULL
};
569 static char *Lisp_suffixes
[] =
570 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
572 static char *Makefile_filenames
[] =
573 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
575 static char *Pascal_suffixes
[] =
576 { "p", "pas", NULL
};
578 static char *Perl_suffixes
[] =
579 { "pl", "pm", NULL
};
581 static char *Perl_interpreters
[] =
582 { "perl", "@PERL@", NULL
};
584 static char *PHP_suffixes
[] =
585 { "php", "php3", "php4", NULL
};
587 static char *plain_C_suffixes
[] =
588 { "lm", /* Objective lex file */
589 "m", /* Objective C file */
590 "pc", /* Pro*C file */
593 static char *Postscript_suffixes
[] =
594 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
596 static char *Prolog_suffixes
[] =
599 static char *Python_suffixes
[] =
602 /* Can't do the `SCM' or `scm' prefix with a version number. */
603 static char *Scheme_suffixes
[] =
604 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
606 static char *TeX_suffixes
[] =
607 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
609 static char *Texinfo_suffixes
[] =
610 { "texi", "texinfo", "txi", NULL
};
612 static char *Yacc_suffixes
[] =
613 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
616 * Table of languages.
618 * It is ok for a given function to be listed under more than one
619 * name. I just didn't.
622 static language lang_names
[] =
624 { "ada", FALSE
, Ada_funcs
, NULL
, Ada_suffixes
, NULL
},
625 { "asm", FALSE
, Asm_labels
, NULL
, Asm_suffixes
, NULL
},
626 { "c", FALSE
, default_C_entries
, NULL
, default_C_suffixes
, NULL
},
627 { "c++", FALSE
, Cplusplus_entries
, NULL
, Cplusplus_suffixes
, NULL
},
628 { "c*", FALSE
, Cstar_entries
, NULL
, Cstar_suffixes
, NULL
},
629 { "cobol", FALSE
, Cobol_paragraphs
, NULL
, Cobol_suffixes
, NULL
},
630 { "erlang", FALSE
, Erlang_functions
, NULL
, Erlang_suffixes
, NULL
},
631 { "fortran", FALSE
, Fortran_functions
, NULL
, Fortran_suffixes
, NULL
},
632 { "java", FALSE
, Cjava_entries
, NULL
, Cjava_suffixes
, NULL
},
633 { "lisp", FALSE
, Lisp_functions
, NULL
, Lisp_suffixes
, NULL
},
634 { "makefile", FALSE
, Makefile_targets
, Makefile_filenames
, NULL
, NULL
},
635 { "pascal", FALSE
, Pascal_functions
, NULL
, Pascal_suffixes
, NULL
},
636 { "perl", FALSE
, Perl_functions
,NULL
, Perl_suffixes
, Perl_interpreters
},
637 { "php", FALSE
, PHP_functions
, NULL
, PHP_suffixes
, NULL
},
638 { "postscript",FALSE
, Postscript_functions
,NULL
, Postscript_suffixes
, NULL
},
639 { "proc", FALSE
, plain_C_entries
, NULL
, plain_C_suffixes
, NULL
},
640 { "prolog", FALSE
, Prolog_functions
, NULL
, Prolog_suffixes
, NULL
},
641 { "python", FALSE
, Python_functions
, NULL
, Python_suffixes
, NULL
},
642 { "scheme", FALSE
, Scheme_functions
, NULL
, Scheme_suffixes
, NULL
},
643 { "tex", FALSE
, TeX_commands
, NULL
, TeX_suffixes
, NULL
},
644 { "texinfo", FALSE
, Texinfo_nodes
, NULL
, Texinfo_suffixes
, NULL
},
645 { "yacc", TRUE
, Yacc_entries
, NULL
, Yacc_suffixes
, NULL
},
646 { "auto", FALSE
, NULL
}, /* default guessing scheme */
647 { "none", FALSE
, just_read_file
}, /* regexp matching only */
648 { NULL
, FALSE
, NULL
} /* end of list */
653 print_language_names ()
658 puts ("\nThese are the currently supported languages, along with the\n\
659 default file names and dot suffixes:");
660 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
662 printf (" %-*s", 10, lang
->name
);
663 if (lang
->filenames
!= NULL
)
664 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
665 printf (" %s", *name
);
666 if (lang
->suffixes
!= NULL
)
667 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
668 printf (" .%s", *ext
);
671 puts ("Where `auto' means use default language for files based on file\n\
672 name suffix, and `none' means only do regexp processing on files.\n\
673 If no language is specified and no matching suffix is found,\n\
674 the first line of the file is read for a sharp-bang (#!) sequence\n\
675 followed by the name of an interpreter. If no such sequence is found,\n\
676 Fortran is tried first; if no tags are found, C is tried next.\n\
677 When parsing any C file, a \"class\" keyword switches to C++.\n\
678 Compressed files are supported using gzip and bzip2.");
682 # define EMACS_NAME "standalone"
685 # define VERSION "version"
690 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
691 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
692 puts ("This program is distributed under the same terms as Emacs");
700 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
702 These are the options accepted by %s.\n", progname
, progname
);
704 puts ("You may use unambiguous abbreviations for the long option names.");
706 puts ("Long option names do not work with this executable, as it is not\n\
707 linked with GNU getopt.");
708 #endif /* LONG_OPTIONS */
709 puts (" A - as file name means read names from stdin (one per line).\n\
710 Absolute names are stored in the output file as they are.\n\
711 Relative ones are stored relative to the output file's directory.\n");
714 puts ("-a, --append\n\
715 Append tag entries to existing tags file.");
717 puts ("--packages-only\n\
718 For Ada files, only generate tags for packages.");
721 puts ("-B, --backward-search\n\
722 Write the search commands for the tag entries using '?', the\n\
723 backward-search command instead of '/', the forward-search command.");
725 /* This option is mostly obsolete, because etags can now automatically
726 detect C++. Retained for backward compatibility and for debugging and
727 experimentation. In principle, we could want to tag as C++ even
728 before any "class" keyword.
730 Treat files whose name suffix defaults to C language as C++ files.");
733 puts ("--declarations\n\
734 In C and derived languages, create tags for function declarations,");
736 puts ("\tand create tags for extern variables if --globals is used.");
739 ("\tand create tags for extern variables unless --no-globals is used.");
742 puts ("-d, --defines\n\
743 Create tag entries for C #define constants and enum constants, too.");
745 puts ("-D, --no-defines\n\
746 Don't create tag entries for C #define constants and enum constants.\n\
747 This makes the tags file smaller.");
750 puts ("-i FILE, --include=FILE\n\
751 Include a note in tag file indicating that, when searching for\n\
752 a tag, one should also consult the tags file FILE after\n\
753 checking the current file.");
755 puts ("-l LANG, --language=LANG\n\
756 Force the following files to be considered as written in the\n\
757 named language up to the next --language=LANG option.");
761 Create tag entries for global variables in some languages.");
763 puts ("--no-globals\n\
764 Do not create tag entries for global variables in some\n\
765 languages. This makes the tags file smaller.");
767 Create tag entries for member variables in C and derived languages.");
770 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
771 Make a tag for each line matching the regular expression pattern\n\
772 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
773 files only. REGEXFILE is a file containing one REGEXP per line.\n\
774 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
775 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
776 puts (" If TAGNAME/ is present, the tags created are named.\n\
777 For example Tcl named tags can be created with:\n\
778 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
779 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
780 `m' means to allow multi-line matches, `s' implies `m' and\n\
781 causes dot to match the newline character as well.");
782 puts ("-R, --no-regex\n\
783 Don't create tags from regexps for the following files.");
784 #endif /* ETAGS_REGEXPS */
785 puts ("-I, --ignore-indentation\n\
786 Don't rely on indentation quite as much as normal. Currently,\n\
787 this means not to assume that a closing brace in the first\n\
788 column is the final brace of a function or structure\n\
789 definition in C and C++.");
790 puts ("-o FILE, --output=FILE\n\
791 Write the tags to FILE.");
792 puts ("--parse-stdin=NAME\n\
793 Read from standard input and record tags as belonging to file NAME.");
797 puts ("-t, --typedefs\n\
798 Generate tag entries for C and Ada typedefs.");
799 puts ("-T, --typedefs-and-c++\n\
800 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
801 and C++ member functions.");
805 puts ("-u, --update\n\
806 Update the tag entries for the given files, leaving tag\n\
807 entries for other files in place. Currently, this is\n\
808 implemented by deleting the existing entries for the given\n\
809 files and then rewriting the new entries at the end of the\n\
810 tags file. It is often faster to simply rebuild the entire\n\
811 tag file than to use this.");
815 puts ("-v, --vgrind\n\
816 Generates an index of items intended for human consumption,\n\
817 similar to the output of vgrind. The index is sorted, and\n\
818 gives the page number of each item.");
819 puts ("-w, --no-warn\n\
820 Suppress warning messages about entries defined in multiple\n\
822 puts ("-x, --cxref\n\
823 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
824 The output uses line numbers instead of page numbers, but\n\
825 beyond that the differences are cosmetic; try both to see\n\
829 puts ("-V, --version\n\
830 Print the version of the program.\n\
832 Print this help message.");
834 print_language_names ();
837 puts ("Report bugs to bug-gnu-emacs@gnu.org");
843 #ifdef VMS /* VMS specific functions */
847 /* This is a BUG! ANY arbitrary limit is a BUG!
848 Won't someone please fix this? */
849 #define MAX_FILE_SPEC_LEN 255
852 char body
[MAX_FILE_SPEC_LEN
+ 1];
856 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
857 returning in each successive call the next file name matching the input
858 spec. The function expects that each in_spec passed
859 to it will be processed to completion; in particular, up to and
860 including the call following that in which the last matching name
861 is returned, the function ignores the value of in_spec, and will
862 only start processing a new spec with the following call.
863 If an error occurs, on return out_spec contains the value
864 of in_spec when the error occurred.
866 With each successive file name returned in out_spec, the
867 function's return value is one. When there are no more matching
868 names the function returns zero. If on the first call no file
869 matches in_spec, or there is any other error, -1 is returned.
874 #define OUTSIZE MAX_FILE_SPEC_LEN
880 static long context
= 0;
881 static struct dsc$descriptor_s o
;
882 static struct dsc$descriptor_s i
;
883 static bool pass1
= TRUE
;
890 o
.dsc$a_pointer
= (char *) out
;
891 o
.dsc$w_length
= (short)OUTSIZE
;
892 i
.dsc$a_pointer
= in
;
893 i
.dsc$w_length
= (short)strlen(in
);
894 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
895 i
.dsc$b_class
= DSC$K_CLASS_S
;
896 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
897 o
.dsc$b_class
= DSC$K_CLASS_VS
;
899 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
901 out
->body
[out
->curlen
] = EOS
;
904 else if (status
== RMS$_NMF
)
908 strcpy(out
->body
, in
);
911 lib$
find_file_end(&context
);
917 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
918 name of each file specified by the provided arg expanding wildcards.
921 gfnames (arg
, p_error
)
925 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
927 switch (fn_exp (&filename
, arg
))
931 return filename
.body
;
937 return filename
.body
;
941 #ifndef OLD /* Newer versions of VMS do provide `system'. */
945 error ("%s", "system() function not implemented under VMS");
949 #define VERSION_DELIM ';'
950 char *massage_name (s
)
956 if (*s
== VERSION_DELIM
)
974 unsigned int nincluded_files
;
975 char **included_files
;
977 int current_arg
, file_count
;
978 linebuffer filename_lb
;
987 _fmode
= O_BINARY
; /* all of files are treated as binary files */
992 included_files
= xnew (argc
, char *);
996 /* Allocate enough no matter what happens. Overkill, but each one
998 argbuffer
= xnew (argc
, argument
);
1001 * If etags, always find typedefs and structure tags. Why not?
1002 * Also default to find macro constants, enum constants and
1007 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1012 #ifdef ETAGS_REGEXPS
1013 optstring
= "-r:Rc:";
1014 #endif /* ETAGS_REGEXPS */
1015 #ifndef LONG_OPTIONS
1016 optstring
= optstring
+ 1;
1017 #endif /* LONG_OPTIONS */
1018 optstring
= concat (optstring
,
1020 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1022 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0)) != EOF
)
1026 /* If getopt returns 0, then it has already processed a
1027 long-named option. We should do nothing. */
1031 /* This means that a file name has been seen. Record it. */
1032 argbuffer
[current_arg
].arg_type
= at_filename
;
1033 argbuffer
[current_arg
].what
= optarg
;
1039 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1040 argbuffer
[current_arg
].arg_type
= at_stdin
;
1041 argbuffer
[current_arg
].what
= optarg
;
1045 fatal ("cannot parse standard input more than once", (char *)NULL
);
1046 parsing_stdin
= TRUE
;
1049 /* Common options. */
1050 case 'C': cplusplus
= TRUE
; break;
1051 case 'f': /* for compatibility with old makefiles */
1055 error ("-o option may only be given once.", (char *)NULL
);
1056 suggest_asking_for_help ();
1061 case 'S': /* for backward compatibility */
1062 noindentypedefs
= TRUE
;
1066 language
*lang
= get_language_from_langname (optarg
);
1069 argbuffer
[current_arg
].lang
= lang
;
1070 argbuffer
[current_arg
].arg_type
= at_language
;
1076 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1077 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1080 argbuffer
[current_arg
].arg_type
= at_regexp
;
1081 argbuffer
[current_arg
].what
= optarg
;
1085 argbuffer
[current_arg
].arg_type
= at_regexp
;
1086 argbuffer
[current_arg
].what
= NULL
;
1098 case 'a': append_to_tagfile
= TRUE
; break;
1099 case 'D': constantypedefs
= FALSE
; break;
1100 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1102 /* Ctags options. */
1103 case 'B': searchar
= '?'; break;
1104 case 'd': constantypedefs
= TRUE
; break;
1105 case 't': typedefs
= TRUE
; break;
1106 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1107 case 'u': update
= TRUE
; break;
1108 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1109 case 'x': cxref_style
= TRUE
; break;
1110 case 'w': no_warnings
= TRUE
; break;
1112 suggest_asking_for_help ();
1115 for (; optind
< argc
; ++optind
)
1117 argbuffer
[current_arg
].arg_type
= at_filename
;
1118 argbuffer
[current_arg
].what
= argv
[optind
];
1123 if (nincluded_files
== 0 && file_count
== 0)
1125 error ("no input files specified.", (char *)NULL
);
1126 suggest_asking_for_help ();
1129 if (tagfile
== NULL
)
1130 tagfile
= CTAGS
? "tags" : "TAGS";
1131 cwd
= etags_getcwd (); /* the current working directory */
1132 if (cwd
[strlen (cwd
) - 1] != '/')
1135 cwd
= concat (oldcwd
, "/", "");
1138 if (streq (tagfile
, "-"))
1141 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1143 init (); /* set up boolean "functions" */
1146 initbuffer (&filename_lb
);
1147 initbuffer (&filebuf
);
1151 if (streq (tagfile
, "-"))
1155 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1156 doesn't take effect until after `stdout' is already open). */
1157 if (!isatty (fileno (stdout
)))
1158 setmode (fileno (stdout
), O_BINARY
);
1162 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1168 * Loop through files finding functions.
1170 for (i
= 0; i
< current_arg
; ++i
)
1172 static language
*lang
; /* non-NULL if language is forced */
1175 switch (argbuffer
[i
].arg_type
)
1178 lang
= argbuffer
[i
].lang
;
1180 #ifdef ETAGS_REGEXPS
1182 analyse_regex (argbuffer
[i
].what
);
1187 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1191 error ("can't find file %s\n", this_file
);
1196 this_file
= massage_name (this_file
);
1199 this_file
= argbuffer
[i
].what
;
1201 /* Input file named "-" means read file names from stdin
1202 (one per line) and use them. */
1203 if (streq (this_file
, "-"))
1206 fatal ("cannot parse standard input AND read file names from it",
1208 while (readline_internal (&filename_lb
, stdin
) > 0)
1209 process_file_name (filename_lb
.buffer
, lang
);
1212 process_file_name (this_file
, lang
);
1218 this_file
= argbuffer
[i
].what
;
1219 process_file (stdin
, this_file
, lang
);
1224 #ifdef ETAGS_REGEXPS
1226 #endif /* ETAGS_REGEXPS */
1227 free (filebuf
.buffer
);
1229 if (!CTAGS
|| cxref_style
)
1231 put_entries (nodehead
); /* write the remainig tags (ETAGS) */
1232 free_tree (nodehead
);
1235 while (nincluded_files
-- > 0)
1236 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1238 if (fclose (tagf
) == EOF
)
1246 for (i
= 0; i
< current_arg
; ++i
)
1248 switch (argbuffer
[i
].arg_type
)
1254 continue; /* the for loop */
1257 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1258 tagfile
, argbuffer
[i
].what
, tagfile
);
1259 if (system (cmd
) != GOOD
)
1260 fatal ("failed to execute shell command", (char *)NULL
);
1262 append_to_tagfile
= TRUE
;
1265 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1268 put_entries (nodehead
); /* write all the tags (CTAGS) */
1269 free_tree (nodehead
);
1271 if (fclose (tagf
) == EOF
)
1276 char cmd
[2*BUFSIZ
+10];
1277 sprintf (cmd
, "sort -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1278 exit (system (cmd
));
1285 * Return a compressor given the file name. If EXTPTR is non-zero,
1286 * return a pointer into FILE where the compressor-specific
1287 * extension begins. If no compressor is found, NULL is returned
1288 * and EXTPTR is not significant.
1289 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1292 get_compressor_from_suffix (file
, extptr
)
1297 char *slash
, *suffix
;
1299 /* This relies on FN to be after canonicalize_filename,
1300 so we don't need to consider backslashes on DOS_NT. */
1301 slash
= etags_strrchr (file
, '/');
1302 suffix
= etags_strrchr (file
, '.');
1303 if (suffix
== NULL
|| suffix
< slash
)
1308 /* Let those poor souls who live with DOS 8+3 file name limits get
1309 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1310 Only the first do loop is run if not MSDOS */
1313 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1314 if (streq (compr
->suffix
, suffix
))
1317 break; /* do it only once: not really a loop */
1320 } while (*suffix
!= '\0');
1327 * Return a language given the name.
1330 get_language_from_langname (name
)
1336 error ("empty language name", (char *)NULL
);
1339 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1340 if (streq (name
, lang
->name
))
1342 error ("unknown language \"%s\"", name
);
1350 * Return a language given the interpreter name.
1353 get_language_from_interpreter (interpreter
)
1359 if (interpreter
== NULL
)
1361 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1362 if (lang
->interpreters
!= NULL
)
1363 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1364 if (streq (*iname
, interpreter
))
1373 * Return a language given the file name.
1376 get_language_from_filename (file
, case_sensitive
)
1378 bool case_sensitive
;
1381 char **name
, **ext
, *suffix
;
1383 /* Try whole file name first. */
1384 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1385 if (lang
->filenames
!= NULL
)
1386 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1387 if ((case_sensitive
)
1388 ? streq (*name
, file
)
1389 : strcaseeq (*name
, file
))
1392 /* If not found, try suffix after last dot. */
1393 suffix
= etags_strrchr (file
, '.');
1397 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1398 if (lang
->suffixes
!= NULL
)
1399 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1400 if ((case_sensitive
)
1401 ? streq (*ext
, suffix
)
1402 : strcaseeq (*ext
, suffix
))
1409 * This routine is called on each file argument.
1412 process_file_name (file
, lang
)
1416 struct stat stat_buf
;
1420 char *compressed_name
, *uncompressed_name
;
1421 char *ext
, *real_name
;
1424 canonicalize_filename (file
);
1425 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1427 error ("skipping inclusion of %s in self.", file
);
1430 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1432 compressed_name
= NULL
;
1433 real_name
= uncompressed_name
= savestr (file
);
1437 real_name
= compressed_name
= savestr (file
);
1438 uncompressed_name
= savenstr (file
, ext
- file
);
1441 /* If the canonicalized uncompressed name
1442 has already been dealt with, skip it silently. */
1443 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1445 assert (fdp
->infname
!= NULL
);
1446 if (streq (uncompressed_name
, fdp
->infname
))
1450 if (stat (real_name
, &stat_buf
) != 0)
1452 /* Reset real_name and try with a different name. */
1454 if (compressed_name
!= NULL
) /* try with the given suffix */
1456 if (stat (uncompressed_name
, &stat_buf
) == 0)
1457 real_name
= uncompressed_name
;
1459 else /* try all possible suffixes */
1461 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1463 compressed_name
= concat (file
, ".", compr
->suffix
);
1464 if (stat (compressed_name
, &stat_buf
) != 0)
1468 char *suf
= compressed_name
+ strlen (file
);
1469 size_t suflen
= strlen (compr
->suffix
) + 1;
1470 for ( ; suf
[1]; suf
++, suflen
--)
1472 memmove (suf
, suf
+ 1, suflen
);
1473 if (stat (compressed_name
, &stat_buf
) == 0)
1475 real_name
= compressed_name
;
1479 if (real_name
!= NULL
)
1482 free (compressed_name
);
1483 compressed_name
= NULL
;
1487 real_name
= compressed_name
;
1492 if (real_name
== NULL
)
1497 } /* try with a different name */
1499 if (!S_ISREG (stat_buf
.st_mode
))
1501 error ("skipping %s: it is not a regular file.", real_name
);
1504 if (real_name
== compressed_name
)
1506 char *cmd
= concat (compr
->command
, " ", real_name
);
1507 inf
= (FILE *) popen (cmd
, "r");
1511 inf
= fopen (real_name
, "r");
1518 process_file (inf
, uncompressed_name
, lang
);
1520 if (real_name
== compressed_name
)
1521 retval
= pclose (inf
);
1523 retval
= fclose (inf
);
1528 if (compressed_name
) free (compressed_name
);
1529 if (uncompressed_name
) free (uncompressed_name
);
1536 process_file (fh
, fn
, lang
)
1541 static const fdesc emptyfdesc
;
1544 /* Create a new input file description entry. */
1545 fdp
= xnew (1, fdesc
);
1548 fdp
->infname
= savestr (fn
);
1550 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1551 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1552 if (filename_is_absolute (fn
))
1554 /* An absolute file name. Canonicalize it. */
1555 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1559 /* A file name relative to cwd. Make it relative
1560 to the directory of the tags file. */
1561 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1563 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1567 curfdp
= fdhead
; /* the current file description */
1571 /* If not Ctags, and if this is not metasource and if it contained no #line
1572 directives, we can write the tags and free all nodes pointing to
1575 && curfdp
->usecharno
/* no #line directives in this file */
1576 && !curfdp
->lang
->metasource
)
1580 /* Look for the head of the sublist relative to this file. See add_node
1581 for the structure of the node tree. */
1583 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1584 if (np
->fdp
== curfdp
)
1587 /* If we generated tags for this file, write and delete them. */
1590 /* This is the head of the last sublist, if any. The following
1591 instructions depend on this being true. */
1592 assert (np
->left
== NULL
);
1594 assert (fdhead
== curfdp
);
1595 assert (last_node
->fdp
== curfdp
);
1596 put_entries (np
); /* write tags for file curfdp->taggedfname */
1597 free_tree (np
); /* remove the written nodes */
1599 nodehead
= NULL
; /* no nodes left */
1601 prev
->left
= NULL
; /* delete the pointer to the sublist */
1607 * This routine sets up the boolean pseudo-functions which work
1608 * by setting boolean flags dependent upon the corresponding character.
1609 * Every char which is NOT in that string is not a white char. Therefore,
1610 * all of the array "_wht" is set to FALSE, and then the elements
1611 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1612 * of a char is TRUE if it is the string "white", else FALSE.
1620 for (i
= 0; i
< CHARS
; i
++)
1621 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1622 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1623 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1624 notinname('\0') = notinname('\n');
1625 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1626 begtoken('\0') = begtoken('\n');
1627 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1628 intoken('\0') = intoken('\n');
1629 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1630 endtoken('\0') = endtoken('\n');
1634 * This routine opens the specified file and calls the function
1635 * which finds the function and type definitions.
1642 language
*lang
= curfdp
->lang
;
1643 Lang_function
*parser
= NULL
;
1645 /* If user specified a language, use it. */
1646 if (lang
!= NULL
&& lang
->function
!= NULL
)
1648 parser
= lang
->function
;
1651 /* Else try to guess the language given the file name. */
1654 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1655 if (lang
!= NULL
&& lang
->function
!= NULL
)
1657 curfdp
->lang
= lang
;
1658 parser
= lang
->function
;
1662 /* Else look for sharp-bang as the first two characters. */
1664 && readline_internal (&lb
, inf
) > 0
1666 && lb
.buffer
[0] == '#'
1667 && lb
.buffer
[1] == '!')
1671 /* Set lp to point at the first char after the last slash in the
1672 line or, if no slashes, at the first nonblank. Then set cp to
1673 the first successive blank and terminate the string. */
1674 lp
= etags_strrchr (lb
.buffer
+2, '/');
1678 lp
= skip_spaces (lb
.buffer
+ 2);
1679 cp
= skip_non_spaces (lp
);
1682 if (strlen (lp
) > 0)
1684 lang
= get_language_from_interpreter (lp
);
1685 if (lang
!= NULL
&& lang
->function
!= NULL
)
1687 curfdp
->lang
= lang
;
1688 parser
= lang
->function
;
1693 /* We rewind here, even if inf may be a pipe. We fail if the
1694 length of the first line is longer than the pipe block size,
1695 which is unlikely. */
1698 /* Else try to guess the language given the case insensitive file name. */
1701 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1702 if (lang
!= NULL
&& lang
->function
!= NULL
)
1704 curfdp
->lang
= lang
;
1705 parser
= lang
->function
;
1709 /* Else try Fortran or C. */
1712 node
*old_last_node
= last_node
;
1714 curfdp
->lang
= get_language_from_langname ("fortran");
1717 if (old_last_node
== last_node
)
1718 /* No Fortran entries found. Try C. */
1720 /* We do not tag if rewind fails.
1721 Only the file name will be recorded in the tags file. */
1723 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1729 if (!no_line_directive
1730 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1731 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1732 file, or anyway we parsed a file that is automatically generated from
1733 this one. If this is the case, the bingo.c file contained #line
1734 directives that generated tags pointing to this file. Let's delete
1735 them all before parsing this file, which is the real source. */
1737 fdesc
**fdpp
= &fdhead
;
1738 while (*fdpp
!= NULL
)
1740 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1741 /* We found one of those! We must delete both the file description
1742 and all tags referring to it. */
1744 fdesc
*badfdp
= *fdpp
;
1748 "Removing references to \"%s\" obtained from \"%s\"\n",
1749 badfdp
->taggedfname
, badfdp
->infname
);
1751 /* Delete the tags referring to badfdp. */
1752 invalidate_nodes (badfdp
, &nodehead
);
1754 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1755 free_fdesc (badfdp
);
1758 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1761 assert (parser
!= NULL
);
1763 /* Generic initialisations before reading from file. */
1764 filebuf
.len
= 0; /* reset the file buffer */
1766 /* Generic initialisations before parsing file with readline. */
1767 lineno
= 0; /* reset global line number */
1768 charno
= 0; /* reset global char number */
1769 linecharno
= 0; /* reset global char number of line start */
1773 #ifdef ETAGS_REGEXPS
1774 regex_tag_multiline ();
1775 #endif /* ETAGS_REGEXPS */
1780 * Check whether an implicitly named tag should be created,
1781 * then call `pfnote'.
1782 * NAME is a string that is internally copied by this function.
1784 * TAGS format specification
1785 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1786 * The following is explained in some more detail in etc/ETAGS.EBNF.
1788 * make_tag creates tags with "implicit tag names" (unnamed tags)
1789 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
1790 * 1. NAME does not contain any of the characters in NONAM;
1791 * 2. LINESTART contains name as either a rightmost, or rightmost but
1792 * one character, substring;
1793 * 3. the character, if any, immediately before NAME in LINESTART must
1794 * be a character in NONAM;
1795 * 4. the character, if any, immediately after NAME in LINESTART must
1796 * also be a character in NONAM.
1798 * The implementation uses the notinname() macro, which recognises the
1799 * characters stored in the string `nonam'.
1800 * etags.el needs to use the same characters that are in NONAM.
1803 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1804 char *name
; /* tag name, or NULL if unnamed */
1805 int namelen
; /* tag length */
1806 bool is_func
; /* tag is a function */
1807 char *linestart
; /* start of the line where tag is */
1808 int linelen
; /* length of the line where tag is */
1809 int lno
; /* line number */
1810 long cno
; /* character number */
1814 if (!CTAGS
&& name
!= NULL
&& namelen
> 0)
1817 register char *cp
= name
;
1819 for (i
= 0; i
< namelen
; i
++)
1820 if (notinname (*cp
++))
1822 if (i
== namelen
) /* rule #1 */
1824 cp
= linestart
+ linelen
- namelen
;
1825 if (notinname (linestart
[linelen
-1]))
1826 cp
-= 1; /* rule #4 */
1827 if (cp
>= linestart
/* rule #2 */
1829 || notinname (cp
[-1])) /* rule #3 */
1830 && strneq (name
, cp
, namelen
)) /* rule #2 */
1831 named
= FALSE
; /* use implicit tag name */
1836 name
= savenstr (name
, namelen
);
1839 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
1844 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1845 char *name
; /* tag name, or NULL if unnamed */
1846 bool is_func
; /* tag is a function */
1847 char *linestart
; /* start of the line where tag is */
1848 int linelen
; /* length of the line where tag is */
1849 int lno
; /* line number */
1850 long cno
; /* character number */
1854 if (CTAGS
&& name
== NULL
)
1857 np
= xnew (1, node
);
1859 /* If ctags mode, change name "main" to M<thisfilename>. */
1860 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1862 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
1863 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
1864 fp
= etags_strrchr (np
->name
, '.');
1865 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
1871 np
->been_warned
= FALSE
;
1873 np
->is_func
= is_func
;
1875 if (np
->fdp
->usecharno
)
1876 /* Our char numbers are 0-base, because of C language tradition?
1877 ctags compatibility? old versions compatibility? I don't know.
1878 Anyway, since emacs's are 1-base we expect etags.el to take care
1879 of the difference. If we wanted to have 1-based numbers, we would
1880 uncomment the +1 below. */
1881 np
->cno
= cno
/* + 1 */ ;
1883 np
->cno
= invalidcharno
;
1884 np
->left
= np
->right
= NULL
;
1885 if (CTAGS
&& !cxref_style
)
1887 if (strlen (linestart
) < 50)
1888 np
->pat
= concat (linestart
, "$", "");
1890 np
->pat
= savenstr (linestart
, 50);
1893 np
->pat
= savenstr (linestart
, linelen
);
1895 add_node (np
, &nodehead
);
1900 * recurse on left children, iterate on right children.
1908 register node
*node_right
= np
->right
;
1909 free_tree (np
->left
);
1910 if (np
->name
!= NULL
)
1920 * delete a file description
1924 register fdesc
*fdp
;
1926 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
1927 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
1928 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
1929 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
1930 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
1936 * Adds a node to the tree of nodes. In etags mode, sort by file
1937 * name. In ctags mode, sort by tag name. Make no attempt at
1940 * add_node is the only function allowed to add nodes, so it can
1944 add_node (np
, cur_node_p
)
1945 node
*np
, **cur_node_p
;
1948 register node
*cur_node
= *cur_node_p
;
1950 if (cur_node
== NULL
)
1960 /* For each file name, tags are in a linked sublist on the right
1961 pointer. The first tags of different files are a linked list
1962 on the left pointer. last_node points to the end of the last
1964 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
1966 /* Let's use the same sublist as the last added node. */
1967 assert (last_node
->right
== NULL
);
1968 last_node
->right
= np
;
1971 else if (cur_node
->fdp
== np
->fdp
)
1973 /* Scanning the list we found the head of a sublist which is
1974 good for us. Let's scan this sublist. */
1975 add_node (np
, &cur_node
->right
);
1978 /* The head of this sublist is not good for us. Let's try the
1980 add_node (np
, &cur_node
->left
);
1981 } /* if ETAGS mode */
1986 dif
= strcmp (np
->name
, cur_node
->name
);
1989 * If this tag name matches an existing one, then
1990 * do not add the node, but maybe print a warning.
1994 if (np
->fdp
== cur_node
->fdp
)
1998 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1999 np
->fdp
->infname
, lineno
, np
->name
);
2000 fprintf (stderr
, "Second entry ignored\n");
2003 else if (!cur_node
->been_warned
&& !no_warnings
)
2007 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2008 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2009 cur_node
->been_warned
= TRUE
;
2014 /* Actually add the node */
2015 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2016 } /* if CTAGS mode */
2020 * invalidate_nodes ()
2021 * Scan the node tree and invalidate all nodes pointing to the
2022 * given file description (CTAGS case) or free them (ETAGS case).
2025 invalidate_nodes (badfdp
, npp
)
2036 if (np
->left
!= NULL
)
2037 invalidate_nodes (badfdp
, &np
->left
);
2038 if (np
->fdp
== badfdp
)
2040 if (np
->right
!= NULL
)
2041 invalidate_nodes (badfdp
, &np
->right
);
2045 assert (np
->fdp
!= NULL
);
2046 if (np
->fdp
== badfdp
)
2048 *npp
= np
->left
; /* detach the sublist from the list */
2049 np
->left
= NULL
; /* isolate it */
2050 free_tree (np
); /* free it */
2051 invalidate_nodes (badfdp
, npp
);
2054 invalidate_nodes (badfdp
, &np
->left
);
2059 static int total_size_of_entries
__P((node
*));
2060 static int number_len
__P((long));
2062 /* Length of a non-negative number's decimal representation. */
2068 while ((num
/= 10) > 0)
2074 * Return total number of characters that put_entries will output for
2075 * the nodes in the linked list at the right of the specified node.
2076 * This count is irrelevant with etags.el since emacs 19.34 at least,
2077 * but is still supplied for backward compatibility.
2080 total_size_of_entries (np
)
2083 register int total
= 0;
2085 for (; np
!= NULL
; np
= np
->right
)
2087 total
+= strlen (np
->pat
) + 1; /* pat\177 */
2088 if (np
->name
!= NULL
)
2089 total
+= strlen (np
->name
) + 1; /* name\001 */
2090 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2091 if (np
->cno
!= invalidcharno
) /* cno */
2092 total
+= number_len (np
->cno
);
2093 total
+= 1; /* newline */
2104 static fdesc
*fdp
= NULL
;
2109 /* Output subentries that precede this one */
2111 put_entries (np
->left
);
2113 /* Output this entry */
2122 fprintf (tagf
, "\f\n%s,%d\n",
2123 fdp
->taggedfname
, total_size_of_entries (np
));
2125 fputs (np
->pat
, tagf
);
2126 fputc ('\177', tagf
);
2127 if (np
->name
!= NULL
)
2129 fputs (np
->name
, tagf
);
2130 fputc ('\001', tagf
);
2132 fprintf (tagf
, "%d,", np
->lno
);
2133 if (np
->cno
!= invalidcharno
)
2134 fprintf (tagf
, "%ld", np
->cno
);
2140 if (np
->name
== NULL
)
2141 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2146 fprintf (stdout
, "%s %s %d\n",
2147 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2149 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2150 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->pat
);
2154 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2157 { /* function or #define macro with args */
2158 putc (searchar
, tagf
);
2161 for (sp
= np
->pat
; *sp
; sp
++)
2163 if (*sp
== '\\' || *sp
== searchar
)
2167 putc (searchar
, tagf
);
2170 { /* anything else; text pattern inadequate */
2171 fprintf (tagf
, "%d", np
->lno
);
2176 } /* if this node contains a valid tag */
2178 /* Output subentries that follow this one */
2179 put_entries (np
->right
);
2181 put_entries (np
->left
);
2186 #define C_EXT 0x00fff /* C extensions */
2187 #define C_PLAIN 0x00000 /* C */
2188 #define C_PLPL 0x00001 /* C++ */
2189 #define C_STAR 0x00003 /* C* */
2190 #define C_JAVA 0x00005 /* JAVA */
2191 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2192 #define YACC 0x10000 /* yacc file */
2195 * The C symbol tables.
2200 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2205 st_C_class
, st_C_template
,
2206 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
2209 static unsigned int hash
__P((const char *, unsigned int));
2210 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2211 static enum sym_type C_symtype
__P((char *, int, int));
2213 /* Feed stuff between (but not including) %[ and %] lines to:
2214 gperf -c -k 1,3 -o -p -r -t
2216 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2220 while, 0, st_C_ignore
2221 switch, 0, st_C_ignore
2222 return, 0, st_C_ignore
2223 @interface, 0, st_C_objprot
2224 @protocol, 0, st_C_objprot
2225 @implementation,0, st_C_objimpl
2226 @end, 0, st_C_objend
2227 import, C_JAVA, st_C_ignore
2228 package, C_JAVA, st_C_ignore
2229 friend, C_PLPL, st_C_ignore
2230 extends, C_JAVA, st_C_javastruct
2231 implements, C_JAVA, st_C_javastruct
2232 interface, C_JAVA, st_C_struct
2233 class, 0, st_C_class
2234 namespace, C_PLPL, st_C_struct
2235 domain, C_STAR, st_C_struct
2236 union, 0, st_C_struct
2237 struct, 0, st_C_struct
2238 extern, 0, st_C_extern
2240 typedef, 0, st_C_typedef
2241 define, 0, st_C_define
2242 operator, C_PLPL, st_C_operator
2243 template, 0, st_C_template
2244 bool, C_PLPL, st_C_typespec
2245 long, 0, st_C_typespec
2246 short, 0, st_C_typespec
2247 int, 0, st_C_typespec
2248 char, 0, st_C_typespec
2249 float, 0, st_C_typespec
2250 double, 0, st_C_typespec
2251 signed, 0, st_C_typespec
2252 unsigned, 0, st_C_typespec
2253 auto, 0, st_C_typespec
2254 void, 0, st_C_typespec
2255 static, 0, st_C_typespec
2256 const, 0, st_C_typespec
2257 volatile, 0, st_C_typespec
2258 explicit, C_PLPL, st_C_typespec
2259 mutable, C_PLPL, st_C_typespec
2260 typename, C_PLPL, st_C_typespec
2261 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2262 DEFUN, 0, st_C_gnumacro
2263 SYSCALL, 0, st_C_gnumacro
2264 ENTRY, 0, st_C_gnumacro
2265 PSEUDO, 0, st_C_gnumacro
2266 # These are defined inside C functions, so currently they are not met.
2267 # EXFUN used in glibc, DEFVAR_* in emacs.
2268 #EXFUN, 0, st_C_gnumacro
2269 #DEFVAR_, 0, st_C_gnumacro
2271 and replace lines between %< and %> with its output,
2272 then make in_word_set and C_stab_entry static. */
2274 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2275 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2276 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2278 #define TOTAL_KEYWORDS 47
2279 #define MIN_WORD_LENGTH 2
2280 #define MAX_WORD_LENGTH 15
2281 #define MIN_HASH_VALUE 18
2282 #define MAX_HASH_VALUE 138
2283 /* maximum key range = 121, duplicates = 0 */
2290 register const char *str
;
2291 register unsigned int len
;
2293 static unsigned char asso_values
[] =
2295 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2296 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2297 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2298 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2299 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2300 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2301 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2302 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2303 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2304 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2305 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2306 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2307 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2308 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2309 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2310 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2311 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2312 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2313 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2314 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2315 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2316 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2317 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2318 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2319 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2320 139, 139, 139, 139, 139, 139
2322 register int hval
= len
;
2328 hval
+= asso_values
[(unsigned char)str
[2]];
2331 hval
+= asso_values
[(unsigned char)str
[0]];
2340 static struct C_stab_entry
*
2341 in_word_set (str
, len
)
2342 register const char *str
;
2343 register unsigned int len
;
2345 static struct C_stab_entry wordlist
[] =
2347 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2348 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2349 {"if", 0, st_C_ignore
},
2350 {""}, {""}, {""}, {""},
2351 {"int", 0, st_C_typespec
},
2353 {"void", 0, st_C_typespec
},
2355 {"interface", C_JAVA
, st_C_struct
},
2357 {"SYSCALL", 0, st_C_gnumacro
},
2359 {"return", 0, st_C_ignore
},
2360 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2361 {"while", 0, st_C_ignore
},
2362 {"auto", 0, st_C_typespec
},
2363 {""}, {""}, {""}, {""}, {""}, {""},
2364 {"float", 0, st_C_typespec
},
2365 {"typedef", 0, st_C_typedef
},
2366 {"typename", C_PLPL
, st_C_typespec
},
2368 {"friend", C_PLPL
, st_C_ignore
},
2369 {"volatile", 0, st_C_typespec
},
2371 {"for", 0, st_C_ignore
},
2372 {"const", 0, st_C_typespec
},
2373 {"import", C_JAVA
, st_C_ignore
},
2375 {"define", 0, st_C_define
},
2376 {"long", 0, st_C_typespec
},
2377 {"implements", C_JAVA
, st_C_javastruct
},
2378 {"signed", 0, st_C_typespec
},
2380 {"extern", 0, st_C_extern
},
2381 {"extends", C_JAVA
, st_C_javastruct
},
2383 {"mutable", C_PLPL
, st_C_typespec
},
2384 {"template", 0, st_C_template
},
2385 {"short", 0, st_C_typespec
},
2386 {"bool", C_PLPL
, st_C_typespec
},
2387 {"char", 0, st_C_typespec
},
2388 {"class", 0, st_C_class
},
2389 {"operator", C_PLPL
, st_C_operator
},
2391 {"switch", 0, st_C_ignore
},
2393 {"ENTRY", 0, st_C_gnumacro
},
2395 {"package", C_JAVA
, st_C_ignore
},
2396 {"union", 0, st_C_struct
},
2397 {"@end", 0, st_C_objend
},
2398 {"struct", 0, st_C_struct
},
2399 {"namespace", C_PLPL
, st_C_struct
},
2401 {"domain", C_STAR
, st_C_struct
},
2402 {"@interface", 0, st_C_objprot
},
2403 {"PSEUDO", 0, st_C_gnumacro
},
2404 {"double", 0, st_C_typespec
},
2406 {"@protocol", 0, st_C_objprot
},
2408 {"static", 0, st_C_typespec
},
2410 {"DEFUN", 0, st_C_gnumacro
},
2411 {""}, {""}, {""}, {""},
2412 {"explicit", C_PLPL
, st_C_typespec
},
2413 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2414 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2416 {"enum", 0, st_C_enum
},
2418 {"unsigned", 0, st_C_typespec
},
2419 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2420 {"@implementation",0, st_C_objimpl
}
2423 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2425 register int key
= hash (str
, len
);
2427 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2429 register const char *s
= wordlist
[key
].name
;
2431 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
2432 return &wordlist
[key
];
2439 static enum sym_type
2440 C_symtype (str
, len
, c_ext
)
2445 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2447 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2454 * C functions and variables are recognized using a simple
2455 * finite automaton. fvdef is its state variable.
2459 fvnone
, /* nothing seen */
2460 fdefunkey
, /* Emacs DEFUN keyword seen */
2461 fdefunname
, /* Emacs DEFUN name seen */
2462 foperator
, /* func: operator keyword seen (cplpl) */
2463 fvnameseen
, /* function or variable name seen */
2464 fstartlist
, /* func: just after open parenthesis */
2465 finlist
, /* func: in parameter list */
2466 flistseen
, /* func: after parameter list */
2467 fignore
, /* func: before open brace */
2468 vignore
/* var-like: ignore until ';' */
2471 static bool fvextern
; /* func or var: extern keyword seen; */
2474 * typedefs are recognized using a simple finite automaton.
2475 * typdef is its state variable.
2479 tnone
, /* nothing seen */
2480 tkeyseen
, /* typedef keyword seen */
2481 ttypeseen
, /* defined type seen */
2482 tinbody
, /* inside typedef body */
2483 tend
, /* just before typedef tag */
2484 tignore
/* junk after typedef tag */
2488 * struct-like structures (enum, struct and union) are recognized
2489 * using another simple finite automaton. `structdef' is its state
2494 snone
, /* nothing seen yet,
2495 or in struct body if cblev > 0 */
2496 skeyseen
, /* struct-like keyword seen */
2497 stagseen
, /* struct-like tag seen */
2498 sintemplate
, /* inside template (ignore) */
2499 scolonseen
/* colon seen after struct-like tag */
2503 * When objdef is different from onone, objtag is the name of the class.
2505 static char *objtag
= "<uninited>";
2508 * Yet another little state machine to deal with preprocessor lines.
2512 dnone
, /* nothing seen */
2513 dsharpseen
, /* '#' seen as first char on line */
2514 ddefineseen
, /* '#' and 'define' seen */
2515 dignorerest
/* ignore rest of line */
2519 * State machine for Objective C protocols and implementations.
2520 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2524 onone
, /* nothing seen */
2525 oprotocol
, /* @interface or @protocol seen */
2526 oimplementation
, /* @implementations seen */
2527 otagseen
, /* class name seen */
2528 oparenseen
, /* parenthesis before category seen */
2529 ocatseen
, /* category name seen */
2530 oinbody
, /* in @implementation body */
2531 omethodsign
, /* in @implementation body, after +/- */
2532 omethodtag
, /* after method name */
2533 omethodcolon
, /* after method colon */
2534 omethodparm
, /* after method parameter */
2535 oignore
/* wait for @end */
2540 * Use this structure to keep info about the token read, and how it
2541 * should be tagged. Used by the make_C_tag function to build a tag.
2552 } token
; /* latest token read */
2553 static linebuffer token_name
; /* its name */
2556 * Variables and functions for dealing with nested structures.
2557 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2559 static void pushclass_above
__P((int, char *, int));
2560 static void popclass_above
__P((int));
2561 static void write_classname
__P((linebuffer
*, char *qualifier
));
2564 char **cname
; /* nested class names */
2565 int *cblev
; /* nested class curly brace level */
2566 int nl
; /* class nesting level (elements used) */
2567 int size
; /* length of the array */
2568 } cstack
; /* stack for nested declaration tags */
2569 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2570 #define nestlev (cstack.nl)
2571 /* After struct keyword or in struct body, not inside an nested function. */
2572 #define instruct (structdef == snone && nestlev > 0 \
2573 && cblev == cstack.cblev[nestlev-1] + 1)
2576 pushclass_above (cblev
, str
, len
)
2583 popclass_above (cblev
);
2585 if (nl
>= cstack
.size
)
2587 int size
= cstack
.size
*= 2;
2588 xrnew (cstack
.cname
, size
, char *);
2589 xrnew (cstack
.cblev
, size
, int);
2591 assert (nl
== 0 || cstack
.cblev
[nl
-1] < cblev
);
2592 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2593 cstack
.cblev
[nl
] = cblev
;
2598 popclass_above (cblev
)
2603 for (nl
= cstack
.nl
- 1;
2604 nl
>= 0 && cstack
.cblev
[nl
] >= cblev
;
2607 if (cstack
.cname
[nl
] != NULL
)
2608 free (cstack
.cname
[nl
]);
2614 write_classname (cn
, qualifier
)
2619 int qlen
= strlen (qualifier
);
2621 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2625 cn
->buffer
[0] = '\0';
2629 len
= strlen (cstack
.cname
[0]);
2630 linebuffer_setlen (cn
, len
);
2631 strcpy (cn
->buffer
, cstack
.cname
[0]);
2633 for (i
= 1; i
< cstack
.nl
; i
++)
2638 s
= cstack
.cname
[i
];
2643 linebuffer_setlen (cn
, len
);
2644 strncat (cn
->buffer
, qualifier
, qlen
);
2645 strncat (cn
->buffer
, s
, slen
);
2650 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2651 static void make_C_tag
__P((bool));
2655 * checks to see if the current token is at the start of a
2656 * function or variable, or corresponds to a typedef, or
2657 * is a struct/union/enum tag, or #define, or an enum constant.
2659 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2660 * with args. C_EXTP points to which language we are looking at.
2671 consider_token (str
, len
, c
, c_extp
, cblev
, parlev
, is_func_or_var
)
2672 register char *str
; /* IN: token pointer */
2673 register int len
; /* IN: token length */
2674 register int c
; /* IN: first char after the token */
2675 int *c_extp
; /* IN, OUT: C extensions mask */
2676 int cblev
; /* IN: curly brace level */
2677 int parlev
; /* IN: parenthesis level */
2678 bool *is_func_or_var
; /* OUT: function or variable found */
2680 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2681 structtype is the type of the preceding struct-like keyword, and
2682 structcblev is the curly brace level where it has been seen. */
2683 static enum sym_type structtype
;
2684 static int structcblev
;
2685 static enum sym_type toktype
;
2688 toktype
= C_symtype (str
, len
, *c_extp
);
2691 * Advance the definedef state machine.
2696 /* We're not on a preprocessor line. */
2697 if (toktype
== st_C_gnumacro
)
2704 if (toktype
== st_C_define
)
2706 definedef
= ddefineseen
;
2710 definedef
= dignorerest
;
2715 * Make a tag for any macro, unless it is a constant
2716 * and constantypedefs is FALSE.
2718 definedef
= dignorerest
;
2719 *is_func_or_var
= (c
== '(');
2720 if (!*is_func_or_var
&& !constantypedefs
)
2727 error ("internal error: definedef value.", (char *)NULL
);
2736 if (toktype
== st_C_typedef
)
2758 if (structdef
== snone
&& fvdef
== fvnone
)
2777 * This structdef business is NOT invoked when we are ctags and the
2778 * file is plain C. This is because a struct tag may have the same
2779 * name as another tag, and this loses with ctags.
2783 case st_C_javastruct
:
2784 if (structdef
== stagseen
)
2785 structdef
= scolonseen
;
2790 && (*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2791 && definedef
== dnone
&& structdef
== snone
2792 && typdef
== tnone
&& fvdef
== fvnone
)
2793 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2794 if (toktype
== st_C_template
)
2801 && (typdef
== tkeyseen
2802 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2804 structdef
= skeyseen
;
2805 structtype
= toktype
;
2806 structcblev
= cblev
;
2811 if (structdef
== skeyseen
)
2813 structdef
= stagseen
;
2817 if (typdef
!= tnone
)
2820 /* Detect Objective C constructs. */
2830 objdef
= oimplementation
;
2834 case oimplementation
:
2835 /* Save the class tag for functions or variables defined inside. */
2836 objtag
= savenstr (str
, len
);
2840 /* Save the class tag for categories. */
2841 objtag
= savenstr (str
, len
);
2843 *is_func_or_var
= TRUE
;
2847 *is_func_or_var
= TRUE
;
2854 objdef
= omethodtag
;
2855 linebuffer_setlen (&token_name
, len
);
2856 strncpy (token_name
.buffer
, str
, len
);
2857 token_name
.buffer
[len
] = '\0';
2863 objdef
= omethodparm
;
2868 objdef
= omethodtag
;
2869 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
2870 strncat (token_name
.buffer
, str
, len
);
2875 if (toktype
== st_C_objend
)
2877 /* Memory leakage here: the string pointed by objtag is
2878 never released, because many tests would be needed to
2879 avoid breaking on incorrect input code. The amount of
2880 memory leaked here is the sum of the lengths of the
2888 /* A function, variable or enum constant? */
2895 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!= vignore
)
2896 fvdef
= fvnone
; /* should be useless */
2904 *is_func_or_var
= TRUE
;
2908 && structdef
== snone
2909 && structtype
== st_C_enum
&& cblev
> structcblev
)
2910 return TRUE
; /* enum constant */
2916 fvdef
= fdefunname
; /* GNU macro */
2917 *is_func_or_var
= TRUE
;
2920 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
2921 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
2926 if ((*c_extp
& C_PLPL
) && strneq (str
+len
-10, "::operator", 10))
2929 *is_func_or_var
= TRUE
;
2932 if (cblev
> 0 && !instruct
)
2934 fvdef
= fvnameseen
; /* function or variable */
2935 *is_func_or_var
= TRUE
;
2946 * C_entries often keeps pointers to tokens or lines which are older than
2947 * the line currently read. By keeping two line buffers, and switching
2948 * them at end of line, it is possible to use those pointers.
2956 #define current_lb_is_new (newndx == curndx)
2957 #define switch_line_buffers() (curndx = 1 - curndx)
2959 #define curlb (lbs[curndx].lb)
2960 #define newlb (lbs[newndx].lb)
2961 #define curlinepos (lbs[curndx].linepos)
2962 #define newlinepos (lbs[newndx].linepos)
2964 #define CNL_SAVE_DEFINEDEF() \
2966 curlinepos = charno; \
2967 readline (&curlb, inf); \
2968 lp = curlb.buffer; \
2975 CNL_SAVE_DEFINEDEF(); \
2976 if (savetoken.valid) \
2978 token = savetoken; \
2979 savetoken.valid = FALSE; \
2981 definedef = dnone; \
2989 /* This function should never be called when token.valid is FALSE, but
2990 we must protect against invalid input or internal errors. */
2991 if (!DEBUG
&& !token
.valid
)
2994 if (!token
.valid
) /* this case is optimised away if !DEBUG */
2995 make_tag (concat (token_name
.buffer
, "##invalid token##", ""),
2996 token_name
.len
+ 17, isfun
, token
.line
,
2997 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
2999 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3000 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3002 token
.valid
= FALSE
;
3008 * This routine finds functions, variables, typedefs,
3009 * #define's, enum constants and struct/union/enum definitions in
3010 * C syntax and adds them to the list.
3013 C_entries (c_ext
, inf
)
3014 int c_ext
; /* extension of C */
3015 FILE *inf
; /* input file */
3017 register char c
; /* latest char read; '\0' for end of line */
3018 register char *lp
; /* pointer one beyond the character `c' */
3019 int curndx
, newndx
; /* indices for current and new lb */
3020 register int tokoff
; /* offset in line of start of current token */
3021 register int toklen
; /* length of current token */
3022 char *qualifier
; /* string used to qualify names */
3023 int qlen
; /* length of qualifier */
3024 int cblev
; /* current curly brace level */
3025 int parlev
; /* current parenthesis level */
3026 int typdefcblev
; /* cblev where a typedef struct body begun */
3027 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3029 bool yacc_rules
; /* in the rules part of a yacc file */
3030 struct tok savetoken
; /* token saved during preprocessor handling */
3033 initbuffer (&token_name
);
3034 initbuffer (&lbs
[0].lb
);
3035 initbuffer (&lbs
[1].lb
);
3036 if (cstack
.size
== 0)
3038 cstack
.size
= (DEBUG
) ? 1 : 4;
3040 cstack
.cname
= xnew (cstack
.size
, char *);
3041 cstack
.cblev
= xnew (cstack
.size
, int);
3044 tokoff
= toklen
= typdefcblev
= 0; /* keep compiler quiet */
3045 curndx
= newndx
= 0;
3049 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3050 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3052 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3053 token
.valid
= savetoken
.valid
= FALSE
;
3056 cplpl
= (c_ext
& C_PLPL
) == C_PLPL
;
3057 cjava
= (c_ext
& C_JAVA
) == C_JAVA
;
3059 { qualifier
= "."; qlen
= 1; }
3061 { qualifier
= "::"; qlen
= 2; }
3069 /* If we're at the end of the line, the next character is a
3070 '\0'; don't skip it, because it's the thing that tells us
3071 to read the next line. */
3092 /* Newlines inside comments do not end macro definitions in
3094 CNL_SAVE_DEFINEDEF ();
3107 /* Newlines inside strings do not end macro definitions
3108 in traditional cpp, even though compilers don't
3109 usually accept them. */
3110 CNL_SAVE_DEFINEDEF ();
3120 /* Hmmm, something went wrong. */
3149 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3162 else if (/* cplpl && */ *lp
== '/')
3170 if ((c_ext
& YACC
) && *lp
== '%')
3172 /* Entering or exiting rules section in yacc file. */
3174 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3175 typdef
= tnone
; structdef
= snone
;
3176 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3178 yacc_rules
= !yacc_rules
;
3184 if (definedef
== dnone
)
3187 bool cpptoken
= TRUE
;
3189 /* Look back on this line. If all blanks, or nonblanks
3190 followed by an end of comment, this is a preprocessor
3192 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3195 if (*cp
== '*' && *(cp
+1) == '/')
3204 definedef
= dsharpseen
;
3205 } /* if (definedef == dnone) */
3211 /* Consider token only if some involved conditions are satisfied. */
3212 if (typdef
!= tignore
3213 && definedef
!= dignorerest
3215 && structdef
!= sintemplate
3216 && (definedef
!= dnone
3217 || structdef
!= scolonseen
))
3223 if (c
== ':' && cplpl
&& *lp
== ':' && begtoken (lp
[1]))
3226 * This handles :: in the middle, but not at the
3227 * beginning of an identifier. Also, space-separated
3228 * :: is not recognised.
3233 goto still_in_token
;
3237 bool funorvar
= FALSE
;
3240 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3241 &c_ext
, cblev
, parlev
, &funorvar
))
3243 if (fvdef
== foperator
)
3246 lp
= skip_spaces (lp
-1);
3250 && !iswhite (*lp
) && *lp
!= '(')
3253 toklen
+= lp
- oldlp
;
3255 token
.named
= FALSE
;
3256 if ((c_ext
& C_EXT
) /* not pure C */
3257 && nestlev
> 0 && definedef
== dnone
)
3258 /* in struct body */
3260 write_classname (&token_name
, qualifier
);
3261 linebuffer_setlen (&token_name
,
3262 token_name
.len
+qlen
+toklen
);
3263 strcat (token_name
.buffer
, qualifier
);
3264 strncat (token_name
.buffer
,
3265 newlb
.buffer
+ tokoff
, toklen
);
3268 else if (objdef
== ocatseen
)
3269 /* Objective C category */
3271 int len
= strlen (objtag
) + 2 + toklen
;
3272 linebuffer_setlen (&token_name
, len
);
3273 strcpy (token_name
.buffer
, objtag
);
3274 strcat (token_name
.buffer
, "(");
3275 strncat (token_name
.buffer
,
3276 newlb
.buffer
+ tokoff
, toklen
);
3277 strcat (token_name
.buffer
, ")");
3280 else if (objdef
== omethodtag
3281 || objdef
== omethodparm
)
3282 /* Objective C method */
3286 else if (fvdef
== fdefunname
)
3287 /* GNU DEFUN and similar macros */
3289 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3293 /* Rewrite the tag so that emacs lisp DEFUNs
3294 can be found by their elisp name */
3301 linebuffer_setlen (&token_name
, len
);
3302 strncpy (token_name
.buffer
,
3303 newlb
.buffer
+ off
, len
);
3304 token_name
.buffer
[len
] = '\0';
3307 if (token_name
.buffer
[len
] == '_')
3308 token_name
.buffer
[len
] = '-';
3309 token
.named
= defun
;
3313 linebuffer_setlen (&token_name
, toklen
);
3314 strncpy (token_name
.buffer
,
3315 newlb
.buffer
+ tokoff
, toklen
);
3316 token_name
.buffer
[toklen
] = '\0';
3317 /* Name macros and members. */
3318 token
.named
= (structdef
== stagseen
3319 || typdef
== ttypeseen
3322 && definedef
== dignorerest
)
3324 && definedef
== dnone
3325 && structdef
== snone
3328 token
.lineno
= lineno
;
3329 token
.offset
= tokoff
;
3330 token
.length
= toklen
;
3331 token
.line
= newlb
.buffer
;
3332 token
.linepos
= newlinepos
;
3335 if (definedef
== dnone
3336 && (fvdef
== fvnameseen
3337 || fvdef
== foperator
3338 || structdef
== stagseen
3340 || typdef
== ttypeseen
3341 || objdef
!= onone
))
3343 if (current_lb_is_new
)
3344 switch_line_buffers ();
3346 else if (definedef
!= dnone
3347 || fvdef
== fdefunname
3349 make_C_tag (funorvar
);
3353 } /* if (endtoken (c)) */
3354 else if (intoken (c
))
3360 } /* if (midtoken) */
3361 else if (begtoken (c
))
3372 make_C_tag (TRUE
); /* a function */
3379 if (structdef
== stagseen
&& !cjava
)
3381 popclass_above (cblev
);
3389 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3391 tokoff
= lp
- 1 - newlb
.buffer
;
3396 } /* if (begtoken) */
3397 } /* if must look at token */
3400 /* Detect end of line, colon, comma, semicolon and various braces
3401 after having handled a token.*/
3405 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3407 make_C_tag (FALSE
); /* a yacc function */
3410 if (definedef
!= dnone
)
3416 make_C_tag (TRUE
); /* an Objective C class */
3420 objdef
= omethodcolon
;
3421 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3422 strcat (token_name
.buffer
, ":");
3425 if (structdef
== stagseen
)
3426 structdef
= scolonseen
;
3429 if (definedef
!= dnone
)
3435 make_C_tag (FALSE
); /* a typedef */
3445 if (typdef
== tignore
)
3449 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3450 || (members
&& instruct
))
3451 make_C_tag (FALSE
); /* a variable */
3454 token
.valid
= FALSE
;
3457 if ((declarations
&& typdef
== tnone
&& !instruct
)
3458 || (members
&& typdef
!= tignore
&& instruct
))
3459 make_C_tag (TRUE
); /* a function declaration */
3465 && structdef
== stagseen
&& (c_ext
& C_PLPL
))
3466 make_C_tag (FALSE
); /* forward declaration */
3468 /* The following instruction invalidates the token.
3469 Probably the token should be invalidated in all other
3470 cases where some state machine is reset prematurely. */
3471 token
.valid
= FALSE
;
3472 } /* switch (fvdef) */
3478 if (structdef
== stagseen
)
3482 if (definedef
!= dnone
)
3488 make_C_tag (TRUE
); /* an Objective C method */
3504 case fvnameseen
: /* a variable */
3505 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3506 || (members
&& instruct
))
3509 case flistseen
: /* a function */
3510 if ((declarations
&& typdef
== tnone
&& !instruct
)
3511 || (members
&& typdef
!= tignore
&& instruct
))
3513 make_C_tag (TRUE
); /* a function declaration */
3516 else if (!declarations
)
3518 token
.valid
= FALSE
;
3523 if (structdef
== stagseen
)
3527 if (definedef
!= dnone
)
3529 if (structdef
== stagseen
)
3536 make_C_tag (FALSE
); /* a typedef */
3548 if ((members
&& cblev
== 1)
3549 || (globals
&& cblev
== 0
3550 && (!fvextern
|| declarations
)))
3551 make_C_tag (FALSE
); /* a variable */
3560 if (definedef
!= dnone
)
3562 if (objdef
== otagseen
&& parlev
== 0)
3563 objdef
= oparenseen
;
3567 if (typdef
== ttypeseen
3571 /* This handles constructs like:
3572 typedef void OperatorFun (int fun); */
3589 if (definedef
!= dnone
)
3591 if (objdef
== ocatseen
&& parlev
== 1)
3593 make_C_tag (TRUE
); /* an Objective C category */
3607 || typdef
== ttypeseen
))
3610 make_C_tag (FALSE
); /* a typedef */
3613 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3617 if (definedef
!= dnone
)
3619 if (typdef
== ttypeseen
)
3621 /* Whenever typdef is set to tinbody (currently only
3622 here), typdefcblev should be set to cblev. */
3624 typdefcblev
= cblev
;
3629 make_C_tag (TRUE
); /* a function */
3638 make_C_tag (TRUE
); /* an Objective C class */
3643 make_C_tag (TRUE
); /* an Objective C method */
3647 /* Neutralize `extern "C" {' grot. */
3648 if (cblev
== 0 && structdef
== snone
&& nestlev
== 0
3656 case skeyseen
: /* unnamed struct */
3657 pushclass_above (cblev
, NULL
, 0);
3660 case stagseen
: /* named struct or enum */
3661 case scolonseen
: /* a class */
3662 pushclass_above (cblev
, token
.line
+token
.offset
, token
.length
);
3664 make_C_tag (FALSE
); /* a struct or enum */
3670 if (definedef
!= dnone
)
3672 if (fvdef
== fstartlist
)
3673 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3676 if (definedef
!= dnone
)
3678 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
3680 cblev
= 0; /* reset curly brace level if first column */
3681 parlev
= 0; /* also reset paren level, just in case... */
3685 popclass_above (cblev
);
3687 /* Only if typdef == tinbody is typdefcblev significant. */
3688 if (typdef
== tinbody
&& cblev
<= typdefcblev
)
3690 assert (cblev
== typdefcblev
);
3695 if (definedef
!= dnone
)
3705 if ((members
&& cblev
== 1)
3706 || (globals
&& cblev
== 0 && (!fvextern
|| declarations
)))
3707 make_C_tag (FALSE
); /* a variable */
3714 if (cplpl
&& structdef
== stagseen
)
3716 structdef
= sintemplate
;
3721 if (structdef
== sintemplate
)
3723 structdef
= stagseen
;
3729 if (objdef
== oinbody
&& cblev
== 0)
3731 objdef
= omethodsign
;
3736 case '#': case '~': case '&': case '%': case '/': case '|':
3737 case '^': case '!': case '.': case '?': case ']':
3738 if (definedef
!= dnone
)
3740 /* These surely cannot follow a function tag in C. */
3753 if (objdef
== otagseen
)
3755 make_C_tag (TRUE
); /* an Objective C class */
3758 /* If a macro spans multiple lines don't reset its state. */
3760 CNL_SAVE_DEFINEDEF ();
3766 } /* while not eof */
3768 free (token_name
.buffer
);
3769 free (lbs
[0].lb
.buffer
);
3770 free (lbs
[1].lb
.buffer
);
3774 * Process either a C++ file or a C file depending on the setting
3778 default_C_entries (inf
)
3781 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
3784 /* Always do plain C. */
3786 plain_C_entries (inf
)
3792 /* Always do C++. */
3794 Cplusplus_entries (inf
)
3797 C_entries (C_PLPL
, inf
);
3800 /* Always do Java. */
3805 C_entries (C_JAVA
, inf
);
3813 C_entries (C_STAR
, inf
);
3816 /* Always do Yacc. */
3821 C_entries (YACC
, inf
);
3825 /* Useful macros. */
3826 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3827 for (; /* loop initialization */ \
3828 !feof (file_pointer) /* loop test */ \
3829 && /* instructions at start of loop */ \
3830 (readline (&line_buffer, file_pointer), \
3831 char_pointer = line_buffer.buffer, \
3834 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3835 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3836 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3837 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3840 * Read a file, but do no processing. This is used to do regexp
3841 * matching on files that have no language defined.
3844 just_read_file (inf
)
3847 register char *dummy
;
3849 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
3854 /* Fortran parsing */
3856 static void F_takeprec
__P((void));
3857 static void F_getit
__P((FILE *));
3862 dbp
= skip_spaces (dbp
);
3866 dbp
= skip_spaces (dbp
);
3867 if (strneq (dbp
, "(*)", 3))
3872 if (!ISDIGIT (*dbp
))
3874 --dbp
; /* force failure */
3879 while (ISDIGIT (*dbp
));
3888 dbp
= skip_spaces (dbp
);
3891 readline (&lb
, inf
);
3896 dbp
= skip_spaces (dbp
);
3898 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
3900 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
3902 make_tag (dbp
, cp
-dbp
, TRUE
,
3903 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3908 Fortran_functions (inf
)
3911 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
3914 dbp
++; /* Ratfor escape to fortran */
3915 dbp
= skip_spaces (dbp
);
3918 switch (lowcase (*dbp
))
3921 if (nocase_tail ("integer"))
3925 if (nocase_tail ("real"))
3929 if (nocase_tail ("logical"))
3933 if (nocase_tail ("complex") || nocase_tail ("character"))
3937 if (nocase_tail ("double"))
3939 dbp
= skip_spaces (dbp
);
3942 if (nocase_tail ("precision"))
3948 dbp
= skip_spaces (dbp
);
3951 switch (lowcase (*dbp
))
3954 if (nocase_tail ("function"))
3958 if (nocase_tail ("subroutine"))
3962 if (nocase_tail ("entry"))
3966 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
3968 dbp
= skip_spaces (dbp
);
3969 if (*dbp
== '\0') /* assume un-named */
3970 make_tag ("blockdata", 9, TRUE
,
3971 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
3973 F_getit (inf
); /* look for name */
3984 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
3987 static void Ada_getit
__P((FILE *, char *));
3989 /* Once we are positioned after an "interesting" keyword, let's get
3990 the real tag value necessary. */
3992 Ada_getit (inf
, name_qualifier
)
3994 char *name_qualifier
;
4002 dbp
= skip_spaces (dbp
);
4004 || (dbp
[0] == '-' && dbp
[1] == '-'))
4006 readline (&lb
, inf
);
4009 switch (lowcase(*dbp
))
4012 if (nocase_tail ("body"))
4014 /* Skipping body of procedure body or package body or ....
4015 resetting qualifier to body instead of spec. */
4016 name_qualifier
= "/b";
4021 /* Skipping type of task type or protected type ... */
4022 if (nocase_tail ("type"))
4029 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4034 dbp
= skip_spaces (dbp
);
4037 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4045 name
= concat (dbp
, name_qualifier
, "");
4047 make_tag (name
, strlen (name
), TRUE
,
4048 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4060 bool inquote
= FALSE
;
4062 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4064 while (*dbp
!= '\0')
4066 /* Skip a string i.e. "abcd". */
4067 if (inquote
|| (*dbp
== '"'))
4069 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4074 continue; /* advance char */
4079 break; /* advance line */
4083 /* Skip comments. */
4084 if (dbp
[0] == '-' && dbp
[1] == '-')
4085 break; /* advance line */
4087 /* Skip character enclosed in single quote i.e. 'a'
4088 and skip single quote starting an attribute i.e. 'Image. */
4097 /* Search for beginning of a token. */
4098 if (!begtoken (*dbp
))
4101 continue; /* advance char */
4104 /* We are at the beginning of a token. */
4105 switch (lowcase(*dbp
))
4108 if (!packages_only
&& nocase_tail ("function"))
4109 Ada_getit (inf
, "/f");
4111 break; /* from switch */
4112 continue; /* advance char */
4114 if (!packages_only
&& nocase_tail ("procedure"))
4115 Ada_getit (inf
, "/p");
4116 else if (nocase_tail ("package"))
4117 Ada_getit (inf
, "/s");
4118 else if (nocase_tail ("protected")) /* protected type */
4119 Ada_getit (inf
, "/t");
4121 break; /* from switch */
4122 continue; /* advance char */
4124 if (!packages_only
&& nocase_tail ("task"))
4125 Ada_getit (inf
, "/k");
4126 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4128 Ada_getit (inf
, "/t");
4129 while (*dbp
!= '\0')
4133 break; /* from switch */
4134 continue; /* advance char */
4137 /* Look for the end of the token. */
4138 while (!endtoken (*dbp
))
4141 } /* advance char */
4142 } /* advance line */
4147 * Unix and microcontroller assembly tag handling
4148 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4149 * Idea by Bob Weiner, Motorola Inc. (1994)
4157 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4159 /* If first char is alphabetic or one of [_.$], test for colon
4160 following identifier. */
4161 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4163 /* Read past label. */
4165 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4167 if (*cp
== ':' || iswhite (*cp
))
4168 /* Found end of label, so copy it and add it to the table. */
4169 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4170 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4178 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4179 * Perl variable names: /^(my|local).../
4180 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4181 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4182 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4185 Perl_functions (inf
)
4188 char *package
= savestr ("main"); /* current package name */
4191 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4195 if (LOOKING_AT (cp
, "package"))
4198 get_tag (cp
, &package
);
4200 else if (LOOKING_AT (cp
, "sub"))
4205 while (!notinname (*cp
))
4208 continue; /* nothing found */
4209 if ((pos
= etags_strchr (sp
, ':')) != NULL
4210 && pos
< cp
&& pos
[1] == ':')
4211 /* The name is already qualified. */
4212 make_tag (sp
, cp
- sp
, TRUE
,
4213 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4217 char savechar
, *name
;
4221 name
= concat (package
, "::", sp
);
4223 make_tag (name
, strlen(name
), TRUE
,
4224 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4228 else if (globals
) /* only if we are tagging global vars */
4230 /* Skip a qualifier, if any. */
4231 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4232 /* After "my" or "local", but before any following paren or space. */
4233 char *varstart
= cp
;
4235 if (qual
/* should this be removed? If yes, how? */
4236 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4241 while (ISALNUM (*cp
) || *cp
== '_');
4245 /* Should be examining a variable list at this point;
4246 could insist on seeing an open parenthesis. */
4247 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4253 make_tag (varstart
, cp
- varstart
, FALSE
,
4254 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4262 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4263 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4264 * More ideas by seb bacon <seb@jamkit.com> (2002)
4267 Python_functions (inf
)
4272 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4274 cp
= skip_spaces (cp
);
4275 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4278 while (!notinname (*cp
) && *cp
!= ':')
4280 make_tag (name
, cp
- name
, TRUE
,
4281 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4290 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4291 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4292 * - /^[ \t]*define\(\"[^\"]+/
4293 * Only with --members:
4294 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4295 * Idea by Diez B. Roggisch (2001)
4301 register char *cp
, *name
;
4302 bool search_identifier
= FALSE
;
4304 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4306 cp
= skip_spaces (cp
);
4308 if (search_identifier
4311 while (!notinname (*cp
))
4313 make_tag (name
, cp
- name
, TRUE
,
4314 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4315 search_identifier
= FALSE
;
4317 else if (LOOKING_AT (cp
, "function"))
4320 cp
= skip_spaces (cp
+1);
4324 while (!notinname (*cp
))
4326 make_tag (name
, cp
- name
, TRUE
,
4327 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4330 search_identifier
= TRUE
;
4332 else if (LOOKING_AT (cp
, "class"))
4337 while (*cp
!= '\0' && !iswhite (*cp
))
4339 make_tag (name
, cp
- name
, FALSE
,
4340 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4343 search_identifier
= TRUE
;
4345 else if (strneq (cp
, "define", 6)
4346 && (cp
= skip_spaces (cp
+6))
4348 && (*cp
== '"' || *cp
== '\''))
4352 while (*cp
!= quote
&& *cp
!= '\0')
4354 make_tag (name
, cp
- name
, FALSE
,
4355 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4358 && LOOKING_AT (cp
, "var")
4362 while (!notinname(*cp
))
4364 make_tag (name
, cp
- name
, FALSE
,
4365 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4372 * Cobol tag functions
4373 * We could look for anything that could be a paragraph name.
4374 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4375 * Idea by Corny de Souza (1993)
4378 Cobol_paragraphs (inf
)
4381 register char *bp
, *ep
;
4383 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4389 /* If eoln, compiler option or comment ignore whole line. */
4390 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4393 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4396 make_tag (bp
, ep
- bp
, TRUE
,
4397 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4404 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4407 Makefile_targets (inf
)
4412 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4414 if (*bp
== '\t' || *bp
== '#')
4416 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4418 if (*bp
== ':' || (globals
&& *bp
== '='))
4419 make_tag (lb
.buffer
, bp
- lb
.buffer
, TRUE
,
4420 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4427 * Original code by Mosur K. Mohan (1989)
4429 * Locates tags for procedures & functions. Doesn't do any type- or
4430 * var-definitions. It does look for the keyword "extern" or
4431 * "forward" immediately following the procedure statement; if found,
4432 * the tag is skipped.
4435 Pascal_functions (inf
)
4438 linebuffer tline
; /* mostly copied from C_entries */
4440 int save_lineno
, namelen
, taglen
;
4443 bool /* each of these flags is TRUE iff: */
4444 incomment
, /* point is inside a comment */
4445 inquote
, /* point is inside '..' string */
4446 get_tagname
, /* point is after PROCEDURE/FUNCTION
4447 keyword, so next item = potential tag */
4448 found_tag
, /* point is after a potential tag */
4449 inparms
, /* point is within parameter-list */
4450 verify_tag
; /* point has passed the parm-list, so the
4451 next token will determine whether this
4452 is a FORWARD/EXTERN to be ignored, or
4453 whether it is a real tag */
4455 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4456 name
= NULL
; /* keep compiler quiet */
4459 initbuffer (&tline
);
4461 incomment
= inquote
= FALSE
;
4462 found_tag
= FALSE
; /* have a proc name; check if extern */
4463 get_tagname
= FALSE
; /* found "procedure" keyword */
4464 inparms
= FALSE
; /* found '(' after "proc" */
4465 verify_tag
= FALSE
; /* check if "extern" is ahead */
4468 while (!feof (inf
)) /* long main loop to get next char */
4471 if (c
== '\0') /* if end of line */
4473 readline (&lb
, inf
);
4477 if (!((found_tag
&& verify_tag
)
4479 c
= *dbp
++; /* only if don't need *dbp pointing
4480 to the beginning of the name of
4481 the procedure or function */
4485 if (c
== '}') /* within { } comments */
4487 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4504 inquote
= TRUE
; /* found first quote */
4506 case '{': /* found open { comment */
4510 if (*dbp
== '*') /* found open (* comment */
4515 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4518 case ')': /* end of parms list */
4523 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4530 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4532 /* Check if this is an "extern" declaration. */
4535 if (lowcase (*dbp
== 'e'))
4537 if (nocase_tail ("extern")) /* superfluous, really! */
4543 else if (lowcase (*dbp
) == 'f')
4545 if (nocase_tail ("forward")) /* check for forward reference */
4551 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4555 make_tag (name
, namelen
, TRUE
,
4556 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4560 if (get_tagname
) /* grab name of proc or fn */
4567 /* Find block name. */
4568 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4571 /* Save all values for later tagging. */
4572 linebuffer_setlen (&tline
, lb
.len
);
4573 strcpy (tline
.buffer
, lb
.buffer
);
4574 save_lineno
= lineno
;
4575 save_lcno
= linecharno
;
4576 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4578 taglen
= cp
- lb
.buffer
+ 1;
4580 dbp
= cp
; /* set dbp to e-o-token */
4581 get_tagname
= FALSE
;
4585 /* And proceed to check for "extern". */
4587 else if (!incomment
&& !inquote
&& !found_tag
)
4589 /* Check for proc/fn keywords. */
4590 switch (lowcase (c
))
4593 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4597 if (nocase_tail ("unction"))
4602 } /* while not eof */
4604 free (tline
.buffer
);
4609 * Lisp tag functions
4610 * look for (def or (DEF, quote or QUOTE
4613 static void L_getit
__P((void));
4618 if (*dbp
== '\'') /* Skip prefix quote */
4620 else if (*dbp
== '(')
4623 /* Try to skip "(quote " */
4624 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4625 /* Ok, then skip "(" before name in (defstruct (foo)) */
4626 dbp
= skip_spaces (dbp
);
4628 get_tag (dbp
, NULL
);
4632 Lisp_functions (inf
)
4635 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4640 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4642 dbp
= skip_non_spaces (dbp
);
4643 dbp
= skip_spaces (dbp
);
4648 /* Check for (foo::defmumble name-defined ... */
4651 while (!notinname (*dbp
) && *dbp
!= ':');
4656 while (*dbp
== ':');
4658 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4660 dbp
= skip_non_spaces (dbp
);
4661 dbp
= skip_spaces (dbp
);
4671 * Postscript tag functions
4672 * Just look for lines where the first character is '/'
4673 * Also look at "defineps" for PSWrap
4675 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4676 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4679 Postscript_functions (inf
)
4682 register char *bp
, *ep
;
4684 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4689 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
4692 make_tag (bp
, ep
- bp
, TRUE
,
4693 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4695 else if (LOOKING_AT (bp
, "defineps"))
4702 * Scheme tag functions
4703 * look for (def... xyzzy
4705 * (def ... ((...(xyzzy ....
4707 * Original code by Ken Haase (1985?)
4711 Scheme_functions (inf
)
4716 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4718 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
4720 bp
= skip_non_spaces (bp
+4);
4721 /* Skip over open parens and white space */
4722 while (notinname (*bp
))
4726 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
4732 /* Find tags in TeX and LaTeX input files. */
4734 /* TEX_toktab is a table of TeX control sequences that define tags.
4735 * Each entry records one such control sequence.
4737 * Original code from who knows whom.
4739 * Stefan Monnier (2002)
4742 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
4744 /* Default set of control sequences to put into TEX_toktab.
4745 The value of environment var TEXTAGS is prepended to this. */
4746 static char *TEX_defenv
= "\
4747 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4748 :part:appendix:entry:index:def\
4749 :newcommand:renewcommand:newenvironment:renewenvironment";
4751 static void TEX_mode
__P((FILE *));
4752 static void TEX_decode_env
__P((char *, char *));
4754 static char TEX_esc
= '\\';
4755 static char TEX_opgrp
= '{';
4756 static char TEX_clgrp
= '}';
4759 * TeX/LaTeX scanning loop.
4768 /* Select either \ or ! as escape character. */
4771 /* Initialize token table once from environment. */
4772 if (TEX_toktab
== NULL
)
4773 TEX_decode_env ("TEXTAGS", TEX_defenv
);
4775 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4777 /* Look at each TEX keyword in line. */
4780 /* Look for a TEX escape. */
4781 while (*cp
++ != TEX_esc
)
4782 if (cp
[-1] == '\0' || cp
[-1] == '%')
4785 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
4786 if (strneq (cp
, key
->buffer
, key
->len
))
4789 int namelen
, linelen
;
4792 cp
= skip_spaces (cp
+ key
->len
);
4793 if (*cp
== TEX_opgrp
)
4799 (!iswhite (*p
) && *p
!= '#' &&
4800 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
4805 if (!opgrp
|| *p
== TEX_clgrp
)
4807 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
4809 linelen
= p
- lb
.buffer
+ 1;
4811 make_tag (cp
, namelen
, TRUE
,
4812 lb
.buffer
, linelen
, lineno
, linecharno
);
4813 goto tex_next_line
; /* We only tag a line once */
4821 #define TEX_LESC '\\'
4822 #define TEX_SESC '!'
4824 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4825 chars accordingly. */
4832 while ((c
= getc (inf
)) != EOF
)
4834 /* Skip to next line if we hit the TeX comment char. */
4838 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
4854 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4855 No attempt is made to correct the situation. */
4859 /* Read environment and prepend it to the default string.
4860 Build token table. */
4862 TEX_decode_env (evarname
, defenv
)
4866 register char *env
, *p
;
4869 /* Append default string to environment. */
4870 env
= getenv (evarname
);
4876 env
= concat (oldenv
, defenv
, "");
4879 /* Allocate a token table */
4880 for (len
= 1, p
= env
; p
;)
4881 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
4883 TEX_toktab
= xnew (len
, linebuffer
);
4885 /* Unpack environment string into token table. Be careful about */
4886 /* zero-length strings (leading ':', "::" and trailing ':') */
4887 for (i
= 0; *env
!= '\0';)
4889 p
= etags_strchr (env
, ':');
4890 if (!p
) /* End of environment string. */
4891 p
= env
+ strlen (env
);
4893 { /* Only non-zero strings. */
4894 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
4895 TEX_toktab
[i
].len
= p
- env
;
4902 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
4903 TEX_toktab
[i
].len
= 0;
4910 /* Texinfo support. Dave Love, Mar. 2000. */
4916 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4917 if (LOOKING_AT (cp
, "@node"))
4920 while (*cp
!= '\0' && *cp
!= ',')
4922 make_tag (start
, cp
- start
, TRUE
,
4923 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4931 * Assumes that the predicate or rule starts at column 0.
4932 * Only the first clause of a predicate or rule is added.
4933 * Original code by Sunichirou Sugou (1989)
4934 * Rewritten by Anders Lindgren (1996)
4936 static int prolog_pr
__P((char *, char *));
4937 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
4938 static int prolog_atom
__P((char *, int));
4941 Prolog_functions (inf
)
4952 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4954 if (cp
[0] == '\0') /* Empty line */
4956 else if (iswhite (cp
[0])) /* Not a predicate */
4958 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
4959 prolog_skip_comment (&lb
, inf
);
4960 else if ((len
= prolog_pr (cp
, last
)) > 0)
4962 /* Predicate or rule. Store the function name so that we
4963 only generate a tag for the first clause. */
4965 last
= xnew(len
+ 1, char);
4966 else if (len
+ 1 > allocated
)
4967 xrnew (last
, len
+ 1, char);
4968 allocated
= len
+ 1;
4969 strncpy (last
, cp
, len
);
4977 prolog_skip_comment (plb
, inf
)
4985 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
4986 if (cp
[0] == '*' && cp
[1] == '/')
4988 readline (plb
, inf
);
4994 * A predicate or rule definition is added if it matches:
4995 * <beginning of line><Prolog Atom><whitespace>(
4996 * or <beginning of line><Prolog Atom><whitespace>:-
4998 * It is added to the tags database if it doesn't match the
4999 * name of the previous clause header.
5001 * Return the size of the name of the predicate or rule, or 0 if no
5007 char *last
; /* Name of last clause. */
5012 pos
= prolog_atom (s
, 0);
5017 pos
= skip_spaces (s
+ pos
) - s
;
5020 || (s
[pos
] == '(' && (pos
+= 1))
5021 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5022 && (last
== NULL
/* save only the first clause */
5023 || len
!= strlen (last
)
5024 || !strneq (s
, last
, len
)))
5026 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5034 * Consume a Prolog atom.
5035 * Return the number of bytes consumed, or -1 if there was an error.
5037 * A prolog atom, in this context, could be one of:
5038 * - An alphanumeric sequence, starting with a lower case letter.
5039 * - A quoted arbitrary string. Single quotes can escape themselves.
5040 * Backslash quotes everything.
5043 prolog_atom (s
, pos
)
5051 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5053 /* The atom is unquoted. */
5055 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5059 return pos
- origpos
;
5061 else if (s
[pos
] == '\'')
5072 pos
++; /* A double quote */
5074 else if (s
[pos
] == '\0')
5075 /* Multiline quoted atoms are ignored. */
5077 else if (s
[pos
] == '\\')
5079 if (s
[pos
+1] == '\0')
5086 return pos
- origpos
;
5094 * Support for Erlang
5096 * Generates tags for functions, defines, and records.
5097 * Assumes that Erlang functions start at column 0.
5098 * Original code by Anders Lindgren (1996)
5100 static int erlang_func
__P((char *, char *));
5101 static void erlang_attribute
__P((char *));
5102 static int erlang_atom
__P((char *));
5105 Erlang_functions (inf
)
5116 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5118 if (cp
[0] == '\0') /* Empty line */
5120 else if (iswhite (cp
[0])) /* Not function nor attribute */
5122 else if (cp
[0] == '%') /* comment */
5124 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5126 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5128 erlang_attribute (cp
);
5131 else if ((len
= erlang_func (cp
, last
)) > 0)
5134 * Function. Store the function name so that we only
5135 * generates a tag for the first clause.
5138 last
= xnew (len
+ 1, char);
5139 else if (len
+ 1 > allocated
)
5140 xrnew (last
, len
+ 1, char);
5141 allocated
= len
+ 1;
5142 strncpy (last
, cp
, len
);
5150 * A function definition is added if it matches:
5151 * <beginning of line><Erlang Atom><whitespace>(
5153 * It is added to the tags database if it doesn't match the
5154 * name of the previous clause header.
5156 * Return the size of the name of the function, or 0 if no function
5160 erlang_func (s
, last
)
5162 char *last
; /* Name of last clause. */
5167 pos
= erlang_atom (s
);
5172 pos
= skip_spaces (s
+ pos
) - s
;
5174 /* Save only the first clause. */
5177 || len
!= (int)strlen (last
)
5178 || !strneq (s
, last
, len
)))
5180 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5189 * Handle attributes. Currently, tags are generated for defines
5192 * They are on the form:
5193 * -define(foo, bar).
5194 * -define(Foo(M, N), M+N).
5195 * -record(graph, {vtab = notable, cyclic = true}).
5198 erlang_attribute (s
)
5203 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5206 int len
= erlang_atom (skip_spaces (cp
));
5208 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5215 * Consume an Erlang atom (or variable).
5216 * Return the number of bytes consumed, or -1 if there was an error.
5224 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5226 /* The atom is unquoted. */
5229 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5231 else if (s
[pos
] == '\'')
5233 for (pos
++; s
[pos
] != '\''; pos
++)
5234 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5235 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5244 #ifdef ETAGS_REGEXPS
5246 static char *scan_separators
__P((char *));
5247 static void add_regex
__P((char *, language
*));
5248 static char *substitute
__P((char *, char *, struct re_registers
*));
5251 * Take a string like "/blah/" and turn it into "blah", verifying
5252 * that the first and last characters are the same, and handling
5253 * quoted separator characters. Actually, stops on the occurrence of
5254 * an unquoted separator. Also process \t, \n, etc. and turn into
5255 * appropriate characters. Works in place. Null terminates name string.
5256 * Returns pointer to terminating separator, or NULL for
5257 * unterminated regexps.
5260 scan_separators (name
)
5264 char *copyto
= name
;
5265 bool quoted
= FALSE
;
5267 for (++name
; *name
!= '\0'; ++name
)
5273 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5274 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5275 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5276 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5277 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5278 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5279 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5280 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5281 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5287 /* Something else is quoted, so preserve the quote. */
5295 else if (*name
== '\\')
5297 else if (*name
== sep
)
5303 name
= NULL
; /* signal unterminated regexp */
5305 /* Terminate copied string. */
5310 /* Look at the argument of --regex or --no-regex and do the right
5311 thing. Same for each line of a regexp file. */
5313 analyse_regex (regex_arg
)
5316 if (regex_arg
== NULL
)
5318 free_patterns (); /* --no-regex: remove existing regexps */
5322 /* A real --regexp option or a line in a regexp file. */
5323 switch (regex_arg
[0])
5325 /* Comments in regexp file or null arg to --regex. */
5331 /* Read a regex file. This is recursive and may result in a
5332 loop, which will stop when the file descriptors are exhausted. */
5336 linebuffer regexbuf
;
5337 char *regexfile
= regex_arg
+ 1;
5339 /* regexfile is a file containing regexps, one per line. */
5340 regexfp
= fopen (regexfile
, "r");
5341 if (regexfp
== NULL
)
5346 initbuffer (®exbuf
);
5347 while (readline_internal (®exbuf
, regexfp
) > 0)
5348 analyse_regex (regexbuf
.buffer
);
5349 free (regexbuf
.buffer
);
5354 /* Regexp to be used for a specific language only. */
5358 char *lang_name
= regex_arg
+ 1;
5361 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5364 error ("unterminated language name in regex: %s", regex_arg
);
5368 lang
= get_language_from_langname (lang_name
);
5371 add_regex (cp
, lang
);
5375 /* Regexp to be used for any language. */
5377 add_regex (regex_arg
, NULL
);
5382 /* Turn a name, which is an ed-style (but Emacs syntax) regular
5383 expression, into a real regular expression by compiling it. */
5385 add_regex (regexp_pattern
, lang
)
5386 char *regexp_pattern
;
5389 static struct re_pattern_buffer zeropattern
;
5390 char sep
, *pat
, *name
, *modifiers
;
5392 struct re_pattern_buffer
*patbuf
;
5394 bool ignore_case
, multi_line
, single_line
;
5397 if (strlen(regexp_pattern
) < 3)
5399 error ("null regexp", (char *)NULL
);
5402 sep
= regexp_pattern
[0];
5403 name
= scan_separators (regexp_pattern
);
5406 error ("%s: unterminated regexp", regexp_pattern
);
5411 error ("null name for regexp \"%s\"", regexp_pattern
);
5414 modifiers
= scan_separators (name
);
5415 if (modifiers
== NULL
) /* no terminating separator --> no name */
5421 modifiers
+= 1; /* skip separator */
5423 /* Parse regex modifiers. */
5424 ignore_case
= FALSE
; /* case is significant */
5425 multi_line
= FALSE
; /* matches are done one line at a time */
5426 single_line
= FALSE
; /* dot does not match newline */
5427 for (; modifiers
[0] != '\0'; modifiers
++)
5428 switch (modifiers
[0])
5438 need_filebuf
= TRUE
;
5443 wrongmod
[0] = modifiers
[0];
5445 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
5450 patbuf
= xnew (1, struct re_pattern_buffer
);
5451 *patbuf
= zeropattern
;
5454 static char lc_trans
[CHARS
];
5456 for (i
= 0; i
< CHARS
; i
++)
5457 lc_trans
[i
] = lowcase (i
);
5458 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5462 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
5464 pat
= regexp_pattern
;
5467 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
5469 re_set_syntax (RE_SYNTAX_EMACS
);
5471 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
5476 error ("%s while compiling pattern", err
);
5481 p_head
= xnew (1, pattern
);
5482 p_head
->regex
= savestr (regexp_pattern
);
5483 p_head
->p_next
= pp
;
5484 p_head
->lang
= lang
;
5485 p_head
->pat
= patbuf
;
5486 p_head
->name_pattern
= savestr (name
);
5487 p_head
->error_signaled
= FALSE
;
5488 p_head
->ignore_case
= ignore_case
;
5489 p_head
->multi_line
= multi_line
;
5493 * Do the substitutions indicated by the regular expression and
5497 substitute (in
, out
, regs
)
5499 struct re_registers
*regs
;
5502 int size
, dig
, diglen
;
5505 size
= strlen (out
);
5507 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5508 if (out
[size
- 1] == '\\')
5509 fatal ("pattern error in \"%s\"", out
);
5510 for (t
= etags_strchr (out
, '\\');
5512 t
= etags_strchr (t
+ 2, '\\'))
5516 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5522 /* Allocate space and do the substitutions. */
5523 result
= xnew (size
+ 1, char);
5525 for (t
= result
; *out
!= '\0'; out
++)
5526 if (*out
== '\\' && ISDIGIT (*++out
))
5529 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5530 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5537 assert (t
<= result
+ size
&& t
- result
== (int)strlen (result
));
5542 /* Deallocate all patterns. */
5547 while (p_head
!= NULL
)
5549 pp
= p_head
->p_next
;
5550 free (p_head
->regex
);
5551 free (p_head
->name_pattern
);
5559 * Reads the whole file as a single string from `filebuf' and looks for
5560 * multi-line regular expressions, creating tags on matches.
5561 * readline already dealt with normal regexps.
5563 * Idea by Ben Wing <ben@666.com> (2002).
5566 regex_tag_multiline ()
5568 char *buffer
= filebuf
.buffer
;
5571 for (pp
= p_head
; pp
!= NULL
; pp
= pp
->p_next
)
5575 if (!pp
->multi_line
)
5576 continue; /* skip normal regexps */
5578 /* Generic initialisations before parsing file from memory. */
5579 lineno
= 1; /* reset global line number */
5580 charno
= 0; /* reset global char number */
5581 linecharno
= 0; /* reset global char number of line start */
5583 /* Only use generic regexps or those for the current language. */
5584 if (pp
->lang
!= NULL
&& pp
->lang
!= curfdp
->lang
)
5587 while (match
>= 0 && match
< filebuf
.len
)
5589 match
= re_search (pp
->pat
, buffer
, filebuf
.len
, charno
,
5590 filebuf
.len
- match
, &pp
->regs
);
5595 if (!pp
->error_signaled
)
5597 error ("regexp stack overflow while matching \"%s\"",
5599 pp
->error_signaled
= TRUE
;
5606 if (match
== pp
->regs
.end
[0])
5608 if (!pp
->error_signaled
)
5610 error ("regexp matches the empty string: \"%s\"",
5612 pp
->error_signaled
= TRUE
;
5614 match
= -3; /* exit from while loop */
5618 /* Match occurred. Construct a tag. */
5619 while (charno
< pp
->regs
.end
[0])
5620 if (buffer
[charno
++] == '\n')
5621 lineno
++, linecharno
= charno
;
5622 if (pp
->name_pattern
[0] != '\0')
5624 /* Make a named tag.
5625 Do not use make_tag here, as it would make the name
5626 implicit if possible, while we want to respect the user's
5627 request to create an explicit tag name. */
5628 char *name
= substitute (buffer
,
5629 pp
->name_pattern
, &pp
->regs
);
5631 pfnote (name
, TRUE
, buffer
+ linecharno
,
5632 charno
- linecharno
+ 1, lineno
, linecharno
);
5636 /* Make an unnamed tag. */
5637 pfnote ((char *)NULL
, TRUE
, buffer
+ linecharno
,
5638 charno
- linecharno
+ 1, lineno
, linecharno
);
5646 #endif /* ETAGS_REGEXPS */
5653 register int len
= 0;
5655 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
5657 if (*cp
== '\0' && !intoken (dbp
[len
]))
5666 get_tag (bp
, namepp
)
5670 register char *cp
= bp
;
5674 /* Go till you get to white space or a syntactic break */
5675 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
5677 make_tag (bp
, cp
- bp
, TRUE
,
5678 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5682 *namepp
= savenstr (bp
, cp
- bp
);
5685 /* Initialize a linebuffer for use */
5690 lbp
->size
= (DEBUG
) ? 3 : 200;
5691 lbp
->buffer
= xnew (lbp
->size
, char);
5692 lbp
->buffer
[0] = '\0';
5697 * Read a line of text from `stream' into `lbp', excluding the
5698 * newline or CR-NL, if any. Return the number of characters read from
5699 * `stream', which is the length of the line including the newline.
5701 * On DOS or Windows we do not count the CR character, if any before the
5702 * NL, in the returned length; this mirrors the behavior of Emacs on those
5703 * platforms (for text files, it translates CR-NL to NL as it reads in the
5706 * If multi-line regular expressions are requested, each line read is
5707 * appended to `filebuf'.
5710 readline_internal (lbp
, stream
)
5712 register FILE *stream
;
5714 char *buffer
= lbp
->buffer
;
5715 register char *p
= lbp
->buffer
;
5716 register char *pend
;
5719 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
5723 register int c
= getc (stream
);
5726 /* We're at the end of linebuffer: expand it. */
5728 xrnew (buffer
, lbp
->size
, char);
5729 p
+= buffer
- lbp
->buffer
;
5730 pend
= buffer
+ lbp
->size
;
5731 lbp
->buffer
= buffer
;
5741 if (p
> buffer
&& p
[-1] == '\r')
5745 /* Assume CRLF->LF translation will be performed by Emacs
5746 when loading this file, so CRs won't appear in the buffer.
5747 It would be cleaner to compensate within Emacs;
5748 however, Emacs does not know how many CRs were deleted
5749 before any given point in the file. */
5764 lbp
->len
= p
- buffer
;
5766 if (need_filebuf
/* we need filebuf for multi-line regexps */
5767 && chars_deleted
> 0) /* not at EOF */
5769 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
5771 /* Expand filebuf. */
5773 xrnew (filebuf
.buffer
, filebuf
.size
, char);
5775 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
5776 filebuf
.len
+= lbp
->len
;
5777 filebuf
.buffer
[filebuf
.len
++] = '\n';
5778 filebuf
.buffer
[filebuf
.len
] = '\0';
5781 return lbp
->len
+ chars_deleted
;
5785 * Like readline_internal, above, but in addition try to match the
5786 * input line against relevant regular expressions and manage #line
5790 readline (lbp
, stream
)
5796 linecharno
= charno
; /* update global char number of line start */
5797 result
= readline_internal (lbp
, stream
); /* read line */
5798 lineno
+= 1; /* increment global line number */
5799 charno
+= result
; /* increment global char number */
5801 /* Honour #line directives. */
5802 if (!no_line_directive
)
5804 static bool discard_until_line_directive
;
5806 /* Check whether this is a #line directive. */
5807 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
5811 if (DEBUG
) start
= 0; /* shut up the compiler */
5812 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
5814 char *endp
= lbp
->buffer
+ start
;
5817 while ((endp
= etags_strchr (endp
, '"')) != NULL
5818 && endp
[-1] == '\\')
5821 /* Ok, this is a real #line directive. Let's deal with it. */
5823 char *taggedabsname
; /* absolute name of original file */
5824 char *taggedfname
; /* name of original file as given */
5825 char *name
; /* temp var */
5827 discard_until_line_directive
= FALSE
; /* found it */
5828 name
= lbp
->buffer
+ start
;
5830 canonicalize_filename (name
); /* for DOS */
5831 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
5832 if (filename_is_absolute (name
)
5833 || filename_is_absolute (curfdp
->infname
))
5834 taggedfname
= savestr (taggedabsname
);
5836 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
5838 if (streq (curfdp
->taggedfname
, taggedfname
))
5839 /* The #line directive is only a line number change. We
5840 deal with this afterwards. */
5843 /* The tags following this #line directive should be
5844 attributed to taggedfname. In order to do this, set
5845 curfdp accordingly. */
5847 fdesc
*fdp
; /* file description pointer */
5849 /* Go look for a file description already set up for the
5850 file indicated in the #line directive. If there is
5851 one, use it from now until the next #line
5853 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5854 if (streq (fdp
->infname
, curfdp
->infname
)
5855 && streq (fdp
->taggedfname
, taggedfname
))
5856 /* If we remove the second test above (after the &&)
5857 then all entries pertaining to the same file are
5858 coalesced in the tags file. If we use it, then
5859 entries pertaining to the same file but generated
5860 from different files (via #line directives) will
5861 go into separate sections in the tags file. These
5862 alternatives look equivalent. The first one
5863 destroys some apparently useless information. */
5869 /* Else, if we already tagged the real file, skip all
5870 input lines until the next #line directive. */
5871 if (fdp
== NULL
) /* not found */
5872 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5873 if (streq (fdp
->infabsname
, taggedabsname
))
5875 discard_until_line_directive
= TRUE
;
5879 /* Else create a new file description and use that from
5880 now on, until the next #line directive. */
5881 if (fdp
== NULL
) /* not found */
5884 fdhead
= xnew (1, fdesc
);
5885 *fdhead
= *curfdp
; /* copy curr. file description */
5887 fdhead
->infname
= savestr (curfdp
->infname
);
5888 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
5889 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
5890 fdhead
->taggedfname
= taggedfname
;
5891 fdhead
->usecharno
= FALSE
;
5895 free (taggedabsname
);
5897 readline (lbp
, stream
);
5899 } /* if a real #line directive */
5900 } /* if #line is followed by a a number */
5901 } /* if line begins with "#line " */
5903 /* If we are here, no #line directive was found. */
5904 if (discard_until_line_directive
)
5908 /* Do a tail recursion on ourselves, thus discarding the contents
5909 of the line buffer. */
5910 readline (lbp
, stream
);
5914 discard_until_line_directive
= FALSE
;
5917 } /* if #line directives should be considered */
5919 #ifdef ETAGS_REGEXPS
5924 /* Match against relevant patterns. */
5926 for (pp
= p_head
; pp
!= NULL
; pp
= pp
->p_next
)
5928 /* Only use generic regexps or those for the current language.
5929 Also do not use multiline regexps, which is the job of
5930 regex_tag_multiline. */
5931 if ((pp
->lang
!= NULL
&& pp
->lang
!= fdhead
->lang
)
5935 match
= re_match (pp
->pat
, lbp
->buffer
, lbp
->len
, 0, &pp
->regs
);
5940 if (!pp
->error_signaled
)
5942 error ("regexp stack overflow while matching \"%s\"",
5944 pp
->error_signaled
= TRUE
;
5951 /* Empty string matched. */
5952 if (!pp
->error_signaled
)
5954 error ("regexp matches the empty string: \"%s\"",
5956 pp
->error_signaled
= TRUE
;
5960 /* Match occurred. Construct a tag. */
5961 if (pp
->name_pattern
[0] != '\0')
5963 /* Make a named tag.
5964 Do not use make_tag here, as it would make the name
5965 implicit if possible, while we want to respect the user's
5966 request to create an explicit tag name. */
5967 char *name
= substitute (lbp
->buffer
,
5968 pp
->name_pattern
, &pp
->regs
);
5970 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
5974 /* Make an unnamed tag. */
5975 pfnote ((char *)NULL
, TRUE
,
5976 lbp
->buffer
, match
, lineno
, linecharno
);
5982 #endif /* ETAGS_REGEXPS */
5987 * Return a pointer to a space of size strlen(cp)+1 allocated
5988 * with xnew where the string CP has been copied.
5994 return savenstr (cp
, strlen (cp
));
5998 * Return a pointer to a space of size LEN+1 allocated with xnew where
5999 * the string CP has been copied for at most the first LEN characters.
6008 dp
= xnew (len
+ 1, char);
6009 strncpy (dp
, cp
, len
);
6015 * Return the ptr in sp at which the character c last
6016 * appears; NULL if not found
6018 * Identical to POSIX strrchr, included for portability.
6021 etags_strrchr (sp
, c
)
6022 register const char *sp
;
6025 register const char *r
;
6037 * Return the ptr in sp at which the character c first
6038 * appears; NULL if not found
6040 * Identical to POSIX strchr, included for portability.
6043 etags_strchr (sp
, c
)
6044 register const char *sp
;
6056 * Return TRUE if the two strings are equal, ignoring case for alphabetic
6059 * Analogous to BSD's strcasecmp, included for portability.
6063 register const char *s1
;
6064 register const char *s2
;
6067 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6068 ? lowcase (*s1
) == lowcase (*s2
)
6072 return (*s1
== *s2
);
6075 /* Skip spaces, return new pointer. */
6080 while (iswhite (*cp
))
6085 /* Skip non spaces, return new pointer. */
6087 skip_non_spaces (cp
)
6090 while (*cp
!= '\0' && !iswhite (*cp
))
6095 /* Print error message and exit. */
6113 suggest_asking_for_help ()
6115 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6126 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6129 const char *s1
, *s2
;
6131 fprintf (stderr
, "%s: ", progname
);
6132 fprintf (stderr
, s1
, s2
);
6133 fprintf (stderr
, "\n");
6136 /* Return a newly-allocated string whose contents
6137 concatenate those of s1, s2, s3. */
6142 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6143 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6145 strcpy (result
, s1
);
6146 strcpy (result
+ len1
, s2
);
6147 strcpy (result
+ len1
+ len2
, s3
);
6148 result
[len1
+ len2
+ len3
] = '\0';
6154 /* Does the same work as the system V getcwd, but does not need to
6155 guess the buffer size in advance. */
6161 char *path
= xnew (bufsize
, char);
6163 while (getcwd (path
, bufsize
) == NULL
)
6165 if (errno
!= ERANGE
)
6169 path
= xnew (bufsize
, char);
6172 canonicalize_filename (path
);
6175 #else /* not HAVE_GETCWD */
6178 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6182 for (p
= path
; *p
!= '\0'; p
++)
6188 return strdup (path
);
6189 #else /* not MSDOS */
6194 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6195 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6200 #endif /* not MSDOS */
6201 #endif /* not HAVE_GETCWD */
6204 /* Return a newly allocated string containing the file name of FILE
6205 relative to the absolute directory DIR (which should end with a slash). */
6207 relative_filename (file
, dir
)
6210 char *fp
, *dp
, *afn
, *res
;
6213 /* Find the common root of file and dir (with a trailing slash). */
6214 afn
= absolute_filename (file
, cwd
);
6217 while (*fp
++ == *dp
++)
6219 fp
--, dp
--; /* back to the first differing char */
6221 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6224 do /* look at the equal chars until '/' */
6228 /* Build a sequence of "../" strings for the resulting relative file name. */
6230 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6232 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6235 strcat (res
, "../");
6237 /* Add the file name relative to the common root of file and dir. */
6238 strcat (res
, fp
+ 1);
6244 /* Return a newly allocated string containing the absolute file name
6245 of FILE given DIR (which should end with a slash). */
6247 absolute_filename (file
, dir
)
6250 char *slashp
, *cp
, *res
;
6252 if (filename_is_absolute (file
))
6253 res
= savestr (file
);
6255 /* We don't support non-absolute file names with a drive
6256 letter, like `d:NAME' (it's too much hassle). */
6257 else if (file
[1] == ':')
6258 fatal ("%s: relative file names with drive letters not supported", file
);
6261 res
= concat (dir
, file
, "");
6263 /* Delete the "/dirname/.." and "/." substrings. */
6264 slashp
= etags_strchr (res
, '/');
6265 while (slashp
!= NULL
&& slashp
[0] != '\0')
6267 if (slashp
[1] == '.')
6269 if (slashp
[2] == '.'
6270 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6275 while (cp
>= res
&& !filename_is_absolute (cp
));
6277 cp
= slashp
; /* the absolute name begins with "/.." */
6279 /* Under MSDOS and NT we get `d:/NAME' as absolute
6280 file name, so the luser could say `d:/../NAME'.
6281 We silently treat this as `d:/NAME'. */
6282 else if (cp
[0] != '/')
6285 strcpy (cp
, slashp
+ 3);
6289 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6291 strcpy (slashp
, slashp
+ 2);
6296 slashp
= etags_strchr (slashp
+ 1, '/');
6300 return savestr ("/");
6305 /* Return a newly allocated string containing the absolute
6306 file name of dir where FILE resides given DIR (which should
6307 end with a slash). */
6309 absolute_dirname (file
, dir
)
6315 canonicalize_filename (file
);
6316 slashp
= etags_strrchr (file
, '/');
6318 return savestr (dir
);
6321 res
= absolute_filename (file
, dir
);
6327 /* Whether the argument string is an absolute file name. The argument
6328 string must have been canonicalized with canonicalize_filename. */
6330 filename_is_absolute (fn
)
6333 return (fn
[0] == '/'
6335 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6340 /* Translate backslashes into slashes. Works in place. */
6342 canonicalize_filename (fn
)
6346 /* Canonicalize drive letter case. */
6347 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6348 fn
[0] = upcase (fn
[0]);
6349 /* Convert backslashes to slashes. */
6350 for (; *fn
!= '\0'; fn
++)
6355 fn
= NULL
; /* shut up the compiler */
6359 /* Set the minimum size of a string contained in a linebuffer. */
6361 linebuffer_setlen (lbp
, toksize
)
6365 while (lbp
->size
<= toksize
)
6368 xrnew (lbp
->buffer
, lbp
->size
, char);
6373 /* Like malloc but get fatal error if memory is exhausted. */
6378 PTR result
= (PTR
) malloc (size
);
6380 fatal ("virtual memory exhausted", (char *)NULL
);
6385 xrealloc (ptr
, size
)
6389 PTR result
= (PTR
) realloc (ptr
, size
);
6391 fatal ("virtual memory exhausted", (char *)NULL
);
6397 * c-indentation-style: gnu
6398 * indent-tabs-mode: t
6401 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "pattern")