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 $Revision: 16.55 $";
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 strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
191 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
192 #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
194 #define CHARS 256 /* 2^sizeof(char) */
195 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
196 #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
197 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
198 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
199 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
200 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
202 #define ISALNUM(c) isalnum (CHAR(c))
203 #define ISALPHA(c) isalpha (CHAR(c))
204 #define ISDIGIT(c) isdigit (CHAR(c))
205 #define ISLOWER(c) islower (CHAR(c))
207 #define lowcase(c) tolower (CHAR(c))
208 #define upcase(c) toupper (CHAR(c))
212 * xnew, xrnew -- allocate, reallocate storage
214 * SYNOPSIS: Type *xnew (int n, Type);
215 * void xrnew (OldPointer, int n, Type);
218 # include "chkmalloc.h"
219 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
220 (n) * sizeof (Type)))
221 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
222 (char *) (op), (n) * sizeof (Type)))
224 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
225 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
226 (char *) (op), (n) * sizeof (Type)))
231 typedef void Lang_function
__P((FILE *));
235 char *suffix
; /* file name suffix for this compressor */
236 char *command
; /* takes one arg and decompresses to stdout */
241 char *name
; /* language name */
242 bool metasource
; /* source used to generate other sources */
243 Lang_function
*function
; /* parse function */
244 char **filenames
; /* names of this language's files */
245 char **suffixes
; /* name suffixes of this language's files */
246 char **interpreters
; /* interpreters for this language */
251 struct fdesc
*next
; /* for the linked list */
252 char *infname
; /* uncompressed input file name */
253 char *infabsname
; /* absolute uncompressed input file name */
254 char *infabsdir
; /* absolute dir of input file */
255 char *taggedfname
; /* file name to write in tagfile */
256 language
*lang
; /* language of file */
257 char *prop
; /* file properties to write in tagfile */
258 bool usecharno
; /* etags tags shall contain char number */
259 bool written
; /* entry written in the tags file */
262 typedef struct node_st
263 { /* sorting structure */
264 struct node_st
*left
, *right
; /* left and right sons */
265 fdesc
*fdp
; /* description of file to whom tag belongs */
266 char *name
; /* tag name */
267 char *regex
; /* search regexp */
268 bool valid
; /* write this tag on the tag file */
269 bool is_func
; /* function tag: use regexp in CTAGS mode */
270 bool been_warned
; /* warning already given for duplicated tag */
271 int lno
; /* line number tag is on */
272 long cno
; /* character number line starts on */
276 * A `linebuffer' is a structure which holds a line of text.
277 * `readline_internal' reads a line from a stream into a linebuffer
278 * and works regardless of the length of the line.
279 * SIZE is the size of BUFFER, LEN is the length of the string in
280 * BUFFER after readline reads it.
289 /* Used to support mixing of --lang and file names. */
293 at_language
, /* a language specification */
294 at_regexp
, /* a regular expression */
295 at_filename
, /* a file name */
296 at_stdin
/* read from stdin here */
297 } arg_type
; /* argument type */
298 language
*lang
; /* language associated with the argument */
299 char *what
; /* the argument itself */
303 /* Structure defining a regular expression. */
304 typedef struct regexp
306 struct regexp
*p_next
; /* pointer to next in list */
307 language
*lang
; /* if set, use only for this language */
308 char *pattern
; /* the regexp pattern */
309 char *name
; /* tag name */
310 struct re_pattern_buffer
*pat
; /* the compiled pattern */
311 struct re_registers regs
; /* re registers */
312 bool error_signaled
; /* already signaled for this regexp */
313 bool force_explicit_name
; /* do not allow implict tag name */
314 bool ignore_case
; /* ignore case when matching */
315 bool multi_line
; /* do a multi-line match on the whole file */
317 #endif /* ETAGS_REGEXPS */
320 /* Many compilers barf on this:
321 Lang_function Ada_funcs;
322 so let's write it this way */
323 static void Ada_funcs
__P((FILE *));
324 static void Asm_labels
__P((FILE *));
325 static void C_entries
__P((int c_ext
, FILE *));
326 static void default_C_entries
__P((FILE *));
327 static void plain_C_entries
__P((FILE *));
328 static void Cjava_entries
__P((FILE *));
329 static void Cobol_paragraphs
__P((FILE *));
330 static void Cplusplus_entries
__P((FILE *));
331 static void Cstar_entries
__P((FILE *));
332 static void Erlang_functions
__P((FILE *));
333 static void Fortran_functions
__P((FILE *));
334 static void HTML_labels
__P((FILE *));
335 static void Lisp_functions
__P((FILE *));
336 static void Makefile_targets
__P((FILE *));
337 static void Pascal_functions
__P((FILE *));
338 static void Perl_functions
__P((FILE *));
339 static void PHP_functions
__P((FILE *));
340 static void Postscript_functions
__P((FILE *));
341 static void Prolog_functions
__P((FILE *));
342 static void Python_functions
__P((FILE *));
343 static void Scheme_functions
__P((FILE *));
344 static void TeX_commands
__P((FILE *));
345 static void Texinfo_nodes
__P((FILE *));
346 static void Yacc_entries
__P((FILE *));
347 static void just_read_file
__P((FILE *));
349 static void print_language_names
__P((void));
350 static void print_version
__P((void));
351 static void print_help
__P((void));
352 int main
__P((int, char **));
354 static compressor
*get_compressor_from_suffix
__P((char *, char **));
355 static language
*get_language_from_langname
__P((const char *));
356 static language
*get_language_from_interpreter
__P((char *));
357 static language
*get_language_from_filename
__P((char *, bool));
358 static void readline
__P((linebuffer
*, FILE *));
359 static long readline_internal
__P((linebuffer
*, FILE *));
360 static bool nocase_tail
__P((char *));
361 static void get_tag
__P((char *, char **));
364 static void analyse_regex
__P((char *));
365 static void free_regexps
__P((void));
366 static void regex_tag_multiline
__P((void));
367 #endif /* ETAGS_REGEXPS */
368 static void error
__P((const char *, const char *));
369 static void suggest_asking_for_help
__P((void));
370 void fatal
__P((char *, char *));
371 static void pfatal
__P((char *));
372 static void add_node
__P((node
*, node
**));
374 static void init
__P((void));
375 static void process_file_name
__P((char *, language
*));
376 static void process_file
__P((FILE *, char *, language
*));
377 static void find_entries
__P((FILE *));
378 static void free_tree
__P((node
*));
379 static void free_fdesc
__P((fdesc
*));
380 static void pfnote
__P((char *, bool, char *, int, int, long));
381 static void make_tag
__P((char *, int, bool, char *, int, int, long));
382 static void invalidate_nodes
__P((fdesc
*, node
**));
383 static void put_entries
__P((node
*));
385 static char *concat
__P((char *, char *, char *));
386 static char *skip_spaces
__P((char *));
387 static char *skip_non_spaces
__P((char *));
388 static char *savenstr
__P((char *, int));
389 static char *savestr
__P((char *));
390 static char *etags_strchr
__P((const char *, int));
391 static char *etags_strrchr
__P((const char *, int));
392 static int etags_strcasecmp
__P((const char *, const char *));
393 static int etags_strncasecmp
__P((const char *, const char *, int));
394 static char *etags_getcwd
__P((void));
395 static char *relative_filename
__P((char *, char *));
396 static char *absolute_filename
__P((char *, char *));
397 static char *absolute_dirname
__P((char *, char *));
398 static bool filename_is_absolute
__P((char *f
));
399 static void canonicalize_filename
__P((char *));
400 static void linebuffer_init
__P((linebuffer
*));
401 static void linebuffer_setlen
__P((linebuffer
*, int));
402 static PTR xmalloc
__P((unsigned int));
403 static PTR xrealloc
__P((char *, unsigned int));
406 static char searchar
= '/'; /* use /.../ searches */
408 static char *tagfile
; /* output file */
409 static char *progname
; /* name this program was invoked with */
410 static char *cwd
; /* current working directory */
411 static char *tagfiledir
; /* directory of tagfile */
412 static FILE *tagf
; /* ioptr for tags file */
414 static fdesc
*fdhead
; /* head of file description list */
415 static fdesc
*curfdp
; /* current file description */
416 static int lineno
; /* line number of current line */
417 static long charno
; /* current character number */
418 static long linecharno
; /* charno of start of current line */
419 static char *dbp
; /* pointer to start of current tag */
421 static const int invalidcharno
= -1;
423 static node
*nodehead
; /* the head of the binary tree of tags */
424 static node
*last_node
; /* the last node created */
426 static linebuffer lb
; /* the current line */
427 static linebuffer filebuf
; /* a buffer containing the whole file */
428 static linebuffer token_name
; /* a buffer containing a tag name */
430 /* boolean "functions" (see init) */
431 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
434 *white
= " \f\t\n\r\v",
436 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
437 /* token ending chars */
438 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
439 /* token starting chars */
440 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
441 /* valid in-token chars */
442 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
444 static bool append_to_tagfile
; /* -a: append to tags */
445 /* The next four default to TRUE for etags, but to FALSE for ctags. */
446 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
447 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
448 /* 0 struct/enum/union decls, and C++ */
449 /* member functions. */
450 static bool constantypedefs
; /* -d: create tags for C #define, enum */
451 /* constants and variables. */
452 /* -D: opposite of -d. Default under ctags. */
453 static bool globals
; /* create tags for global variables */
454 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
455 static bool members
; /* create tags for C member variables */
456 static bool no_line_directive
; /* ignore #line directives (undocumented) */
457 static bool update
; /* -u: update tags */
458 static bool vgrind_style
; /* -v: create vgrind style index output */
459 static bool no_warnings
; /* -w: suppress warnings */
460 static bool cxref_style
; /* -x: create cxref style output */
461 static bool cplusplus
; /* .[hc] means C++, not C */
462 static bool ignoreindent
; /* -I: ignore indentation in C */
463 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
465 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
466 static bool parsing_stdin
; /* --parse-stdin used */
469 static regexp
*p_head
; /* list of all regexps */
470 static bool need_filebuf
; /* some regexes are multi-line */
472 # define need_filebuf FALSE
473 #endif /* ETAGS_REGEXPS */
476 static struct option longopts
[] =
478 { "packages-only", no_argument
, &packages_only
, TRUE
},
479 { "c++", no_argument
, NULL
, 'C' },
480 { "declarations", no_argument
, &declarations
, TRUE
},
481 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
482 { "help", no_argument
, NULL
, 'h' },
483 { "help", no_argument
, NULL
, 'H' },
484 { "ignore-indentation", no_argument
, NULL
, 'I' },
485 { "language", required_argument
, NULL
, 'l' },
486 { "members", no_argument
, &members
, TRUE
},
487 { "no-members", no_argument
, &members
, FALSE
},
488 { "output", required_argument
, NULL
, 'o' },
490 { "regex", required_argument
, NULL
, 'r' },
491 { "no-regex", no_argument
, NULL
, 'R' },
492 { "ignore-case-regex", required_argument
, NULL
, 'c' },
493 #endif /* ETAGS_REGEXPS */
494 { "parse-stdin", required_argument
, NULL
, STDIN
},
495 { "version", no_argument
, NULL
, 'V' },
497 #if CTAGS /* Etags options */
498 { "backward-search", no_argument
, NULL
, 'B' },
499 { "cxref", no_argument
, NULL
, 'x' },
500 { "defines", no_argument
, NULL
, 'd' },
501 { "globals", no_argument
, &globals
, TRUE
},
502 { "typedefs", no_argument
, NULL
, 't' },
503 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
504 { "update", no_argument
, NULL
, 'u' },
505 { "vgrind", no_argument
, NULL
, 'v' },
506 { "no-warn", no_argument
, NULL
, 'w' },
508 #else /* Ctags options */
509 { "append", no_argument
, NULL
, 'a' },
510 { "no-defines", no_argument
, NULL
, 'D' },
511 { "no-globals", no_argument
, &globals
, FALSE
},
512 { "include", required_argument
, NULL
, 'i' },
516 #endif /* LONG_OPTIONS */
518 static compressor compressors
[] =
520 { "z", "gzip -d -c"},
521 { "Z", "gzip -d -c"},
522 { "gz", "gzip -d -c"},
523 { "GZ", "gzip -d -c"},
524 { "bz2", "bzip2 -d -c" },
533 static char *Ada_suffixes
[] =
534 { "ads", "adb", "ada", NULL
};
537 static char *Asm_suffixes
[] =
538 { "a", /* Unix assembler */
539 "asm", /* Microcontroller assembly */
540 "def", /* BSO/Tasking definition includes */
541 "inc", /* Microcontroller include files */
542 "ins", /* Microcontroller include files */
543 "s", "sa", /* Unix assembler */
544 "S", /* cpp-processed Unix assembler */
545 "src", /* BSO/Tasking C compiler output */
549 /* Note that .c and .h can be considered C++, if the --c++ flag was
550 given, or if the `class' keyowrd is met inside the file.
551 That is why default_C_entries is called for these. */
552 static char *default_C_suffixes
[] =
555 static char *Cplusplus_suffixes
[] =
556 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
557 "M", /* Objective C++ */
558 "pdb", /* Postscript with C syntax */
561 static char *Cjava_suffixes
[] =
564 static char *Cobol_suffixes
[] =
565 { "COB", "cob", NULL
};
567 static char *Cstar_suffixes
[] =
568 { "cs", "hs", NULL
};
570 static char *Erlang_suffixes
[] =
571 { "erl", "hrl", NULL
};
573 static char *Fortran_suffixes
[] =
574 { "F", "f", "f90", "for", NULL
};
576 static char *HTML_suffixes
[] =
577 { "htm", "html", "shtml", NULL
};
579 static char *Lisp_suffixes
[] =
580 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
582 static char *Makefile_filenames
[] =
583 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
585 static char *Pascal_suffixes
[] =
586 { "p", "pas", NULL
};
588 static char *Perl_suffixes
[] =
589 { "pl", "pm", NULL
};
591 static char *Perl_interpreters
[] =
592 { "perl", "@PERL@", NULL
};
594 static char *PHP_suffixes
[] =
595 { "php", "php3", "php4", NULL
};
597 static char *plain_C_suffixes
[] =
598 { "lm", /* Objective lex file */
599 "m", /* Objective C file */
600 "pc", /* Pro*C file */
603 static char *Postscript_suffixes
[] =
604 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
606 static char *Prolog_suffixes
[] =
609 static char *Python_suffixes
[] =
612 /* Can't do the `SCM' or `scm' prefix with a version number. */
613 static char *Scheme_suffixes
[] =
614 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
616 static char *TeX_suffixes
[] =
617 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
619 static char *Texinfo_suffixes
[] =
620 { "texi", "texinfo", "txi", NULL
};
622 static char *Yacc_suffixes
[] =
623 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
626 * Table of languages.
628 * It is ok for a given function to be listed under more than one
629 * name. I just didn't.
632 static language lang_names
[] =
634 { "ada", FALSE
, Ada_funcs
, NULL
, Ada_suffixes
, NULL
},
635 { "asm", FALSE
, Asm_labels
, NULL
, Asm_suffixes
, NULL
},
636 { "c", FALSE
, default_C_entries
, NULL
, default_C_suffixes
, NULL
},
637 { "c++", FALSE
, Cplusplus_entries
, NULL
, Cplusplus_suffixes
, NULL
},
638 { "c*", FALSE
, Cstar_entries
, NULL
, Cstar_suffixes
, NULL
},
639 { "cobol", FALSE
, Cobol_paragraphs
, NULL
, Cobol_suffixes
, NULL
},
640 { "erlang", FALSE
, Erlang_functions
, NULL
, Erlang_suffixes
, NULL
},
641 { "fortran", FALSE
, Fortran_functions
, NULL
, Fortran_suffixes
, NULL
},
642 { "html", FALSE
, HTML_labels
, NULL
, HTML_suffixes
, NULL
},
643 { "java", FALSE
, Cjava_entries
, NULL
, Cjava_suffixes
, NULL
},
644 { "lisp", FALSE
, Lisp_functions
, NULL
, Lisp_suffixes
, NULL
},
645 { "makefile", FALSE
, Makefile_targets
, Makefile_filenames
, NULL
, NULL
},
646 { "pascal", FALSE
, Pascal_functions
, NULL
, Pascal_suffixes
, NULL
},
647 { "perl", FALSE
, Perl_functions
,NULL
, Perl_suffixes
, Perl_interpreters
},
648 { "php", FALSE
, PHP_functions
, NULL
, PHP_suffixes
, NULL
},
649 { "postscript",FALSE
, Postscript_functions
,NULL
, Postscript_suffixes
, NULL
},
650 { "proc", FALSE
, plain_C_entries
, NULL
, plain_C_suffixes
, NULL
},
651 { "prolog", FALSE
, Prolog_functions
, NULL
, Prolog_suffixes
, NULL
},
652 { "python", FALSE
, Python_functions
, NULL
, Python_suffixes
, NULL
},
653 { "scheme", FALSE
, Scheme_functions
, NULL
, Scheme_suffixes
, NULL
},
654 { "tex", FALSE
, TeX_commands
, NULL
, TeX_suffixes
, NULL
},
655 { "texinfo", FALSE
, Texinfo_nodes
, NULL
, Texinfo_suffixes
, NULL
},
656 { "yacc", TRUE
, Yacc_entries
, NULL
, Yacc_suffixes
, NULL
},
657 { "auto", FALSE
, NULL
}, /* default guessing scheme */
658 { "none", FALSE
, just_read_file
}, /* regexp matching only */
659 { NULL
, FALSE
, NULL
} /* end of list */
664 print_language_names ()
669 puts ("\nThese are the currently supported languages, along with the\n\
670 default file names and dot suffixes:");
671 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
673 printf (" %-*s", 10, lang
->name
);
674 if (lang
->filenames
!= NULL
)
675 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
676 printf (" %s", *name
);
677 if (lang
->suffixes
!= NULL
)
678 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
679 printf (" .%s", *ext
);
682 puts ("Where `auto' means use default language for files based on file\n\
683 name suffix, and `none' means only do regexp processing on files.\n\
684 If no language is specified and no matching suffix is found,\n\
685 the first line of the file is read for a sharp-bang (#!) sequence\n\
686 followed by the name of an interpreter. If no such sequence is found,\n\
687 Fortran is tried first; if no tags are found, C is tried next.\n\
688 When parsing any C file, a \"class\" keyword switches to C++.\n\
689 Compressed files are supported using gzip and bzip2.");
693 # define EMACS_NAME "standalone"
696 # define VERSION "version"
701 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
702 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
703 puts ("This program is distributed under the same terms as Emacs");
711 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
713 These are the options accepted by %s.\n", progname
, progname
);
715 puts ("You may use unambiguous abbreviations for the long option names.");
717 puts ("Long option names do not work with this executable, as it is not\n\
718 linked with GNU getopt.");
719 #endif /* LONG_OPTIONS */
720 puts (" A - as file name means read names from stdin (one per line).\n\
721 Absolute names are stored in the output file as they are.\n\
722 Relative ones are stored relative to the output file's directory.\n");
725 puts ("-a, --append\n\
726 Append tag entries to existing tags file.");
728 puts ("--packages-only\n\
729 For Ada files, only generate tags for packages.");
732 puts ("-B, --backward-search\n\
733 Write the search commands for the tag entries using '?', the\n\
734 backward-search command instead of '/', the forward-search command.");
736 /* This option is mostly obsolete, because etags can now automatically
737 detect C++. Retained for backward compatibility and for debugging and
738 experimentation. In principle, we could want to tag as C++ even
739 before any "class" keyword.
741 Treat files whose name suffix defaults to C language as C++ files.");
744 puts ("--declarations\n\
745 In C and derived languages, create tags for function declarations,");
747 puts ("\tand create tags for extern variables if --globals is used.");
750 ("\tand create tags for extern variables unless --no-globals is used.");
753 puts ("-d, --defines\n\
754 Create tag entries for C #define constants and enum constants, too.");
756 puts ("-D, --no-defines\n\
757 Don't create tag entries for C #define constants and enum constants.\n\
758 This makes the tags file smaller.");
761 puts ("-i FILE, --include=FILE\n\
762 Include a note in tag file indicating that, when searching for\n\
763 a tag, one should also consult the tags file FILE after\n\
764 checking the current file.");
766 puts ("-l LANG, --language=LANG\n\
767 Force the following files to be considered as written in the\n\
768 named language up to the next --language=LANG option.");
772 Create tag entries for global variables in some languages.");
774 puts ("--no-globals\n\
775 Do not create tag entries for global variables in some\n\
776 languages. This makes the tags file smaller.");
778 Create tag entries for member variables in some languages.");
781 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
782 Make a tag for each line matching a regular expression pattern\n\
783 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
784 files only. REGEXFILE is a file containing one REGEXP per line.\n\
785 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
786 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
787 puts (" If TAGNAME/ is present, the tags created are named.\n\
788 For example Tcl named tags can be created with:\n\
789 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
790 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
791 `m' means to allow multi-line matches, `s' implies `m' and\n\
792 causes dot to match any character, including newline.");
793 puts ("-R, --no-regex\n\
794 Don't create tags from regexps for the following files.");
795 #endif /* ETAGS_REGEXPS */
796 puts ("-I, --ignore-indentation\n\
797 In C and C++ do not assume that a closing brace in the first\n\
798 column is the final brace of a function or structure definition.");
799 puts ("-o FILE, --output=FILE\n\
800 Write the tags to FILE.");
801 puts ("--parse-stdin=NAME\n\
802 Read from standard input and record tags as belonging to file NAME.");
806 puts ("-t, --typedefs\n\
807 Generate tag entries for C and Ada typedefs.");
808 puts ("-T, --typedefs-and-c++\n\
809 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
810 and C++ member functions.");
814 puts ("-u, --update\n\
815 Update the tag entries for the given files, leaving tag\n\
816 entries for other files in place. Currently, this is\n\
817 implemented by deleting the existing entries for the given\n\
818 files and then rewriting the new entries at the end of the\n\
819 tags file. It is often faster to simply rebuild the entire\n\
820 tag file than to use this.");
824 puts ("-v, --vgrind\n\
825 Generates an index of items intended for human consumption,\n\
826 similar to the output of vgrind. The index is sorted, and\n\
827 gives the page number of each item.");
828 puts ("-w, --no-warn\n\
829 Suppress warning messages about entries defined in multiple\n\
831 puts ("-x, --cxref\n\
832 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
833 The output uses line numbers instead of page numbers, but\n\
834 beyond that the differences are cosmetic; try both to see\n\
838 puts ("-V, --version\n\
839 Print the version of the program.\n\
841 Print this help message.");
843 print_language_names ();
846 puts ("Report bugs to bug-gnu-emacs@gnu.org");
852 #ifdef VMS /* VMS specific functions */
856 /* This is a BUG! ANY arbitrary limit is a BUG!
857 Won't someone please fix this? */
858 #define MAX_FILE_SPEC_LEN 255
861 char body
[MAX_FILE_SPEC_LEN
+ 1];
865 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
866 returning in each successive call the next file name matching the input
867 spec. The function expects that each in_spec passed
868 to it will be processed to completion; in particular, up to and
869 including the call following that in which the last matching name
870 is returned, the function ignores the value of in_spec, and will
871 only start processing a new spec with the following call.
872 If an error occurs, on return out_spec contains the value
873 of in_spec when the error occurred.
875 With each successive file name returned in out_spec, the
876 function's return value is one. When there are no more matching
877 names the function returns zero. If on the first call no file
878 matches in_spec, or there is any other error, -1 is returned.
883 #define OUTSIZE MAX_FILE_SPEC_LEN
889 static long context
= 0;
890 static struct dsc$descriptor_s o
;
891 static struct dsc$descriptor_s i
;
892 static bool pass1
= TRUE
;
899 o
.dsc$a_pointer
= (char *) out
;
900 o
.dsc$w_length
= (short)OUTSIZE
;
901 i
.dsc$a_pointer
= in
;
902 i
.dsc$w_length
= (short)strlen(in
);
903 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
904 i
.dsc$b_class
= DSC$K_CLASS_S
;
905 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
906 o
.dsc$b_class
= DSC$K_CLASS_VS
;
908 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
910 out
->body
[out
->curlen
] = EOS
;
913 else if (status
== RMS$_NMF
)
917 strcpy(out
->body
, in
);
920 lib$
find_file_end(&context
);
926 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
927 name of each file specified by the provided arg expanding wildcards.
930 gfnames (arg
, p_error
)
934 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
936 switch (fn_exp (&filename
, arg
))
940 return filename
.body
;
946 return filename
.body
;
950 #ifndef OLD /* Newer versions of VMS do provide `system'. */
954 error ("%s", "system() function not implemented under VMS");
958 #define VERSION_DELIM ';'
959 char *massage_name (s
)
965 if (*s
== VERSION_DELIM
)
983 unsigned int nincluded_files
;
984 char **included_files
;
986 int current_arg
, file_count
;
987 linebuffer filename_lb
;
996 _fmode
= O_BINARY
; /* all of files are treated as binary files */
1000 nincluded_files
= 0;
1001 included_files
= xnew (argc
, char *);
1005 /* Allocate enough no matter what happens. Overkill, but each one
1007 argbuffer
= xnew (argc
, argument
);
1010 * If etags, always find typedefs and structure tags. Why not?
1011 * Also default to find macro constants, enum constants and
1016 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1021 #ifdef ETAGS_REGEXPS
1022 optstring
= "-r:Rc:";
1023 #endif /* ETAGS_REGEXPS */
1024 #ifndef LONG_OPTIONS
1025 optstring
= optstring
+ 1;
1026 #endif /* LONG_OPTIONS */
1027 optstring
= concat (optstring
,
1029 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1031 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0)) != EOF
)
1035 /* If getopt returns 0, then it has already processed a
1036 long-named option. We should do nothing. */
1040 /* This means that a file name has been seen. Record it. */
1041 argbuffer
[current_arg
].arg_type
= at_filename
;
1042 argbuffer
[current_arg
].what
= optarg
;
1048 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1049 argbuffer
[current_arg
].arg_type
= at_stdin
;
1050 argbuffer
[current_arg
].what
= optarg
;
1054 fatal ("cannot parse standard input more than once", (char *)NULL
);
1055 parsing_stdin
= TRUE
;
1058 /* Common options. */
1059 case 'C': cplusplus
= TRUE
; break;
1060 case 'f': /* for compatibility with old makefiles */
1064 error ("-o option may only be given once.", (char *)NULL
);
1065 suggest_asking_for_help ();
1070 case 'S': /* for backward compatibility */
1071 ignoreindent
= TRUE
;
1075 language
*lang
= get_language_from_langname (optarg
);
1078 argbuffer
[current_arg
].lang
= lang
;
1079 argbuffer
[current_arg
].arg_type
= at_language
;
1085 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1086 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1089 argbuffer
[current_arg
].arg_type
= at_regexp
;
1090 argbuffer
[current_arg
].what
= optarg
;
1094 argbuffer
[current_arg
].arg_type
= at_regexp
;
1095 argbuffer
[current_arg
].what
= NULL
;
1107 case 'a': append_to_tagfile
= TRUE
; break;
1108 case 'D': constantypedefs
= FALSE
; break;
1109 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1111 /* Ctags options. */
1112 case 'B': searchar
= '?'; break;
1113 case 'd': constantypedefs
= TRUE
; break;
1114 case 't': typedefs
= TRUE
; break;
1115 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1116 case 'u': update
= TRUE
; break;
1117 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1118 case 'x': cxref_style
= TRUE
; break;
1119 case 'w': no_warnings
= TRUE
; break;
1121 suggest_asking_for_help ();
1124 for (; optind
< argc
; ++optind
)
1126 argbuffer
[current_arg
].arg_type
= at_filename
;
1127 argbuffer
[current_arg
].what
= argv
[optind
];
1132 if (nincluded_files
== 0 && file_count
== 0)
1134 error ("no input files specified.", (char *)NULL
);
1135 suggest_asking_for_help ();
1138 if (tagfile
== NULL
)
1139 tagfile
= CTAGS
? "tags" : "TAGS";
1140 cwd
= etags_getcwd (); /* the current working directory */
1141 if (cwd
[strlen (cwd
) - 1] != '/')
1144 cwd
= concat (oldcwd
, "/", "");
1147 if (streq (tagfile
, "-"))
1150 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1152 init (); /* set up boolean "functions" */
1154 linebuffer_init (&lb
);
1155 linebuffer_init (&filename_lb
);
1156 linebuffer_init (&filebuf
);
1157 linebuffer_init (&token_name
);
1161 if (streq (tagfile
, "-"))
1165 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1166 doesn't take effect until after `stdout' is already open). */
1167 if (!isatty (fileno (stdout
)))
1168 setmode (fileno (stdout
), O_BINARY
);
1172 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1178 * Loop through files finding functions.
1180 for (i
= 0; i
< current_arg
; ++i
)
1182 static language
*lang
; /* non-NULL if language is forced */
1185 switch (argbuffer
[i
].arg_type
)
1188 lang
= argbuffer
[i
].lang
;
1190 #ifdef ETAGS_REGEXPS
1192 analyse_regex (argbuffer
[i
].what
);
1197 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1201 error ("can't find file %s\n", this_file
);
1206 this_file
= massage_name (this_file
);
1209 this_file
= argbuffer
[i
].what
;
1211 /* Input file named "-" means read file names from stdin
1212 (one per line) and use them. */
1213 if (streq (this_file
, "-"))
1216 fatal ("cannot parse standard input AND read file names from it",
1218 while (readline_internal (&filename_lb
, stdin
) > 0)
1219 process_file_name (filename_lb
.buffer
, lang
);
1222 process_file_name (this_file
, lang
);
1228 this_file
= argbuffer
[i
].what
;
1229 process_file (stdin
, this_file
, lang
);
1234 #ifdef ETAGS_REGEXPS
1236 #endif /* ETAGS_REGEXPS */
1238 free (filebuf
.buffer
);
1239 free (token_name
.buffer
);
1241 if (!CTAGS
|| cxref_style
)
1243 put_entries (nodehead
); /* write the remainig tags (ETAGS) */
1244 free_tree (nodehead
);
1250 /* Output file entries that have no tags. */
1251 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1253 fprintf (tagf
, "\f\n%s,0\n", fdp
->taggedfname
);
1255 while (nincluded_files
-- > 0)
1256 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1259 if (fclose (tagf
) == EOF
)
1267 for (i
= 0; i
< current_arg
; ++i
)
1269 switch (argbuffer
[i
].arg_type
)
1275 continue; /* the for loop */
1278 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1279 tagfile
, argbuffer
[i
].what
, tagfile
);
1280 if (system (cmd
) != GOOD
)
1281 fatal ("failed to execute shell command", (char *)NULL
);
1283 append_to_tagfile
= TRUE
;
1286 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1289 put_entries (nodehead
); /* write all the tags (CTAGS) */
1290 free_tree (nodehead
);
1292 if (fclose (tagf
) == EOF
)
1297 char cmd
[2*BUFSIZ
+10];
1298 sprintf (cmd
, "sort -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1299 exit (system (cmd
));
1306 * Return a compressor given the file name. If EXTPTR is non-zero,
1307 * return a pointer into FILE where the compressor-specific
1308 * extension begins. If no compressor is found, NULL is returned
1309 * and EXTPTR is not significant.
1310 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1313 get_compressor_from_suffix (file
, extptr
)
1318 char *slash
, *suffix
;
1320 /* This relies on FN to be after canonicalize_filename,
1321 so we don't need to consider backslashes on DOS_NT. */
1322 slash
= etags_strrchr (file
, '/');
1323 suffix
= etags_strrchr (file
, '.');
1324 if (suffix
== NULL
|| suffix
< slash
)
1329 /* Let those poor souls who live with DOS 8+3 file name limits get
1330 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1331 Only the first do loop is run if not MSDOS */
1334 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1335 if (streq (compr
->suffix
, suffix
))
1338 break; /* do it only once: not really a loop */
1341 } while (*suffix
!= '\0');
1348 * Return a language given the name.
1351 get_language_from_langname (name
)
1357 error ("empty language name", (char *)NULL
);
1360 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1361 if (streq (name
, lang
->name
))
1363 error ("unknown language \"%s\"", name
);
1371 * Return a language given the interpreter name.
1374 get_language_from_interpreter (interpreter
)
1380 if (interpreter
== NULL
)
1382 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1383 if (lang
->interpreters
!= NULL
)
1384 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1385 if (streq (*iname
, interpreter
))
1394 * Return a language given the file name.
1397 get_language_from_filename (file
, case_sensitive
)
1399 bool case_sensitive
;
1402 char **name
, **ext
, *suffix
;
1404 /* Try whole file name first. */
1405 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1406 if (lang
->filenames
!= NULL
)
1407 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1408 if ((case_sensitive
)
1409 ? streq (*name
, file
)
1410 : strcaseeq (*name
, file
))
1413 /* If not found, try suffix after last dot. */
1414 suffix
= etags_strrchr (file
, '.');
1418 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1419 if (lang
->suffixes
!= NULL
)
1420 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1421 if ((case_sensitive
)
1422 ? streq (*ext
, suffix
)
1423 : strcaseeq (*ext
, suffix
))
1430 * This routine is called on each file argument.
1433 process_file_name (file
, lang
)
1437 struct stat stat_buf
;
1441 char *compressed_name
, *uncompressed_name
;
1442 char *ext
, *real_name
;
1445 canonicalize_filename (file
);
1446 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1448 error ("skipping inclusion of %s in self.", file
);
1451 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1453 compressed_name
= NULL
;
1454 real_name
= uncompressed_name
= savestr (file
);
1458 real_name
= compressed_name
= savestr (file
);
1459 uncompressed_name
= savenstr (file
, ext
- file
);
1462 /* If the canonicalized uncompressed name
1463 has already been dealt with, skip it silently. */
1464 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1466 assert (fdp
->infname
!= NULL
);
1467 if (streq (uncompressed_name
, fdp
->infname
))
1471 if (stat (real_name
, &stat_buf
) != 0)
1473 /* Reset real_name and try with a different name. */
1475 if (compressed_name
!= NULL
) /* try with the given suffix */
1477 if (stat (uncompressed_name
, &stat_buf
) == 0)
1478 real_name
= uncompressed_name
;
1480 else /* try all possible suffixes */
1482 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1484 compressed_name
= concat (file
, ".", compr
->suffix
);
1485 if (stat (compressed_name
, &stat_buf
) != 0)
1489 char *suf
= compressed_name
+ strlen (file
);
1490 size_t suflen
= strlen (compr
->suffix
) + 1;
1491 for ( ; suf
[1]; suf
++, suflen
--)
1493 memmove (suf
, suf
+ 1, suflen
);
1494 if (stat (compressed_name
, &stat_buf
) == 0)
1496 real_name
= compressed_name
;
1500 if (real_name
!= NULL
)
1503 free (compressed_name
);
1504 compressed_name
= NULL
;
1508 real_name
= compressed_name
;
1513 if (real_name
== NULL
)
1518 } /* try with a different name */
1520 if (!S_ISREG (stat_buf
.st_mode
))
1522 error ("skipping %s: it is not a regular file.", real_name
);
1525 if (real_name
== compressed_name
)
1527 char *cmd
= concat (compr
->command
, " ", real_name
);
1528 inf
= (FILE *) popen (cmd
, "r");
1532 inf
= fopen (real_name
, "r");
1539 process_file (inf
, uncompressed_name
, lang
);
1541 if (real_name
== compressed_name
)
1542 retval
= pclose (inf
);
1544 retval
= fclose (inf
);
1549 if (compressed_name
) free (compressed_name
);
1550 if (uncompressed_name
) free (uncompressed_name
);
1557 process_file (fh
, fn
, lang
)
1562 static const fdesc emptyfdesc
;
1565 /* Create a new input file description entry. */
1566 fdp
= xnew (1, fdesc
);
1569 fdp
->infname
= savestr (fn
);
1571 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1572 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1573 if (filename_is_absolute (fn
))
1575 /* An absolute file name. Canonicalize it. */
1576 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1580 /* A file name relative to cwd. Make it relative
1581 to the directory of the tags file. */
1582 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1584 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1586 fdp
->written
= FALSE
; /* not written on tags file yet */
1589 curfdp
= fdhead
; /* the current file description */
1593 /* If not Ctags, and if this is not metasource and if it contained no #line
1594 directives, we can write the tags and free all nodes pointing to
1597 && curfdp
->usecharno
/* no #line directives in this file */
1598 && !curfdp
->lang
->metasource
)
1602 /* Look for the head of the sublist relative to this file. See add_node
1603 for the structure of the node tree. */
1605 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1606 if (np
->fdp
== curfdp
)
1609 /* If we generated tags for this file, write and delete them. */
1612 /* This is the head of the last sublist, if any. The following
1613 instructions depend on this being true. */
1614 assert (np
->left
== NULL
);
1616 assert (fdhead
== curfdp
);
1617 assert (last_node
->fdp
== curfdp
);
1618 put_entries (np
); /* write tags for file curfdp->taggedfname */
1619 free_tree (np
); /* remove the written nodes */
1621 nodehead
= NULL
; /* no nodes left */
1623 prev
->left
= NULL
; /* delete the pointer to the sublist */
1629 * This routine sets up the boolean pseudo-functions which work
1630 * by setting boolean flags dependent upon the corresponding character.
1631 * Every char which is NOT in that string is not a white char. Therefore,
1632 * all of the array "_wht" is set to FALSE, and then the elements
1633 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1634 * of a char is TRUE if it is the string "white", else FALSE.
1642 for (i
= 0; i
< CHARS
; i
++)
1643 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1644 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1645 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1646 notinname('\0') = notinname('\n');
1647 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1648 begtoken('\0') = begtoken('\n');
1649 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1650 intoken('\0') = intoken('\n');
1651 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1652 endtoken('\0') = endtoken('\n');
1656 * This routine opens the specified file and calls the function
1657 * which finds the function and type definitions.
1664 language
*lang
= curfdp
->lang
;
1665 Lang_function
*parser
= NULL
;
1667 /* If user specified a language, use it. */
1668 if (lang
!= NULL
&& lang
->function
!= NULL
)
1670 parser
= lang
->function
;
1673 /* Else try to guess the language given the file name. */
1676 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1677 if (lang
!= NULL
&& lang
->function
!= NULL
)
1679 curfdp
->lang
= lang
;
1680 parser
= lang
->function
;
1684 /* Else look for sharp-bang as the first two characters. */
1686 && readline_internal (&lb
, inf
) > 0
1688 && lb
.buffer
[0] == '#'
1689 && lb
.buffer
[1] == '!')
1693 /* Set lp to point at the first char after the last slash in the
1694 line or, if no slashes, at the first nonblank. Then set cp to
1695 the first successive blank and terminate the string. */
1696 lp
= etags_strrchr (lb
.buffer
+2, '/');
1700 lp
= skip_spaces (lb
.buffer
+ 2);
1701 cp
= skip_non_spaces (lp
);
1704 if (strlen (lp
) > 0)
1706 lang
= get_language_from_interpreter (lp
);
1707 if (lang
!= NULL
&& lang
->function
!= NULL
)
1709 curfdp
->lang
= lang
;
1710 parser
= lang
->function
;
1715 /* We rewind here, even if inf may be a pipe. We fail if the
1716 length of the first line is longer than the pipe block size,
1717 which is unlikely. */
1720 /* Else try to guess the language given the case insensitive file name. */
1723 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1724 if (lang
!= NULL
&& lang
->function
!= NULL
)
1726 curfdp
->lang
= lang
;
1727 parser
= lang
->function
;
1731 /* Else try Fortran or C. */
1734 node
*old_last_node
= last_node
;
1736 curfdp
->lang
= get_language_from_langname ("fortran");
1739 if (old_last_node
== last_node
)
1740 /* No Fortran entries found. Try C. */
1742 /* We do not tag if rewind fails.
1743 Only the file name will be recorded in the tags file. */
1745 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1751 if (!no_line_directive
1752 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1753 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1754 file, or anyway we parsed a file that is automatically generated from
1755 this one. If this is the case, the bingo.c file contained #line
1756 directives that generated tags pointing to this file. Let's delete
1757 them all before parsing this file, which is the real source. */
1759 fdesc
**fdpp
= &fdhead
;
1760 while (*fdpp
!= NULL
)
1762 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1763 /* We found one of those! We must delete both the file description
1764 and all tags referring to it. */
1766 fdesc
*badfdp
= *fdpp
;
1768 /* Delete the tags referring to badfdp->taggedfname
1769 that were obtained from badfdp->infname. */
1770 invalidate_nodes (badfdp
, &nodehead
);
1772 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1773 free_fdesc (badfdp
);
1776 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1779 assert (parser
!= NULL
);
1781 /* Generic initialisations before reading from file. */
1782 linebuffer_setlen (&filebuf
, 0); /* reset the file buffer */
1784 /* Generic initialisations before parsing file with readline. */
1785 lineno
= 0; /* reset global line number */
1786 charno
= 0; /* reset global char number */
1787 linecharno
= 0; /* reset global char number of line start */
1791 #ifdef ETAGS_REGEXPS
1792 regex_tag_multiline ();
1793 #endif /* ETAGS_REGEXPS */
1798 * Check whether an implicitly named tag should be created,
1799 * then call `pfnote'.
1800 * NAME is a string that is internally copied by this function.
1802 * TAGS format specification
1803 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1804 * The following is explained in some more detail in etc/ETAGS.EBNF.
1806 * make_tag creates tags with "implicit tag names" (unnamed tags)
1807 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
1808 * 1. NAME does not contain any of the characters in NONAM;
1809 * 2. LINESTART contains name as either a rightmost, or rightmost but
1810 * one character, substring;
1811 * 3. the character, if any, immediately before NAME in LINESTART must
1812 * be a character in NONAM;
1813 * 4. the character, if any, immediately after NAME in LINESTART must
1814 * also be a character in NONAM.
1816 * The implementation uses the notinname() macro, which recognises the
1817 * characters stored in the string `nonam'.
1818 * etags.el needs to use the same characters that are in NONAM.
1821 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1822 char *name
; /* tag name, or NULL if unnamed */
1823 int namelen
; /* tag length */
1824 bool is_func
; /* tag is a function */
1825 char *linestart
; /* start of the line where tag is */
1826 int linelen
; /* length of the line where tag is */
1827 int lno
; /* line number */
1828 long cno
; /* character number */
1830 bool named
= (name
!= NULL
&& namelen
> 0);
1832 if (!CTAGS
&& named
) /* maybe set named to false */
1833 /* Let's try to make an implicit tag name, that is, create an unnamed tag
1834 such that etags.el can guess a name from it. */
1837 register char *cp
= name
;
1839 for (i
= 0; i
< namelen
; i
++)
1840 if (notinname (*cp
++))
1842 if (i
== namelen
) /* rule #1 */
1844 cp
= linestart
+ linelen
- namelen
;
1845 if (notinname (linestart
[linelen
-1]))
1846 cp
-= 1; /* rule #4 */
1847 if (cp
>= linestart
/* rule #2 */
1849 || notinname (cp
[-1])) /* rule #3 */
1850 && strneq (name
, cp
, namelen
)) /* rule #2 */
1851 named
= FALSE
; /* use implicit tag name */
1856 name
= savenstr (name
, namelen
);
1859 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
1864 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1865 char *name
; /* tag name, or NULL if unnamed */
1866 bool is_func
; /* tag is a function */
1867 char *linestart
; /* start of the line where tag is */
1868 int linelen
; /* length of the line where tag is */
1869 int lno
; /* line number */
1870 long cno
; /* character number */
1874 assert (name
== NULL
|| name
[0] != '\0');
1875 if (CTAGS
&& name
== NULL
)
1878 np
= xnew (1, node
);
1880 /* If ctags mode, change name "main" to M<thisfilename>. */
1881 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1883 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
1884 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
1885 fp
= etags_strrchr (np
->name
, '.');
1886 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
1892 np
->been_warned
= FALSE
;
1894 np
->is_func
= is_func
;
1896 if (np
->fdp
->usecharno
)
1897 /* Our char numbers are 0-base, because of C language tradition?
1898 ctags compatibility? old versions compatibility? I don't know.
1899 Anyway, since emacs's are 1-base we expect etags.el to take care
1900 of the difference. If we wanted to have 1-based numbers, we would
1901 uncomment the +1 below. */
1902 np
->cno
= cno
/* + 1 */ ;
1904 np
->cno
= invalidcharno
;
1905 np
->left
= np
->right
= NULL
;
1906 if (CTAGS
&& !cxref_style
)
1908 if (strlen (linestart
) < 50)
1909 np
->regex
= concat (linestart
, "$", "");
1911 np
->regex
= savenstr (linestart
, 50);
1914 np
->regex
= savenstr (linestart
, linelen
);
1916 add_node (np
, &nodehead
);
1921 * recurse on left children, iterate on right children.
1929 register node
*node_right
= np
->right
;
1930 free_tree (np
->left
);
1931 if (np
->name
!= NULL
)
1941 * delete a file description
1945 register fdesc
*fdp
;
1947 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
1948 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
1949 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
1950 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
1951 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
1957 * Adds a node to the tree of nodes. In etags mode, sort by file
1958 * name. In ctags mode, sort by tag name. Make no attempt at
1961 * add_node is the only function allowed to add nodes, so it can
1965 add_node (np
, cur_node_p
)
1966 node
*np
, **cur_node_p
;
1969 register node
*cur_node
= *cur_node_p
;
1971 if (cur_node
== NULL
)
1981 /* For each file name, tags are in a linked sublist on the right
1982 pointer. The first tags of different files are a linked list
1983 on the left pointer. last_node points to the end of the last
1985 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
1987 /* Let's use the same sublist as the last added node. */
1988 assert (last_node
->right
== NULL
);
1989 last_node
->right
= np
;
1992 else if (cur_node
->fdp
== np
->fdp
)
1994 /* Scanning the list we found the head of a sublist which is
1995 good for us. Let's scan this sublist. */
1996 add_node (np
, &cur_node
->right
);
1999 /* The head of this sublist is not good for us. Let's try the
2001 add_node (np
, &cur_node
->left
);
2002 } /* if ETAGS mode */
2007 dif
= strcmp (np
->name
, cur_node
->name
);
2010 * If this tag name matches an existing one, then
2011 * do not add the node, but maybe print a warning.
2015 if (np
->fdp
== cur_node
->fdp
)
2019 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
2020 np
->fdp
->infname
, lineno
, np
->name
);
2021 fprintf (stderr
, "Second entry ignored\n");
2024 else if (!cur_node
->been_warned
&& !no_warnings
)
2028 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2029 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2030 cur_node
->been_warned
= TRUE
;
2035 /* Actually add the node */
2036 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2037 } /* if CTAGS mode */
2041 * invalidate_nodes ()
2042 * Scan the node tree and invalidate all nodes pointing to the
2043 * given file description (CTAGS case) or free them (ETAGS case).
2046 invalidate_nodes (badfdp
, npp
)
2057 if (np
->left
!= NULL
)
2058 invalidate_nodes (badfdp
, &np
->left
);
2059 if (np
->fdp
== badfdp
)
2061 if (np
->right
!= NULL
)
2062 invalidate_nodes (badfdp
, &np
->right
);
2066 assert (np
->fdp
!= NULL
);
2067 if (np
->fdp
== badfdp
)
2069 *npp
= np
->left
; /* detach the sublist from the list */
2070 np
->left
= NULL
; /* isolate it */
2071 free_tree (np
); /* free it */
2072 invalidate_nodes (badfdp
, npp
);
2075 invalidate_nodes (badfdp
, &np
->left
);
2080 static int total_size_of_entries
__P((node
*));
2081 static int number_len
__P((long));
2083 /* Length of a non-negative number's decimal representation. */
2089 while ((num
/= 10) > 0)
2095 * Return total number of characters that put_entries will output for
2096 * the nodes in the linked list at the right of the specified node.
2097 * This count is irrelevant with etags.el since emacs 19.34 at least,
2098 * but is still supplied for backward compatibility.
2101 total_size_of_entries (np
)
2104 register int total
= 0;
2106 for (; np
!= NULL
; np
= np
->right
)
2109 total
+= strlen (np
->regex
) + 1; /* pat\177 */
2110 if (np
->name
!= NULL
)
2111 total
+= strlen (np
->name
) + 1; /* name\001 */
2112 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2113 if (np
->cno
!= invalidcharno
) /* cno */
2114 total
+= number_len (np
->cno
);
2115 total
+= 1; /* newline */
2126 static fdesc
*fdp
= NULL
;
2131 /* Output subentries that precede this one */
2133 put_entries (np
->left
);
2135 /* Output this entry */
2144 fprintf (tagf
, "\f\n%s,%d\n",
2145 fdp
->taggedfname
, total_size_of_entries (np
));
2146 fdp
->written
= TRUE
;
2148 fputs (np
->regex
, tagf
);
2149 fputc ('\177', tagf
);
2150 if (np
->name
!= NULL
)
2152 fputs (np
->name
, tagf
);
2153 fputc ('\001', tagf
);
2155 fprintf (tagf
, "%d,", np
->lno
);
2156 if (np
->cno
!= invalidcharno
)
2157 fprintf (tagf
, "%ld", np
->cno
);
2163 if (np
->name
== NULL
)
2164 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2169 fprintf (stdout
, "%s %s %d\n",
2170 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2172 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2173 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->regex
);
2177 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2180 { /* function or #define macro with args */
2181 putc (searchar
, tagf
);
2184 for (sp
= np
->regex
; *sp
; sp
++)
2186 if (*sp
== '\\' || *sp
== searchar
)
2190 putc (searchar
, tagf
);
2193 { /* anything else; text pattern inadequate */
2194 fprintf (tagf
, "%d", np
->lno
);
2199 } /* if this node contains a valid tag */
2201 /* Output subentries that follow this one */
2202 put_entries (np
->right
);
2204 put_entries (np
->left
);
2209 #define C_EXT 0x00fff /* C extensions */
2210 #define C_PLAIN 0x00000 /* C */
2211 #define C_PLPL 0x00001 /* C++ */
2212 #define C_STAR 0x00003 /* C* */
2213 #define C_JAVA 0x00005 /* JAVA */
2214 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2215 #define YACC 0x10000 /* yacc file */
2218 * The C symbol tables.
2223 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2228 st_C_class
, st_C_template
,
2229 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
2232 static unsigned int hash
__P((const char *, unsigned int));
2233 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2234 static enum sym_type C_symtype
__P((char *, int, int));
2236 /* Feed stuff between (but not including) %[ and %] lines to:
2237 gperf -c -k 1,3 -o -p -r -t
2239 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2243 while, 0, st_C_ignore
2244 switch, 0, st_C_ignore
2245 return, 0, st_C_ignore
2246 @interface, 0, st_C_objprot
2247 @protocol, 0, st_C_objprot
2248 @implementation,0, st_C_objimpl
2249 @end, 0, st_C_objend
2250 import, C_JAVA, st_C_ignore
2251 package, C_JAVA, st_C_ignore
2252 friend, C_PLPL, st_C_ignore
2253 extends, C_JAVA, st_C_javastruct
2254 implements, C_JAVA, st_C_javastruct
2255 interface, C_JAVA, st_C_struct
2256 class, 0, st_C_class
2257 namespace, C_PLPL, st_C_struct
2258 domain, C_STAR, st_C_struct
2259 union, 0, st_C_struct
2260 struct, 0, st_C_struct
2261 extern, 0, st_C_extern
2263 typedef, 0, st_C_typedef
2264 define, 0, st_C_define
2265 operator, C_PLPL, st_C_operator
2266 template, 0, st_C_template
2267 bool, C_PLPL, st_C_typespec
2268 long, 0, st_C_typespec
2269 short, 0, st_C_typespec
2270 int, 0, st_C_typespec
2271 char, 0, st_C_typespec
2272 float, 0, st_C_typespec
2273 double, 0, st_C_typespec
2274 signed, 0, st_C_typespec
2275 unsigned, 0, st_C_typespec
2276 auto, 0, st_C_typespec
2277 void, 0, st_C_typespec
2278 static, 0, st_C_typespec
2279 const, 0, st_C_typespec
2280 volatile, 0, st_C_typespec
2281 explicit, C_PLPL, st_C_typespec
2282 mutable, C_PLPL, st_C_typespec
2283 typename, C_PLPL, st_C_typespec
2284 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2285 DEFUN, 0, st_C_gnumacro
2286 SYSCALL, 0, st_C_gnumacro
2287 ENTRY, 0, st_C_gnumacro
2288 PSEUDO, 0, st_C_gnumacro
2289 # These are defined inside C functions, so currently they are not met.
2290 # EXFUN used in glibc, DEFVAR_* in emacs.
2291 #EXFUN, 0, st_C_gnumacro
2292 #DEFVAR_, 0, st_C_gnumacro
2294 and replace lines between %< and %> with its output,
2295 then make in_word_set and C_stab_entry static. */
2297 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2298 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2299 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2301 #define TOTAL_KEYWORDS 47
2302 #define MIN_WORD_LENGTH 2
2303 #define MAX_WORD_LENGTH 15
2304 #define MIN_HASH_VALUE 18
2305 #define MAX_HASH_VALUE 138
2306 /* maximum key range = 121, duplicates = 0 */
2313 register const char *str
;
2314 register unsigned int len
;
2316 static unsigned char asso_values
[] =
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, 139, 139, 139, 139,
2321 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2322 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2323 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2324 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2325 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2326 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2327 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2328 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2329 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2330 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2331 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2332 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2333 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2334 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2335 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2336 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2337 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2338 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2339 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2340 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2341 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2342 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2343 139, 139, 139, 139, 139, 139
2345 register int hval
= len
;
2351 hval
+= asso_values
[(unsigned char)str
[2]];
2354 hval
+= asso_values
[(unsigned char)str
[0]];
2363 static struct C_stab_entry
*
2364 in_word_set (str
, len
)
2365 register const char *str
;
2366 register unsigned int len
;
2368 static struct C_stab_entry wordlist
[] =
2370 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2371 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2372 {"if", 0, st_C_ignore
},
2373 {""}, {""}, {""}, {""},
2374 {"int", 0, st_C_typespec
},
2376 {"void", 0, st_C_typespec
},
2378 {"interface", C_JAVA
, st_C_struct
},
2380 {"SYSCALL", 0, st_C_gnumacro
},
2382 {"return", 0, st_C_ignore
},
2383 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2384 {"while", 0, st_C_ignore
},
2385 {"auto", 0, st_C_typespec
},
2386 {""}, {""}, {""}, {""}, {""}, {""},
2387 {"float", 0, st_C_typespec
},
2388 {"typedef", 0, st_C_typedef
},
2389 {"typename", C_PLPL
, st_C_typespec
},
2391 {"friend", C_PLPL
, st_C_ignore
},
2392 {"volatile", 0, st_C_typespec
},
2394 {"for", 0, st_C_ignore
},
2395 {"const", 0, st_C_typespec
},
2396 {"import", C_JAVA
, st_C_ignore
},
2398 {"define", 0, st_C_define
},
2399 {"long", 0, st_C_typespec
},
2400 {"implements", C_JAVA
, st_C_javastruct
},
2401 {"signed", 0, st_C_typespec
},
2403 {"extern", 0, st_C_extern
},
2404 {"extends", C_JAVA
, st_C_javastruct
},
2406 {"mutable", C_PLPL
, st_C_typespec
},
2407 {"template", 0, st_C_template
},
2408 {"short", 0, st_C_typespec
},
2409 {"bool", C_PLPL
, st_C_typespec
},
2410 {"char", 0, st_C_typespec
},
2411 {"class", 0, st_C_class
},
2412 {"operator", C_PLPL
, st_C_operator
},
2414 {"switch", 0, st_C_ignore
},
2416 {"ENTRY", 0, st_C_gnumacro
},
2418 {"package", C_JAVA
, st_C_ignore
},
2419 {"union", 0, st_C_struct
},
2420 {"@end", 0, st_C_objend
},
2421 {"struct", 0, st_C_struct
},
2422 {"namespace", C_PLPL
, st_C_struct
},
2424 {"domain", C_STAR
, st_C_struct
},
2425 {"@interface", 0, st_C_objprot
},
2426 {"PSEUDO", 0, st_C_gnumacro
},
2427 {"double", 0, st_C_typespec
},
2429 {"@protocol", 0, st_C_objprot
},
2431 {"static", 0, st_C_typespec
},
2433 {"DEFUN", 0, st_C_gnumacro
},
2434 {""}, {""}, {""}, {""},
2435 {"explicit", C_PLPL
, st_C_typespec
},
2436 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2437 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2439 {"enum", 0, st_C_enum
},
2441 {"unsigned", 0, st_C_typespec
},
2442 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2443 {"@implementation",0, st_C_objimpl
}
2446 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2448 register int key
= hash (str
, len
);
2450 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2452 register const char *s
= wordlist
[key
].name
;
2454 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
2455 return &wordlist
[key
];
2462 static enum sym_type
2463 C_symtype (str
, len
, c_ext
)
2468 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2470 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2477 * C functions and variables are recognized using a simple
2478 * finite automaton. fvdef is its state variable.
2482 fvnone
, /* nothing seen */
2483 fdefunkey
, /* Emacs DEFUN keyword seen */
2484 fdefunname
, /* Emacs DEFUN name seen */
2485 foperator
, /* func: operator keyword seen (cplpl) */
2486 fvnameseen
, /* function or variable name seen */
2487 fstartlist
, /* func: just after open parenthesis */
2488 finlist
, /* func: in parameter list */
2489 flistseen
, /* func: after parameter list */
2490 fignore
, /* func: before open brace */
2491 vignore
/* var-like: ignore until ';' */
2494 static bool fvextern
; /* func or var: extern keyword seen; */
2497 * typedefs are recognized using a simple finite automaton.
2498 * typdef is its state variable.
2502 tnone
, /* nothing seen */
2503 tkeyseen
, /* typedef keyword seen */
2504 ttypeseen
, /* defined type seen */
2505 tinbody
, /* inside typedef body */
2506 tend
, /* just before typedef tag */
2507 tignore
/* junk after typedef tag */
2511 * struct-like structures (enum, struct and union) are recognized
2512 * using another simple finite automaton. `structdef' is its state
2517 snone
, /* nothing seen yet,
2518 or in struct body if cblev > 0 */
2519 skeyseen
, /* struct-like keyword seen */
2520 stagseen
, /* struct-like tag seen */
2521 sintemplate
, /* inside template (ignore) */
2522 scolonseen
/* colon seen after struct-like tag */
2526 * When objdef is different from onone, objtag is the name of the class.
2528 static char *objtag
= "<uninited>";
2531 * Yet another little state machine to deal with preprocessor lines.
2535 dnone
, /* nothing seen */
2536 dsharpseen
, /* '#' seen as first char on line */
2537 ddefineseen
, /* '#' and 'define' seen */
2538 dignorerest
/* ignore rest of line */
2542 * State machine for Objective C protocols and implementations.
2543 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2547 onone
, /* nothing seen */
2548 oprotocol
, /* @interface or @protocol seen */
2549 oimplementation
, /* @implementations seen */
2550 otagseen
, /* class name seen */
2551 oparenseen
, /* parenthesis before category seen */
2552 ocatseen
, /* category name seen */
2553 oinbody
, /* in @implementation body */
2554 omethodsign
, /* in @implementation body, after +/- */
2555 omethodtag
, /* after method name */
2556 omethodcolon
, /* after method colon */
2557 omethodparm
, /* after method parameter */
2558 oignore
/* wait for @end */
2563 * Use this structure to keep info about the token read, and how it
2564 * should be tagged. Used by the make_C_tag function to build a tag.
2568 char *line
; /* string containing the token */
2569 int offset
; /* where the token starts in LINE */
2570 int length
; /* token length */
2572 The previous members can be used to pass strings around for generic
2573 purposes. The following ones specifically refer to creating tags. In this
2574 case the token contained here is the pattern that will be used to create a
2577 bool valid
; /* do not create a tag; the token should be
2578 invalidated whenever a state machine is
2579 reset prematurely */
2580 bool named
; /* create a named tag */
2581 int lineno
; /* source line number of tag */
2582 long linepos
; /* source char number of tag */
2583 } token
; /* latest token read */
2586 * Variables and functions for dealing with nested structures.
2587 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2589 static void pushclass_above
__P((int, char *, int));
2590 static void popclass_above
__P((int));
2591 static void write_classname
__P((linebuffer
*, char *qualifier
));
2594 char **cname
; /* nested class names */
2595 int *cblev
; /* nested class curly brace level */
2596 int nl
; /* class nesting level (elements used) */
2597 int size
; /* length of the array */
2598 } cstack
; /* stack for nested declaration tags */
2599 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2600 #define nestlev (cstack.nl)
2601 /* After struct keyword or in struct body, not inside a nested function. */
2602 #define instruct (structdef == snone && nestlev > 0 \
2603 && cblev == cstack.cblev[nestlev-1] + 1)
2606 pushclass_above (cblev
, str
, len
)
2613 popclass_above (cblev
);
2615 if (nl
>= cstack
.size
)
2617 int size
= cstack
.size
*= 2;
2618 xrnew (cstack
.cname
, size
, char *);
2619 xrnew (cstack
.cblev
, size
, int);
2621 assert (nl
== 0 || cstack
.cblev
[nl
-1] < cblev
);
2622 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2623 cstack
.cblev
[nl
] = cblev
;
2628 popclass_above (cblev
)
2633 for (nl
= cstack
.nl
- 1;
2634 nl
>= 0 && cstack
.cblev
[nl
] >= cblev
;
2637 if (cstack
.cname
[nl
] != NULL
)
2638 free (cstack
.cname
[nl
]);
2644 write_classname (cn
, qualifier
)
2649 int qlen
= strlen (qualifier
);
2651 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2655 cn
->buffer
[0] = '\0';
2659 len
= strlen (cstack
.cname
[0]);
2660 linebuffer_setlen (cn
, len
);
2661 strcpy (cn
->buffer
, cstack
.cname
[0]);
2663 for (i
= 1; i
< cstack
.nl
; i
++)
2668 s
= cstack
.cname
[i
];
2673 linebuffer_setlen (cn
, len
);
2674 strncat (cn
->buffer
, qualifier
, qlen
);
2675 strncat (cn
->buffer
, s
, slen
);
2680 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2681 static void make_C_tag
__P((bool));
2685 * checks to see if the current token is at the start of a
2686 * function or variable, or corresponds to a typedef, or
2687 * is a struct/union/enum tag, or #define, or an enum constant.
2689 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2690 * with args. C_EXTP points to which language we are looking at.
2701 consider_token (str
, len
, c
, c_extp
, cblev
, parlev
, is_func_or_var
)
2702 register char *str
; /* IN: token pointer */
2703 register int len
; /* IN: token length */
2704 register int c
; /* IN: first char after the token */
2705 int *c_extp
; /* IN, OUT: C extensions mask */
2706 int cblev
; /* IN: curly brace level */
2707 int parlev
; /* IN: parenthesis level */
2708 bool *is_func_or_var
; /* OUT: function or variable found */
2710 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2711 structtype is the type of the preceding struct-like keyword, and
2712 structcblev is the curly brace level where it has been seen. */
2713 static enum sym_type structtype
;
2714 static int structcblev
;
2715 static enum sym_type toktype
;
2718 toktype
= C_symtype (str
, len
, *c_extp
);
2721 * Advance the definedef state machine.
2726 /* We're not on a preprocessor line. */
2727 if (toktype
== st_C_gnumacro
)
2734 if (toktype
== st_C_define
)
2736 definedef
= ddefineseen
;
2740 definedef
= dignorerest
;
2745 * Make a tag for any macro, unless it is a constant
2746 * and constantypedefs is FALSE.
2748 definedef
= dignorerest
;
2749 *is_func_or_var
= (c
== '(');
2750 if (!*is_func_or_var
&& !constantypedefs
)
2757 error ("internal error: definedef value.", (char *)NULL
);
2766 if (toktype
== st_C_typedef
)
2788 if (structdef
== snone
&& fvdef
== fvnone
)
2807 * This structdef business is NOT invoked when we are ctags and the
2808 * file is plain C. This is because a struct tag may have the same
2809 * name as another tag, and this loses with ctags.
2813 case st_C_javastruct
:
2814 if (structdef
== stagseen
)
2815 structdef
= scolonseen
;
2819 if ((*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2821 && definedef
== dnone
&& structdef
== snone
2822 && typdef
== tnone
&& fvdef
== fvnone
)
2823 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2824 if (toktype
== st_C_template
)
2831 && (typdef
== tkeyseen
2832 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2834 structdef
= skeyseen
;
2835 structtype
= toktype
;
2836 structcblev
= cblev
;
2841 if (structdef
== skeyseen
)
2843 structdef
= stagseen
;
2847 if (typdef
!= tnone
)
2850 /* Detect Objective C constructs. */
2860 objdef
= oimplementation
;
2864 case oimplementation
:
2865 /* Save the class tag for functions or variables defined inside. */
2866 objtag
= savenstr (str
, len
);
2870 /* Save the class tag for categories. */
2871 objtag
= savenstr (str
, len
);
2873 *is_func_or_var
= TRUE
;
2877 *is_func_or_var
= TRUE
;
2884 objdef
= omethodtag
;
2885 linebuffer_setlen (&token_name
, len
);
2886 strncpy (token_name
.buffer
, str
, len
);
2887 token_name
.buffer
[len
] = '\0';
2893 objdef
= omethodparm
;
2898 objdef
= omethodtag
;
2899 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
2900 strncat (token_name
.buffer
, str
, len
);
2905 if (toktype
== st_C_objend
)
2907 /* Memory leakage here: the string pointed by objtag is
2908 never released, because many tests would be needed to
2909 avoid breaking on incorrect input code. The amount of
2910 memory leaked here is the sum of the lengths of the
2918 /* A function, variable or enum constant? */
2942 *is_func_or_var
= TRUE
;
2946 && structdef
== snone
2947 && structtype
== st_C_enum
&& cblev
> structcblev
)
2948 return TRUE
; /* enum constant */
2954 fvdef
= fdefunname
; /* GNU macro */
2955 *is_func_or_var
= TRUE
;
2958 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
2959 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
2964 if (strneq (str
+len
-10, "::operator", 10))
2966 if (*c_extp
& C_AUTO
) /* automatic detection of C++ */
2967 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2969 *is_func_or_var
= TRUE
;
2972 if (cblev
> 0 && !instruct
)
2974 fvdef
= fvnameseen
; /* function or variable */
2975 *is_func_or_var
= TRUE
;
2986 * C_entries often keeps pointers to tokens or lines which are older than
2987 * the line currently read. By keeping two line buffers, and switching
2988 * them at end of line, it is possible to use those pointers.
2996 #define current_lb_is_new (newndx == curndx)
2997 #define switch_line_buffers() (curndx = 1 - curndx)
2999 #define curlb (lbs[curndx].lb)
3000 #define newlb (lbs[newndx].lb)
3001 #define curlinepos (lbs[curndx].linepos)
3002 #define newlinepos (lbs[newndx].linepos)
3004 #define plainc ((c_ext & C_EXT) == C_PLAIN)
3005 #define cplpl (c_ext & C_PLPL)
3006 #define cjava ((c_ext & C_JAVA) == C_JAVA)
3008 #define CNL_SAVE_DEFINEDEF() \
3010 curlinepos = charno; \
3011 readline (&curlb, inf); \
3012 lp = curlb.buffer; \
3019 CNL_SAVE_DEFINEDEF(); \
3020 if (savetoken.valid) \
3022 token = savetoken; \
3023 savetoken.valid = FALSE; \
3025 definedef = dnone; \
3033 /* This function should never be called when token.valid is FALSE, but
3034 we must protect against invalid input or internal errors. */
3035 if (!DEBUG
&& !token
.valid
)
3039 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3040 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3041 else /* this case is optimised away if !DEBUG */
3042 make_tag (concat ("INVALID TOKEN:-->", token_name
.buffer
, ""),
3043 token_name
.len
+ 17, isfun
, token
.line
,
3044 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3046 token
.valid
= FALSE
;
3052 * This routine finds functions, variables, typedefs,
3053 * #define's, enum constants and struct/union/enum definitions in
3054 * C syntax and adds them to the list.
3057 C_entries (c_ext
, inf
)
3058 int c_ext
; /* extension of C */
3059 FILE *inf
; /* input file */
3061 register char c
; /* latest char read; '\0' for end of line */
3062 register char *lp
; /* pointer one beyond the character `c' */
3063 int curndx
, newndx
; /* indices for current and new lb */
3064 register int tokoff
; /* offset in line of start of current token */
3065 register int toklen
; /* length of current token */
3066 char *qualifier
; /* string used to qualify names */
3067 int qlen
; /* length of qualifier */
3068 int cblev
; /* current curly brace level */
3069 int parlev
; /* current parenthesis level */
3070 int typdefcblev
; /* cblev where a typedef struct body begun */
3071 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3072 bool yacc_rules
; /* in the rules part of a yacc file */
3073 struct tok savetoken
; /* token saved during preprocessor handling */
3076 linebuffer_init (&lbs
[0].lb
);
3077 linebuffer_init (&lbs
[1].lb
);
3078 if (cstack
.size
== 0)
3080 cstack
.size
= (DEBUG
) ? 1 : 4;
3082 cstack
.cname
= xnew (cstack
.size
, char *);
3083 cstack
.cblev
= xnew (cstack
.size
, int);
3086 tokoff
= toklen
= typdefcblev
= 0; /* keep compiler quiet */
3087 curndx
= newndx
= 0;
3091 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3092 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3094 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3095 token
.valid
= savetoken
.valid
= FALSE
;
3099 { qualifier
= "."; qlen
= 1; }
3101 { qualifier
= "::"; qlen
= 2; }
3109 /* If we're at the end of the line, the next character is a
3110 '\0'; don't skip it, because it's the thing that tells us
3111 to read the next line. */
3132 /* Newlines inside comments do not end macro definitions in
3134 CNL_SAVE_DEFINEDEF ();
3147 /* Newlines inside strings do not end macro definitions
3148 in traditional cpp, even though compilers don't
3149 usually accept them. */
3150 CNL_SAVE_DEFINEDEF ();
3160 /* Hmmm, something went wrong. */
3189 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3202 else if (/* cplpl && */ *lp
== '/')
3210 if ((c_ext
& YACC
) && *lp
== '%')
3212 /* Entering or exiting rules section in yacc file. */
3214 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3215 typdef
= tnone
; structdef
= snone
;
3216 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3218 yacc_rules
= !yacc_rules
;
3224 if (definedef
== dnone
)
3227 bool cpptoken
= TRUE
;
3229 /* Look back on this line. If all blanks, or nonblanks
3230 followed by an end of comment, this is a preprocessor
3232 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3235 if (*cp
== '*' && *(cp
+1) == '/')
3244 definedef
= dsharpseen
;
3245 } /* if (definedef == dnone) */
3251 /* Consider token only if some involved conditions are satisfied. */
3252 if (typdef
!= tignore
3253 && definedef
!= dignorerest
3255 && structdef
!= sintemplate
3256 && (definedef
!= dnone
3257 || structdef
!= scolonseen
))
3263 if (c
== ':' && *lp
== ':' && begtoken (lp
[1]))
3264 /* This handles :: in the middle,
3265 but not at the beginning of an identifier.
3266 Also, space-separated :: is not recognised. */
3268 if (c_ext
& C_AUTO
) /* automatic detection of C++ */
3269 c_ext
= (c_ext
| C_PLPL
) & ~C_AUTO
;
3273 goto still_in_token
;
3277 bool funorvar
= FALSE
;
3280 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3281 &c_ext
, cblev
, parlev
, &funorvar
))
3283 if (fvdef
== foperator
)
3286 lp
= skip_spaces (lp
-1);
3290 && !iswhite (*lp
) && *lp
!= '(')
3293 toklen
+= lp
- oldlp
;
3295 token
.named
= FALSE
;
3297 && nestlev
> 0 && definedef
== dnone
)
3298 /* in struct body */
3300 write_classname (&token_name
, qualifier
);
3301 linebuffer_setlen (&token_name
,
3302 token_name
.len
+qlen
+toklen
);
3303 strcat (token_name
.buffer
, qualifier
);
3304 strncat (token_name
.buffer
,
3305 newlb
.buffer
+ tokoff
, toklen
);
3308 else if (objdef
== ocatseen
)
3309 /* Objective C category */
3311 int len
= strlen (objtag
) + 2 + toklen
;
3312 linebuffer_setlen (&token_name
, len
);
3313 strcpy (token_name
.buffer
, objtag
);
3314 strcat (token_name
.buffer
, "(");
3315 strncat (token_name
.buffer
,
3316 newlb
.buffer
+ tokoff
, toklen
);
3317 strcat (token_name
.buffer
, ")");
3320 else if (objdef
== omethodtag
3321 || objdef
== omethodparm
)
3322 /* Objective C method */
3326 else if (fvdef
== fdefunname
)
3327 /* GNU DEFUN and similar macros */
3329 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3333 /* Rewrite the tag so that emacs lisp DEFUNs
3334 can be found by their elisp name */
3341 linebuffer_setlen (&token_name
, len
);
3342 strncpy (token_name
.buffer
,
3343 newlb
.buffer
+ off
, len
);
3344 token_name
.buffer
[len
] = '\0';
3347 if (token_name
.buffer
[len
] == '_')
3348 token_name
.buffer
[len
] = '-';
3349 token
.named
= defun
;
3353 linebuffer_setlen (&token_name
, toklen
);
3354 strncpy (token_name
.buffer
,
3355 newlb
.buffer
+ tokoff
, toklen
);
3356 token_name
.buffer
[toklen
] = '\0';
3357 /* Name macros and members. */
3358 token
.named
= (structdef
== stagseen
3359 || typdef
== ttypeseen
3362 && definedef
== dignorerest
)
3364 && definedef
== dnone
3365 && structdef
== snone
3368 token
.lineno
= lineno
;
3369 token
.offset
= tokoff
;
3370 token
.length
= toklen
;
3371 token
.line
= newlb
.buffer
;
3372 token
.linepos
= newlinepos
;
3375 if (definedef
== dnone
3376 && (fvdef
== fvnameseen
3377 || fvdef
== foperator
3378 || structdef
== stagseen
3380 || typdef
== ttypeseen
3381 || objdef
!= onone
))
3383 if (current_lb_is_new
)
3384 switch_line_buffers ();
3386 else if (definedef
!= dnone
3387 || fvdef
== fdefunname
3389 make_C_tag (funorvar
);
3393 } /* if (endtoken (c)) */
3394 else if (intoken (c
))
3400 } /* if (midtoken) */
3401 else if (begtoken (c
))
3412 if (plainc
|| declarations
)
3414 make_C_tag (TRUE
); /* a function */
3422 if (structdef
== stagseen
&& !cjava
)
3424 popclass_above (cblev
);
3432 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3434 tokoff
= lp
- 1 - newlb
.buffer
;
3439 } /* if (begtoken) */
3440 } /* if must look at token */
3443 /* Detect end of line, colon, comma, semicolon and various braces
3444 after having handled a token.*/
3448 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3450 make_C_tag (FALSE
); /* a yacc function */
3453 if (definedef
!= dnone
)
3459 make_C_tag (TRUE
); /* an Objective C class */
3463 objdef
= omethodcolon
;
3464 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3465 strcat (token_name
.buffer
, ":");
3468 if (structdef
== stagseen
)
3470 structdef
= scolonseen
;
3473 /* Should be useless, but may be work as a safety net. */
3474 if (cplpl
&& fvdef
== flistseen
)
3476 make_C_tag (TRUE
); /* a function */
3482 if (definedef
!= dnone
)
3488 make_C_tag (FALSE
); /* a typedef */
3498 if (typdef
== tignore
|| cplpl
)
3502 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3503 || (members
&& instruct
))
3504 make_C_tag (FALSE
); /* a variable */
3507 token
.valid
= FALSE
;
3511 && (typdef
== tnone
|| (typdef
!= tignore
&& instruct
)))
3512 make_C_tag (TRUE
); /* a function declaration */
3518 && cplpl
&& structdef
== stagseen
)
3519 make_C_tag (FALSE
); /* forward declaration */
3521 token
.valid
= FALSE
;
3522 } /* switch (fvdef) */
3528 if (structdef
== stagseen
)
3532 if (definedef
!= dnone
)
3538 make_C_tag (TRUE
); /* an Objective C method */
3554 case fvnameseen
: /* a variable */
3555 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3556 || (members
&& instruct
))
3559 case flistseen
: /* a function */
3560 if ((declarations
&& typdef
== tnone
&& !instruct
)
3561 || (members
&& typdef
!= tignore
&& instruct
))
3563 make_C_tag (TRUE
); /* a function declaration */
3566 else if (!declarations
)
3568 token
.valid
= FALSE
;
3573 if (structdef
== stagseen
)
3577 if (definedef
!= dnone
)
3579 if (structdef
== stagseen
)
3586 make_C_tag (FALSE
); /* a typedef */
3598 if ((members
&& cblev
== 1)
3599 || (globals
&& cblev
== 0
3600 && (!fvextern
|| declarations
)))
3601 make_C_tag (FALSE
); /* a variable */
3610 if (definedef
!= dnone
)
3612 if (objdef
== otagseen
&& parlev
== 0)
3613 objdef
= oparenseen
;
3617 if (typdef
== ttypeseen
3621 /* This handles constructs like:
3622 typedef void OperatorFun (int fun); */
3639 if (definedef
!= dnone
)
3641 if (objdef
== ocatseen
&& parlev
== 1)
3643 make_C_tag (TRUE
); /* an Objective C category */
3657 || typdef
== ttypeseen
))
3660 make_C_tag (FALSE
); /* a typedef */
3663 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3667 if (definedef
!= dnone
)
3669 if (typdef
== ttypeseen
)
3671 /* Whenever typdef is set to tinbody (currently only
3672 here), typdefcblev should be set to cblev. */
3674 typdefcblev
= cblev
;
3679 make_C_tag (TRUE
); /* a function */
3688 make_C_tag (TRUE
); /* an Objective C class */
3693 make_C_tag (TRUE
); /* an Objective C method */
3697 /* Neutralize `extern "C" {' grot. */
3698 if (cblev
== 0 && structdef
== snone
&& nestlev
== 0
3706 case skeyseen
: /* unnamed struct */
3707 pushclass_above (cblev
, NULL
, 0);
3710 case stagseen
: /* named struct or enum */
3711 case scolonseen
: /* a class */
3712 pushclass_above (cblev
, token
.line
+token
.offset
, token
.length
);
3714 make_C_tag (FALSE
); /* a struct or enum */
3720 if (definedef
!= dnone
)
3722 if (fvdef
== fstartlist
)
3724 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3725 token
.valid
= FALSE
;
3729 if (definedef
!= dnone
)
3731 if (!ignoreindent
&& lp
== newlb
.buffer
+ 1)
3734 token
.valid
= FALSE
;
3735 cblev
= 0; /* reset curly brace level if first column */
3736 parlev
= 0; /* also reset paren level, just in case... */
3741 token
.valid
= FALSE
; /* something gone amiss, token unreliable */
3742 popclass_above (cblev
);
3744 /* Only if typdef == tinbody is typdefcblev significant. */
3745 if (typdef
== tinbody
&& cblev
<= typdefcblev
)
3747 assert (cblev
== typdefcblev
);
3752 if (definedef
!= dnone
)
3762 if ((members
&& cblev
== 1)
3763 || (globals
&& cblev
== 0 && (!fvextern
|| declarations
)))
3764 make_C_tag (FALSE
); /* a variable */
3771 if (cplpl
&& structdef
== stagseen
)
3773 structdef
= sintemplate
;
3778 if (structdef
== sintemplate
)
3780 structdef
= stagseen
;
3786 if (objdef
== oinbody
&& cblev
== 0)
3788 objdef
= omethodsign
;
3793 case '#': case '~': case '&': case '%': case '/': case '|':
3794 case '^': case '!': case '.': case '?': case ']':
3795 if (definedef
!= dnone
)
3797 /* These surely cannot follow a function tag in C. */
3810 if (objdef
== otagseen
)
3812 make_C_tag (TRUE
); /* an Objective C class */
3815 /* If a macro spans multiple lines don't reset its state. */
3817 CNL_SAVE_DEFINEDEF ();
3823 } /* while not eof */
3825 free (lbs
[0].lb
.buffer
);
3826 free (lbs
[1].lb
.buffer
);
3830 * Process either a C++ file or a C file depending on the setting
3834 default_C_entries (inf
)
3837 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
3840 /* Always do plain C. */
3842 plain_C_entries (inf
)
3848 /* Always do C++. */
3850 Cplusplus_entries (inf
)
3853 C_entries (C_PLPL
, inf
);
3856 /* Always do Java. */
3861 C_entries (C_JAVA
, inf
);
3869 C_entries (C_STAR
, inf
);
3872 /* Always do Yacc. */
3877 C_entries (YACC
, inf
);
3881 /* Useful macros. */
3882 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3883 for (; /* loop initialization */ \
3884 !feof (file_pointer) /* loop test */ \
3885 && /* instructions at start of loop */ \
3886 (readline (&line_buffer, file_pointer), \
3887 char_pointer = line_buffer.buffer, \
3890 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3891 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3892 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3893 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3896 * Read a file, but do no processing. This is used to do regexp
3897 * matching on files that have no language defined.
3900 just_read_file (inf
)
3903 register char *dummy
;
3905 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
3910 /* Fortran parsing */
3912 static void F_takeprec
__P((void));
3913 static void F_getit
__P((FILE *));
3918 dbp
= skip_spaces (dbp
);
3922 dbp
= skip_spaces (dbp
);
3923 if (strneq (dbp
, "(*)", 3))
3928 if (!ISDIGIT (*dbp
))
3930 --dbp
; /* force failure */
3935 while (ISDIGIT (*dbp
));
3944 dbp
= skip_spaces (dbp
);
3947 readline (&lb
, inf
);
3952 dbp
= skip_spaces (dbp
);
3954 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
3956 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
3958 make_tag (dbp
, cp
-dbp
, TRUE
,
3959 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3964 Fortran_functions (inf
)
3967 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
3970 dbp
++; /* Ratfor escape to fortran */
3971 dbp
= skip_spaces (dbp
);
3974 switch (lowcase (*dbp
))
3977 if (nocase_tail ("integer"))
3981 if (nocase_tail ("real"))
3985 if (nocase_tail ("logical"))
3989 if (nocase_tail ("complex") || nocase_tail ("character"))
3993 if (nocase_tail ("double"))
3995 dbp
= skip_spaces (dbp
);
3998 if (nocase_tail ("precision"))
4004 dbp
= skip_spaces (dbp
);
4007 switch (lowcase (*dbp
))
4010 if (nocase_tail ("function"))
4014 if (nocase_tail ("subroutine"))
4018 if (nocase_tail ("entry"))
4022 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
4024 dbp
= skip_spaces (dbp
);
4025 if (*dbp
== '\0') /* assume un-named */
4026 make_tag ("blockdata", 9, TRUE
,
4027 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
4029 F_getit (inf
); /* look for name */
4040 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.int> (1998)
4043 static void Ada_getit
__P((FILE *, char *));
4045 /* Once we are positioned after an "interesting" keyword, let's get
4046 the real tag value necessary. */
4048 Ada_getit (inf
, name_qualifier
)
4050 char *name_qualifier
;
4058 dbp
= skip_spaces (dbp
);
4060 || (dbp
[0] == '-' && dbp
[1] == '-'))
4062 readline (&lb
, inf
);
4065 switch (lowcase(*dbp
))
4068 if (nocase_tail ("body"))
4070 /* Skipping body of procedure body or package body or ....
4071 resetting qualifier to body instead of spec. */
4072 name_qualifier
= "/b";
4077 /* Skipping type of task type or protected type ... */
4078 if (nocase_tail ("type"))
4085 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4090 dbp
= skip_spaces (dbp
);
4093 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4101 name
= concat (dbp
, name_qualifier
, "");
4103 make_tag (name
, strlen (name
), TRUE
,
4104 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4116 bool inquote
= FALSE
;
4117 bool skip_till_semicolumn
= FALSE
;
4119 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4121 while (*dbp
!= '\0')
4123 /* Skip a string i.e. "abcd". */
4124 if (inquote
|| (*dbp
== '"'))
4126 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4131 continue; /* advance char */
4136 break; /* advance line */
4140 /* Skip comments. */
4141 if (dbp
[0] == '-' && dbp
[1] == '-')
4142 break; /* advance line */
4144 /* Skip character enclosed in single quote i.e. 'a'
4145 and skip single quote starting an attribute i.e. 'Image. */
4154 if (skip_till_semicolumn
)
4157 skip_till_semicolumn
= FALSE
;
4159 continue; /* advance char */
4162 /* Search for beginning of a token. */
4163 if (!begtoken (*dbp
))
4166 continue; /* advance char */
4169 /* We are at the beginning of a token. */
4170 switch (lowcase(*dbp
))
4173 if (!packages_only
&& nocase_tail ("function"))
4174 Ada_getit (inf
, "/f");
4176 break; /* from switch */
4177 continue; /* advance char */
4179 if (!packages_only
&& nocase_tail ("procedure"))
4180 Ada_getit (inf
, "/p");
4181 else if (nocase_tail ("package"))
4182 Ada_getit (inf
, "/s");
4183 else if (nocase_tail ("protected")) /* protected type */
4184 Ada_getit (inf
, "/t");
4186 break; /* from switch */
4187 continue; /* advance char */
4190 if (typedefs
&& !packages_only
&& nocase_tail ("use"))
4192 /* when tagging types, avoid tagging use type Pack.Typename;
4193 for this, we will skip everything till a ; */
4194 skip_till_semicolumn
= TRUE
;
4195 continue; /* advance char */
4199 if (!packages_only
&& nocase_tail ("task"))
4200 Ada_getit (inf
, "/k");
4201 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4203 Ada_getit (inf
, "/t");
4204 while (*dbp
!= '\0')
4208 break; /* from switch */
4209 continue; /* advance char */
4212 /* Look for the end of the token. */
4213 while (!endtoken (*dbp
))
4216 } /* advance char */
4217 } /* advance line */
4222 * Unix and microcontroller assembly tag handling
4223 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4224 * Idea by Bob Weiner, Motorola Inc. (1994)
4232 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4234 /* If first char is alphabetic or one of [_.$], test for colon
4235 following identifier. */
4236 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4238 /* Read past label. */
4240 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4242 if (*cp
== ':' || iswhite (*cp
))
4243 /* Found end of label, so copy it and add it to the table. */
4244 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4245 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4253 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4254 * Perl variable names: /^(my|local).../
4255 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4256 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4257 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4260 Perl_functions (inf
)
4263 char *package
= savestr ("main"); /* current package name */
4266 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4270 if (LOOKING_AT (cp
, "package"))
4273 get_tag (cp
, &package
);
4275 else if (LOOKING_AT (cp
, "sub"))
4280 while (!notinname (*cp
))
4283 continue; /* nothing found */
4284 if ((pos
= etags_strchr (sp
, ':')) != NULL
4285 && pos
< cp
&& pos
[1] == ':')
4286 /* The name is already qualified. */
4287 make_tag (sp
, cp
- sp
, TRUE
,
4288 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4292 char savechar
, *name
;
4296 name
= concat (package
, "::", sp
);
4298 make_tag (name
, strlen(name
), TRUE
,
4299 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4303 else if (globals
) /* only if we are tagging global vars */
4305 /* Skip a qualifier, if any. */
4306 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4307 /* After "my" or "local", but before any following paren or space. */
4308 char *varstart
= cp
;
4310 if (qual
/* should this be removed? If yes, how? */
4311 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4316 while (ISALNUM (*cp
) || *cp
== '_');
4320 /* Should be examining a variable list at this point;
4321 could insist on seeing an open parenthesis. */
4322 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4328 make_tag (varstart
, cp
- varstart
, FALSE
,
4329 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4337 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4338 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4339 * More ideas by seb bacon <seb@jamkit.com> (2002)
4342 Python_functions (inf
)
4347 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4349 cp
= skip_spaces (cp
);
4350 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4353 while (!notinname (*cp
) && *cp
!= ':')
4355 make_tag (name
, cp
- name
, TRUE
,
4356 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4365 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4366 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4367 * - /^[ \t]*define\(\"[^\"]+/
4368 * Only with --members:
4369 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4370 * Idea by Diez B. Roggisch (2001)
4376 register char *cp
, *name
;
4377 bool search_identifier
= FALSE
;
4379 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4381 cp
= skip_spaces (cp
);
4383 if (search_identifier
4386 while (!notinname (*cp
))
4388 make_tag (name
, cp
- name
, TRUE
,
4389 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4390 search_identifier
= FALSE
;
4392 else if (LOOKING_AT (cp
, "function"))
4395 cp
= skip_spaces (cp
+1);
4399 while (!notinname (*cp
))
4401 make_tag (name
, cp
- name
, TRUE
,
4402 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4405 search_identifier
= TRUE
;
4407 else if (LOOKING_AT (cp
, "class"))
4412 while (*cp
!= '\0' && !iswhite (*cp
))
4414 make_tag (name
, cp
- name
, FALSE
,
4415 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4418 search_identifier
= TRUE
;
4420 else if (strneq (cp
, "define", 6)
4421 && (cp
= skip_spaces (cp
+6))
4423 && (*cp
== '"' || *cp
== '\''))
4427 while (*cp
!= quote
&& *cp
!= '\0')
4429 make_tag (name
, cp
- name
, FALSE
,
4430 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4433 && LOOKING_AT (cp
, "var")
4437 while (!notinname(*cp
))
4439 make_tag (name
, cp
- name
, FALSE
,
4440 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4447 * Cobol tag functions
4448 * We could look for anything that could be a paragraph name.
4449 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4450 * Idea by Corny de Souza (1993)
4453 Cobol_paragraphs (inf
)
4456 register char *bp
, *ep
;
4458 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4464 /* If eoln, compiler option or comment ignore whole line. */
4465 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4468 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4471 make_tag (bp
, ep
- bp
, TRUE
,
4472 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4479 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4482 Makefile_targets (inf
)
4487 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4489 if (*bp
== '\t' || *bp
== '#')
4491 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4493 if (*bp
== ':' || (globals
&& *bp
== '='))
4494 make_tag (lb
.buffer
, bp
- lb
.buffer
, TRUE
,
4495 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4502 * Original code by Mosur K. Mohan (1989)
4504 * Locates tags for procedures & functions. Doesn't do any type- or
4505 * var-definitions. It does look for the keyword "extern" or
4506 * "forward" immediately following the procedure statement; if found,
4507 * the tag is skipped.
4510 Pascal_functions (inf
)
4513 linebuffer tline
; /* mostly copied from C_entries */
4515 int save_lineno
, namelen
, taglen
;
4518 bool /* each of these flags is TRUE iff: */
4519 incomment
, /* point is inside a comment */
4520 inquote
, /* point is inside '..' string */
4521 get_tagname
, /* point is after PROCEDURE/FUNCTION
4522 keyword, so next item = potential tag */
4523 found_tag
, /* point is after a potential tag */
4524 inparms
, /* point is within parameter-list */
4525 verify_tag
; /* point has passed the parm-list, so the
4526 next token will determine whether this
4527 is a FORWARD/EXTERN to be ignored, or
4528 whether it is a real tag */
4530 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4531 name
= NULL
; /* keep compiler quiet */
4534 linebuffer_init (&tline
);
4536 incomment
= inquote
= FALSE
;
4537 found_tag
= FALSE
; /* have a proc name; check if extern */
4538 get_tagname
= FALSE
; /* found "procedure" keyword */
4539 inparms
= FALSE
; /* found '(' after "proc" */
4540 verify_tag
= FALSE
; /* check if "extern" is ahead */
4543 while (!feof (inf
)) /* long main loop to get next char */
4546 if (c
== '\0') /* if end of line */
4548 readline (&lb
, inf
);
4552 if (!((found_tag
&& verify_tag
)
4554 c
= *dbp
++; /* only if don't need *dbp pointing
4555 to the beginning of the name of
4556 the procedure or function */
4560 if (c
== '}') /* within { } comments */
4562 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4579 inquote
= TRUE
; /* found first quote */
4581 case '{': /* found open { comment */
4585 if (*dbp
== '*') /* found open (* comment */
4590 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4593 case ')': /* end of parms list */
4598 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4605 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4607 /* Check if this is an "extern" declaration. */
4610 if (lowcase (*dbp
== 'e'))
4612 if (nocase_tail ("extern")) /* superfluous, really! */
4618 else if (lowcase (*dbp
) == 'f')
4620 if (nocase_tail ("forward")) /* check for forward reference */
4626 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4630 make_tag (name
, namelen
, TRUE
,
4631 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4635 if (get_tagname
) /* grab name of proc or fn */
4642 /* Find block name. */
4643 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4646 /* Save all values for later tagging. */
4647 linebuffer_setlen (&tline
, lb
.len
);
4648 strcpy (tline
.buffer
, lb
.buffer
);
4649 save_lineno
= lineno
;
4650 save_lcno
= linecharno
;
4651 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4653 taglen
= cp
- lb
.buffer
+ 1;
4655 dbp
= cp
; /* set dbp to e-o-token */
4656 get_tagname
= FALSE
;
4660 /* And proceed to check for "extern". */
4662 else if (!incomment
&& !inquote
&& !found_tag
)
4664 /* Check for proc/fn keywords. */
4665 switch (lowcase (c
))
4668 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4672 if (nocase_tail ("unction"))
4677 } /* while not eof */
4679 free (tline
.buffer
);
4684 * Lisp tag functions
4685 * look for (def or (DEF, quote or QUOTE
4688 static void L_getit
__P((void));
4693 if (*dbp
== '\'') /* Skip prefix quote */
4695 else if (*dbp
== '(')
4698 /* Try to skip "(quote " */
4699 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4700 /* Ok, then skip "(" before name in (defstruct (foo)) */
4701 dbp
= skip_spaces (dbp
);
4703 get_tag (dbp
, NULL
);
4707 Lisp_functions (inf
)
4710 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4715 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4717 dbp
= skip_non_spaces (dbp
);
4718 dbp
= skip_spaces (dbp
);
4723 /* Check for (foo::defmumble name-defined ... */
4726 while (!notinname (*dbp
) && *dbp
!= ':');
4731 while (*dbp
== ':');
4733 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4735 dbp
= skip_non_spaces (dbp
);
4736 dbp
= skip_spaces (dbp
);
4746 * Postscript tag functions
4747 * Just look for lines where the first character is '/'
4748 * Also look at "defineps" for PSWrap
4750 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4751 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4754 Postscript_functions (inf
)
4757 register char *bp
, *ep
;
4759 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4764 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
4767 make_tag (bp
, ep
- bp
, TRUE
,
4768 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4770 else if (LOOKING_AT (bp
, "defineps"))
4777 * Scheme tag functions
4778 * look for (def... xyzzy
4780 * (def ... ((...(xyzzy ....
4782 * Original code by Ken Haase (1985?)
4786 Scheme_functions (inf
)
4791 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4793 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
4795 bp
= skip_non_spaces (bp
+4);
4796 /* Skip over open parens and white space */
4797 while (notinname (*bp
))
4801 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
4807 /* Find tags in TeX and LaTeX input files. */
4809 /* TEX_toktab is a table of TeX control sequences that define tags.
4810 * Each entry records one such control sequence.
4812 * Original code from who knows whom.
4814 * Stefan Monnier (2002)
4817 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
4819 /* Default set of control sequences to put into TEX_toktab.
4820 The value of environment var TEXTAGS is prepended to this. */
4821 static char *TEX_defenv
= "\
4822 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4823 :part:appendix:entry:index:def\
4824 :newcommand:renewcommand:newenvironment:renewenvironment";
4826 static void TEX_mode
__P((FILE *));
4827 static void TEX_decode_env
__P((char *, char *));
4829 static char TEX_esc
= '\\';
4830 static char TEX_opgrp
= '{';
4831 static char TEX_clgrp
= '}';
4834 * TeX/LaTeX scanning loop.
4843 /* Select either \ or ! as escape character. */
4846 /* Initialize token table once from environment. */
4847 if (TEX_toktab
== NULL
)
4848 TEX_decode_env ("TEXTAGS", TEX_defenv
);
4850 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4852 /* Look at each TEX keyword in line. */
4855 /* Look for a TEX escape. */
4856 while (*cp
++ != TEX_esc
)
4857 if (cp
[-1] == '\0' || cp
[-1] == '%')
4860 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
4861 if (strneq (cp
, key
->buffer
, key
->len
))
4864 int namelen
, linelen
;
4867 cp
= skip_spaces (cp
+ key
->len
);
4868 if (*cp
== TEX_opgrp
)
4874 (!iswhite (*p
) && *p
!= '#' &&
4875 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
4880 if (!opgrp
|| *p
== TEX_clgrp
)
4882 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
4884 linelen
= p
- lb
.buffer
+ 1;
4886 make_tag (cp
, namelen
, TRUE
,
4887 lb
.buffer
, linelen
, lineno
, linecharno
);
4888 goto tex_next_line
; /* We only tag a line once */
4896 #define TEX_LESC '\\'
4897 #define TEX_SESC '!'
4899 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4900 chars accordingly. */
4907 while ((c
= getc (inf
)) != EOF
)
4909 /* Skip to next line if we hit the TeX comment char. */
4913 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
4929 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4930 No attempt is made to correct the situation. */
4934 /* Read environment and prepend it to the default string.
4935 Build token table. */
4937 TEX_decode_env (evarname
, defenv
)
4941 register char *env
, *p
;
4944 /* Append default string to environment. */
4945 env
= getenv (evarname
);
4951 env
= concat (oldenv
, defenv
, "");
4954 /* Allocate a token table */
4955 for (len
= 1, p
= env
; p
;)
4956 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
4958 TEX_toktab
= xnew (len
, linebuffer
);
4960 /* Unpack environment string into token table. Be careful about */
4961 /* zero-length strings (leading ':', "::" and trailing ':') */
4962 for (i
= 0; *env
!= '\0';)
4964 p
= etags_strchr (env
, ':');
4965 if (!p
) /* End of environment string. */
4966 p
= env
+ strlen (env
);
4968 { /* Only non-zero strings. */
4969 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
4970 TEX_toktab
[i
].len
= p
- env
;
4977 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
4978 TEX_toktab
[i
].len
= 0;
4985 /* Texinfo support. Dave Love, Mar. 2000. */
4991 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4992 if (LOOKING_AT (cp
, "@node"))
4995 while (*cp
!= '\0' && *cp
!= ',')
4997 make_tag (start
, cp
- start
, TRUE
,
4998 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5003 /* Similar to LOOKING_AT but does not use notinname, does not skip */
5004 #define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \
5005 (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
5006 && ((cp) += sizeof(kw)-1)) /* skip spaces */
5010 * Contents of <title>, <h1>, <h2>, <h3> are tags.
5011 * Contents of <a name=xxx> are tags with name xxx.
5013 * Francesco Potortì, 2002.
5019 bool getnext
= FALSE
; /* next text outside of HTML tags is a tag */
5020 bool skiptag
= FALSE
; /* skip to the end of the current HTML tag */
5021 bool intag
= FALSE
; /* inside an html tag, looking for ID= */
5022 bool inanchor
= FALSE
; /* when INTAG, is an anchor, look for NAME= */
5026 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5028 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5029 for (;;) /* loop on the same line */
5031 if (skiptag
) /* skip HTML tag */
5033 while (*dbp
!= '\0' && *dbp
!= '>')
5039 continue; /* look on the same line */
5041 break; /* go to next line */
5044 else if (intag
) /* look for "name=" or "id=" */
5046 while (*dbp
!= '\0' && *dbp
!= '>'
5047 && lowcase (*dbp
) != 'n' && lowcase (*dbp
) != 'i')
5050 break; /* go to next line */
5055 continue; /* look on the same line */
5057 if ((inanchor
&& LOOKING_AT_NOCASE (dbp
, "name="))
5058 || LOOKING_AT_NOCASE (dbp
, "id="))
5060 bool quoted
= (dbp
[0] == '"');
5063 for (end
= ++dbp
; *end
!= '\0' && *end
!= '"'; end
++)
5066 for (end
= dbp
; *end
!= '\0' && intoken (*end
); end
++)
5068 linebuffer_setlen (&token_name
, end
- dbp
);
5069 strncpy (token_name
.buffer
, dbp
, end
- dbp
);
5070 token_name
.buffer
[end
- dbp
] = '\0';
5073 intag
= FALSE
; /* we found what we looked for */
5074 skiptag
= TRUE
; /* skip to the end of the tag */
5075 getnext
= TRUE
; /* then grab the text */
5076 continue; /* look on the same line */
5081 else if (getnext
) /* grab next tokens and tag them */
5083 dbp
= skip_spaces (dbp
);
5085 break; /* go to next line */
5089 inanchor
= (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]));
5090 continue; /* look on the same line */
5093 for (end
= dbp
+ 1; *end
!= '\0' && *end
!= '<'; end
++)
5095 make_tag (token_name
.buffer
, token_name
.len
, TRUE
,
5096 dbp
, end
- dbp
, lineno
, linecharno
);
5097 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5099 break; /* go to next line */
5102 else /* look for an interesting HTML tag */
5104 while (*dbp
!= '\0' && *dbp
!= '<')
5107 break; /* go to next line */
5109 if (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]))
5112 continue; /* look on the same line */
5114 else if (LOOKING_AT_NOCASE (dbp
, "<title>")
5115 || LOOKING_AT_NOCASE (dbp
, "<h1>")
5116 || LOOKING_AT_NOCASE (dbp
, "<h2>")
5117 || LOOKING_AT_NOCASE (dbp
, "<h3>"))
5121 continue; /* look on the same line */
5132 * Assumes that the predicate or rule starts at column 0.
5133 * Only the first clause of a predicate or rule is added.
5134 * Original code by Sunichirou Sugou (1989)
5135 * Rewritten by Anders Lindgren (1996)
5137 static int prolog_pr
__P((char *, char *));
5138 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
5139 static int prolog_atom
__P((char *, int));
5142 Prolog_functions (inf
)
5153 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5155 if (cp
[0] == '\0') /* Empty line */
5157 else if (iswhite (cp
[0])) /* Not a predicate */
5159 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
5160 prolog_skip_comment (&lb
, inf
);
5161 else if ((len
= prolog_pr (cp
, last
)) > 0)
5163 /* Predicate or rule. Store the function name so that we
5164 only generate a tag for the first clause. */
5166 last
= xnew(len
+ 1, char);
5167 else if (len
+ 1 > allocated
)
5168 xrnew (last
, len
+ 1, char);
5169 allocated
= len
+ 1;
5170 strncpy (last
, cp
, len
);
5178 prolog_skip_comment (plb
, inf
)
5186 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
5187 if (cp
[0] == '*' && cp
[1] == '/')
5189 readline (plb
, inf
);
5195 * A predicate or rule definition is added if it matches:
5196 * <beginning of line><Prolog Atom><whitespace>(
5197 * or <beginning of line><Prolog Atom><whitespace>:-
5199 * It is added to the tags database if it doesn't match the
5200 * name of the previous clause header.
5202 * Return the size of the name of the predicate or rule, or 0 if no
5208 char *last
; /* Name of last clause. */
5213 pos
= prolog_atom (s
, 0);
5218 pos
= skip_spaces (s
+ pos
) - s
;
5221 || (s
[pos
] == '(' && (pos
+= 1))
5222 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5223 && (last
== NULL
/* save only the first clause */
5224 || len
!= strlen (last
)
5225 || !strneq (s
, last
, len
)))
5227 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5235 * Consume a Prolog atom.
5236 * Return the number of bytes consumed, or -1 if there was an error.
5238 * A prolog atom, in this context, could be one of:
5239 * - An alphanumeric sequence, starting with a lower case letter.
5240 * - A quoted arbitrary string. Single quotes can escape themselves.
5241 * Backslash quotes everything.
5244 prolog_atom (s
, pos
)
5252 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5254 /* The atom is unquoted. */
5256 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5260 return pos
- origpos
;
5262 else if (s
[pos
] == '\'')
5273 pos
++; /* A double quote */
5275 else if (s
[pos
] == '\0')
5276 /* Multiline quoted atoms are ignored. */
5278 else if (s
[pos
] == '\\')
5280 if (s
[pos
+1] == '\0')
5287 return pos
- origpos
;
5295 * Support for Erlang
5297 * Generates tags for functions, defines, and records.
5298 * Assumes that Erlang functions start at column 0.
5299 * Original code by Anders Lindgren (1996)
5301 static int erlang_func
__P((char *, char *));
5302 static void erlang_attribute
__P((char *));
5303 static int erlang_atom
__P((char *));
5306 Erlang_functions (inf
)
5317 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5319 if (cp
[0] == '\0') /* Empty line */
5321 else if (iswhite (cp
[0])) /* Not function nor attribute */
5323 else if (cp
[0] == '%') /* comment */
5325 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5327 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5329 erlang_attribute (cp
);
5332 else if ((len
= erlang_func (cp
, last
)) > 0)
5335 * Function. Store the function name so that we only
5336 * generates a tag for the first clause.
5339 last
= xnew (len
+ 1, char);
5340 else if (len
+ 1 > allocated
)
5341 xrnew (last
, len
+ 1, char);
5342 allocated
= len
+ 1;
5343 strncpy (last
, cp
, len
);
5351 * A function definition is added if it matches:
5352 * <beginning of line><Erlang Atom><whitespace>(
5354 * It is added to the tags database if it doesn't match the
5355 * name of the previous clause header.
5357 * Return the size of the name of the function, or 0 if no function
5361 erlang_func (s
, last
)
5363 char *last
; /* Name of last clause. */
5368 pos
= erlang_atom (s
);
5373 pos
= skip_spaces (s
+ pos
) - s
;
5375 /* Save only the first clause. */
5378 || len
!= (int)strlen (last
)
5379 || !strneq (s
, last
, len
)))
5381 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5390 * Handle attributes. Currently, tags are generated for defines
5393 * They are on the form:
5394 * -define(foo, bar).
5395 * -define(Foo(M, N), M+N).
5396 * -record(graph, {vtab = notable, cyclic = true}).
5399 erlang_attribute (s
)
5404 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5407 int len
= erlang_atom (skip_spaces (cp
));
5409 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5416 * Consume an Erlang atom (or variable).
5417 * Return the number of bytes consumed, or -1 if there was an error.
5425 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5427 /* The atom is unquoted. */
5430 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5432 else if (s
[pos
] == '\'')
5434 for (pos
++; s
[pos
] != '\''; pos
++)
5435 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5436 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5445 #ifdef ETAGS_REGEXPS
5447 static char *scan_separators
__P((char *));
5448 static void add_regex
__P((char *, language
*));
5449 static char *substitute
__P((char *, char *, struct re_registers
*));
5452 * Take a string like "/blah/" and turn it into "blah", verifying
5453 * that the first and last characters are the same, and handling
5454 * quoted separator characters. Actually, stops on the occurrence of
5455 * an unquoted separator. Also process \t, \n, etc. and turn into
5456 * appropriate characters. Works in place. Null terminates name string.
5457 * Returns pointer to terminating separator, or NULL for
5458 * unterminated regexps.
5461 scan_separators (name
)
5465 char *copyto
= name
;
5466 bool quoted
= FALSE
;
5468 for (++name
; *name
!= '\0'; ++name
)
5474 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5475 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5476 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5477 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5478 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5479 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5480 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5481 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5482 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5488 /* Something else is quoted, so preserve the quote. */
5496 else if (*name
== '\\')
5498 else if (*name
== sep
)
5504 name
= NULL
; /* signal unterminated regexp */
5506 /* Terminate copied string. */
5511 /* Look at the argument of --regex or --no-regex and do the right
5512 thing. Same for each line of a regexp file. */
5514 analyse_regex (regex_arg
)
5517 if (regex_arg
== NULL
)
5519 free_regexps (); /* --no-regex: remove existing regexps */
5523 /* A real --regexp option or a line in a regexp file. */
5524 switch (regex_arg
[0])
5526 /* Comments in regexp file or null arg to --regex. */
5532 /* Read a regex file. This is recursive and may result in a
5533 loop, which will stop when the file descriptors are exhausted. */
5537 linebuffer regexbuf
;
5538 char *regexfile
= regex_arg
+ 1;
5540 /* regexfile is a file containing regexps, one per line. */
5541 regexfp
= fopen (regexfile
, "r");
5542 if (regexfp
== NULL
)
5547 linebuffer_init (®exbuf
);
5548 while (readline_internal (®exbuf
, regexfp
) > 0)
5549 analyse_regex (regexbuf
.buffer
);
5550 free (regexbuf
.buffer
);
5555 /* Regexp to be used for a specific language only. */
5559 char *lang_name
= regex_arg
+ 1;
5562 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5565 error ("unterminated language name in regex: %s", regex_arg
);
5569 lang
= get_language_from_langname (lang_name
);
5572 add_regex (cp
, lang
);
5576 /* Regexp to be used for any language. */
5578 add_regex (regex_arg
, NULL
);
5583 /* Separate the regexp pattern, compile it,
5584 and care for optional name and modifiers. */
5586 add_regex (regexp_pattern
, lang
)
5587 char *regexp_pattern
;
5590 static struct re_pattern_buffer zeropattern
;
5591 char sep
, *pat
, *name
, *modifiers
;
5593 struct re_pattern_buffer
*patbuf
;
5596 force_explicit_name
= TRUE
, /* do not use implicit tag names */
5597 ignore_case
= FALSE
, /* case is significant */
5598 multi_line
= FALSE
, /* matches are done one line at a time */
5599 single_line
= FALSE
; /* dot does not match newline */
5602 if (strlen(regexp_pattern
) < 3)
5604 error ("null regexp", (char *)NULL
);
5607 sep
= regexp_pattern
[0];
5608 name
= scan_separators (regexp_pattern
);
5611 error ("%s: unterminated regexp", regexp_pattern
);
5616 error ("null name for regexp \"%s\"", regexp_pattern
);
5619 modifiers
= scan_separators (name
);
5620 if (modifiers
== NULL
) /* no terminating separator --> no name */
5626 modifiers
+= 1; /* skip separator */
5628 /* Parse regex modifiers. */
5629 for (; modifiers
[0] != '\0'; modifiers
++)
5630 switch (modifiers
[0])
5633 if (modifiers
== name
)
5634 error ("forcing explicit tag name but no name, ignoring", NULL
);
5635 force_explicit_name
= TRUE
;
5645 need_filebuf
= TRUE
;
5650 wrongmod
[0] = modifiers
[0];
5652 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
5657 patbuf
= xnew (1, struct re_pattern_buffer
);
5658 *patbuf
= zeropattern
;
5661 static char lc_trans
[CHARS
];
5663 for (i
= 0; i
< CHARS
; i
++)
5664 lc_trans
[i
] = lowcase (i
);
5665 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5669 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
5671 pat
= regexp_pattern
;
5674 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
5676 re_set_syntax (RE_SYNTAX_EMACS
);
5678 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
5683 error ("%s while compiling pattern", err
);
5688 p_head
= xnew (1, regexp
);
5689 p_head
->pattern
= savestr (regexp_pattern
);
5690 p_head
->p_next
= rp
;
5691 p_head
->lang
= lang
;
5692 p_head
->pat
= patbuf
;
5693 p_head
->name
= savestr (name
);
5694 p_head
->error_signaled
= FALSE
;
5695 p_head
->force_explicit_name
= force_explicit_name
;
5696 p_head
->ignore_case
= ignore_case
;
5697 p_head
->multi_line
= multi_line
;
5701 * Do the substitutions indicated by the regular expression and
5705 substitute (in
, out
, regs
)
5707 struct re_registers
*regs
;
5710 int size
, dig
, diglen
;
5713 size
= strlen (out
);
5715 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5716 if (out
[size
- 1] == '\\')
5717 fatal ("pattern error in \"%s\"", out
);
5718 for (t
= etags_strchr (out
, '\\');
5720 t
= etags_strchr (t
+ 2, '\\'))
5724 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5730 /* Allocate space and do the substitutions. */
5732 result
= xnew (size
+ 1, char);
5734 for (t
= result
; *out
!= '\0'; out
++)
5735 if (*out
== '\\' && ISDIGIT (*++out
))
5738 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5739 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5746 assert (t
<= result
+ size
);
5747 assert (t
- result
== (int)strlen (result
));
5752 /* Deallocate all regexps. */
5757 while (p_head
!= NULL
)
5759 rp
= p_head
->p_next
;
5760 free (p_head
->pattern
);
5761 free (p_head
->name
);
5769 * Reads the whole file as a single string from `filebuf' and looks for
5770 * multi-line regular expressions, creating tags on matches.
5771 * readline already dealt with normal regexps.
5773 * Idea by Ben Wing <ben@666.com> (2002).
5776 regex_tag_multiline ()
5778 char *buffer
= filebuf
.buffer
;
5782 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
5786 if (!rp
->multi_line
)
5787 continue; /* skip normal regexps */
5789 /* Generic initialisations before parsing file from memory. */
5790 lineno
= 1; /* reset global line number */
5791 charno
= 0; /* reset global char number */
5792 linecharno
= 0; /* reset global char number of line start */
5794 /* Only use generic regexps or those for the current language. */
5795 if (rp
->lang
!= NULL
&& rp
->lang
!= curfdp
->lang
)
5798 while (match
>= 0 && match
< filebuf
.len
)
5800 match
= re_search (rp
->pat
, buffer
, filebuf
.len
, charno
,
5801 filebuf
.len
- match
, &rp
->regs
);
5806 if (!rp
->error_signaled
)
5808 error ("regexp stack overflow while matching \"%s\"",
5810 rp
->error_signaled
= TRUE
;
5817 if (match
== rp
->regs
.end
[0])
5819 if (!rp
->error_signaled
)
5821 error ("regexp matches the empty string: \"%s\"",
5823 rp
->error_signaled
= TRUE
;
5825 match
= -3; /* exit from while loop */
5829 /* Match occurred. Construct a tag. */
5830 while (charno
< rp
->regs
.end
[0])
5831 if (buffer
[charno
++] == '\n')
5832 lineno
++, linecharno
= charno
;
5834 if (name
[0] == '\0')
5836 else /* make a named tag */
5837 name
= substitute (buffer
, rp
->name
, &rp
->regs
);
5838 if (rp
->force_explicit_name
)
5839 /* Force explicit tag name, if a name is there. */
5840 pfnote (name
, TRUE
, buffer
+ linecharno
,
5841 charno
- linecharno
+ 1, lineno
, linecharno
);
5843 make_tag (name
, strlen (name
), TRUE
, buffer
+ linecharno
,
5844 charno
- linecharno
+ 1, lineno
, linecharno
);
5851 #endif /* ETAGS_REGEXPS */
5858 register int len
= 0;
5860 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
5862 if (*cp
== '\0' && !intoken (dbp
[len
]))
5871 get_tag (bp
, namepp
)
5875 register char *cp
= bp
;
5879 /* Go till you get to white space or a syntactic break */
5880 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
5882 make_tag (bp
, cp
- bp
, TRUE
,
5883 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5887 *namepp
= savenstr (bp
, cp
- bp
);
5891 * Read a line of text from `stream' into `lbp', excluding the
5892 * newline or CR-NL, if any. Return the number of characters read from
5893 * `stream', which is the length of the line including the newline.
5895 * On DOS or Windows we do not count the CR character, if any before the
5896 * NL, in the returned length; this mirrors the behavior of Emacs on those
5897 * platforms (for text files, it translates CR-NL to NL as it reads in the
5900 * If multi-line regular expressions are requested, each line read is
5901 * appended to `filebuf'.
5904 readline_internal (lbp
, stream
)
5906 register FILE *stream
;
5908 char *buffer
= lbp
->buffer
;
5909 register char *p
= lbp
->buffer
;
5910 register char *pend
;
5913 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
5917 register int c
= getc (stream
);
5920 /* We're at the end of linebuffer: expand it. */
5922 xrnew (buffer
, lbp
->size
, char);
5923 p
+= buffer
- lbp
->buffer
;
5924 pend
= buffer
+ lbp
->size
;
5925 lbp
->buffer
= buffer
;
5935 if (p
> buffer
&& p
[-1] == '\r')
5939 /* Assume CRLF->LF translation will be performed by Emacs
5940 when loading this file, so CRs won't appear in the buffer.
5941 It would be cleaner to compensate within Emacs;
5942 however, Emacs does not know how many CRs were deleted
5943 before any given point in the file. */
5958 lbp
->len
= p
- buffer
;
5960 if (need_filebuf
/* we need filebuf for multi-line regexps */
5961 && chars_deleted
> 0) /* not at EOF */
5963 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
5965 /* Expand filebuf. */
5967 xrnew (filebuf
.buffer
, filebuf
.size
, char);
5969 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
5970 filebuf
.len
+= lbp
->len
;
5971 filebuf
.buffer
[filebuf
.len
++] = '\n';
5972 filebuf
.buffer
[filebuf
.len
] = '\0';
5975 return lbp
->len
+ chars_deleted
;
5979 * Like readline_internal, above, but in addition try to match the
5980 * input line against relevant regular expressions and manage #line
5984 readline (lbp
, stream
)
5990 linecharno
= charno
; /* update global char number of line start */
5991 result
= readline_internal (lbp
, stream
); /* read line */
5992 lineno
+= 1; /* increment global line number */
5993 charno
+= result
; /* increment global char number */
5995 /* Honour #line directives. */
5996 if (!no_line_directive
)
5998 static bool discard_until_line_directive
;
6000 /* Check whether this is a #line directive. */
6001 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
6005 if (DEBUG
) start
= 0; /* shut up the compiler */
6006 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
6008 char *endp
= lbp
->buffer
+ start
;
6011 while ((endp
= etags_strchr (endp
, '"')) != NULL
6012 && endp
[-1] == '\\')
6015 /* Ok, this is a real #line directive. Let's deal with it. */
6017 char *taggedabsname
; /* absolute name of original file */
6018 char *taggedfname
; /* name of original file as given */
6019 char *name
; /* temp var */
6021 discard_until_line_directive
= FALSE
; /* found it */
6022 name
= lbp
->buffer
+ start
;
6024 canonicalize_filename (name
); /* for DOS */
6025 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
6026 if (filename_is_absolute (name
)
6027 || filename_is_absolute (curfdp
->infname
))
6028 taggedfname
= savestr (taggedabsname
);
6030 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
6032 if (streq (curfdp
->taggedfname
, taggedfname
))
6033 /* The #line directive is only a line number change. We
6034 deal with this afterwards. */
6037 /* The tags following this #line directive should be
6038 attributed to taggedfname. In order to do this, set
6039 curfdp accordingly. */
6041 fdesc
*fdp
; /* file description pointer */
6043 /* Go look for a file description already set up for the
6044 file indicated in the #line directive. If there is
6045 one, use it from now until the next #line
6047 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6048 if (streq (fdp
->infname
, curfdp
->infname
)
6049 && streq (fdp
->taggedfname
, taggedfname
))
6050 /* If we remove the second test above (after the &&)
6051 then all entries pertaining to the same file are
6052 coalesced in the tags file. If we use it, then
6053 entries pertaining to the same file but generated
6054 from different files (via #line directives) will
6055 go into separate sections in the tags file. These
6056 alternatives look equivalent. The first one
6057 destroys some apparently useless information. */
6063 /* Else, if we already tagged the real file, skip all
6064 input lines until the next #line directive. */
6065 if (fdp
== NULL
) /* not found */
6066 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6067 if (streq (fdp
->infabsname
, taggedabsname
))
6069 discard_until_line_directive
= TRUE
;
6073 /* Else create a new file description and use that from
6074 now on, until the next #line directive. */
6075 if (fdp
== NULL
) /* not found */
6078 fdhead
= xnew (1, fdesc
);
6079 *fdhead
= *curfdp
; /* copy curr. file description */
6081 fdhead
->infname
= savestr (curfdp
->infname
);
6082 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
6083 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
6084 fdhead
->taggedfname
= taggedfname
;
6085 fdhead
->usecharno
= FALSE
;
6086 fdhead
->prop
= NULL
;
6087 fdhead
->written
= FALSE
;
6091 free (taggedabsname
);
6093 readline (lbp
, stream
);
6095 } /* if a real #line directive */
6096 } /* if #line is followed by a a number */
6097 } /* if line begins with "#line " */
6099 /* If we are here, no #line directive was found. */
6100 if (discard_until_line_directive
)
6104 /* Do a tail recursion on ourselves, thus discarding the contents
6105 of the line buffer. */
6106 readline (lbp
, stream
);
6110 discard_until_line_directive
= FALSE
;
6113 } /* if #line directives should be considered */
6115 #ifdef ETAGS_REGEXPS
6121 /* Match against relevant regexps. */
6123 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6125 /* Only use generic regexps or those for the current language.
6126 Also do not use multiline regexps, which is the job of
6127 regex_tag_multiline. */
6128 if ((rp
->lang
!= NULL
&& rp
->lang
!= fdhead
->lang
)
6132 match
= re_match (rp
->pat
, lbp
->buffer
, lbp
->len
, 0, &rp
->regs
);
6137 if (!rp
->error_signaled
)
6139 error ("regexp stack overflow while matching \"%s\"",
6141 rp
->error_signaled
= TRUE
;
6148 /* Empty string matched. */
6149 if (!rp
->error_signaled
)
6151 error ("regexp matches the empty string: \"%s\"", rp
->pattern
);
6152 rp
->error_signaled
= TRUE
;
6156 /* Match occurred. Construct a tag. */
6158 if (name
[0] == '\0')
6160 else /* make a named tag */
6161 name
= substitute (lbp
->buffer
, rp
->name
, &rp
->regs
);
6162 if (rp
->force_explicit_name
)
6163 /* Force explicit tag name, if a name is there. */
6164 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
6166 make_tag (name
, strlen (name
), TRUE
,
6167 lbp
->buffer
, match
, lineno
, linecharno
);
6172 #endif /* ETAGS_REGEXPS */
6177 * Return a pointer to a space of size strlen(cp)+1 allocated
6178 * with xnew where the string CP has been copied.
6184 return savenstr (cp
, strlen (cp
));
6188 * Return a pointer to a space of size LEN+1 allocated with xnew where
6189 * the string CP has been copied for at most the first LEN characters.
6198 dp
= xnew (len
+ 1, char);
6199 strncpy (dp
, cp
, len
);
6205 * Return the ptr in sp at which the character c last
6206 * appears; NULL if not found
6208 * Identical to POSIX strrchr, included for portability.
6211 etags_strrchr (sp
, c
)
6212 register const char *sp
;
6215 register const char *r
;
6227 * Return the ptr in sp at which the character c first
6228 * appears; NULL if not found
6230 * Identical to POSIX strchr, included for portability.
6233 etags_strchr (sp
, c
)
6234 register const char *sp
;
6246 * Compare two strings, ignoring case for alphabetic characters.
6248 * Same as BSD's strcasecmp, included for portability.
6251 etags_strcasecmp (s1
, s2
)
6252 register const char *s1
;
6253 register const char *s2
;
6256 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6257 ? lowcase (*s1
) == lowcase (*s2
)
6261 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6262 ? lowcase (*s1
) - lowcase (*s2
)
6267 * Compare two strings, ignoring case for alphabetic characters.
6268 * Stop after a given number of characters
6270 * Same as BSD's strncasecmp, included for portability.
6273 etags_strncasecmp (s1
, s2
, n
)
6274 register const char *s1
;
6275 register const char *s2
;
6278 while (*s1
!= '\0' && n
-- > 0
6279 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6280 ? lowcase (*s1
) == lowcase (*s2
)
6287 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6288 ? lowcase (*s1
) - lowcase (*s2
)
6292 /* Skip spaces, return new pointer. */
6297 while (iswhite (*cp
))
6302 /* Skip non spaces, return new pointer. */
6304 skip_non_spaces (cp
)
6307 while (*cp
!= '\0' && !iswhite (*cp
))
6312 /* Print error message and exit. */
6330 suggest_asking_for_help ()
6332 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6343 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6346 const char *s1
, *s2
;
6348 fprintf (stderr
, "%s: ", progname
);
6349 fprintf (stderr
, s1
, s2
);
6350 fprintf (stderr
, "\n");
6353 /* Return a newly-allocated string whose contents
6354 concatenate those of s1, s2, s3. */
6359 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6360 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6362 strcpy (result
, s1
);
6363 strcpy (result
+ len1
, s2
);
6364 strcpy (result
+ len1
+ len2
, s3
);
6365 result
[len1
+ len2
+ len3
] = '\0';
6371 /* Does the same work as the system V getcwd, but does not need to
6372 guess the buffer size in advance. */
6378 char *path
= xnew (bufsize
, char);
6380 while (getcwd (path
, bufsize
) == NULL
)
6382 if (errno
!= ERANGE
)
6386 path
= xnew (bufsize
, char);
6389 canonicalize_filename (path
);
6392 #else /* not HAVE_GETCWD */
6395 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6399 for (p
= path
; *p
!= '\0'; p
++)
6405 return strdup (path
);
6406 #else /* not MSDOS */
6410 linebuffer_init (&path
);
6411 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6412 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6417 #endif /* not MSDOS */
6418 #endif /* not HAVE_GETCWD */
6421 /* Return a newly allocated string containing the file name of FILE
6422 relative to the absolute directory DIR (which should end with a slash). */
6424 relative_filename (file
, dir
)
6427 char *fp
, *dp
, *afn
, *res
;
6430 /* Find the common root of file and dir (with a trailing slash). */
6431 afn
= absolute_filename (file
, cwd
);
6434 while (*fp
++ == *dp
++)
6436 fp
--, dp
--; /* back to the first differing char */
6438 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6441 do /* look at the equal chars until '/' */
6445 /* Build a sequence of "../" strings for the resulting relative file name. */
6447 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6449 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6452 strcat (res
, "../");
6454 /* Add the file name relative to the common root of file and dir. */
6455 strcat (res
, fp
+ 1);
6461 /* Return a newly allocated string containing the absolute file name
6462 of FILE given DIR (which should end with a slash). */
6464 absolute_filename (file
, dir
)
6467 char *slashp
, *cp
, *res
;
6469 if (filename_is_absolute (file
))
6470 res
= savestr (file
);
6472 /* We don't support non-absolute file names with a drive
6473 letter, like `d:NAME' (it's too much hassle). */
6474 else if (file
[1] == ':')
6475 fatal ("%s: relative file names with drive letters not supported", file
);
6478 res
= concat (dir
, file
, "");
6480 /* Delete the "/dirname/.." and "/." substrings. */
6481 slashp
= etags_strchr (res
, '/');
6482 while (slashp
!= NULL
&& slashp
[0] != '\0')
6484 if (slashp
[1] == '.')
6486 if (slashp
[2] == '.'
6487 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6492 while (cp
>= res
&& !filename_is_absolute (cp
));
6494 cp
= slashp
; /* the absolute name begins with "/.." */
6496 /* Under MSDOS and NT we get `d:/NAME' as absolute
6497 file name, so the luser could say `d:/../NAME'.
6498 We silently treat this as `d:/NAME'. */
6499 else if (cp
[0] != '/')
6502 strcpy (cp
, slashp
+ 3);
6506 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6508 strcpy (slashp
, slashp
+ 2);
6513 slashp
= etags_strchr (slashp
+ 1, '/');
6517 return savestr ("/");
6522 /* Return a newly allocated string containing the absolute
6523 file name of dir where FILE resides given DIR (which should
6524 end with a slash). */
6526 absolute_dirname (file
, dir
)
6532 canonicalize_filename (file
);
6533 slashp
= etags_strrchr (file
, '/');
6535 return savestr (dir
);
6538 res
= absolute_filename (file
, dir
);
6544 /* Whether the argument string is an absolute file name. The argument
6545 string must have been canonicalized with canonicalize_filename. */
6547 filename_is_absolute (fn
)
6550 return (fn
[0] == '/'
6552 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6557 /* Translate backslashes into slashes. Works in place. */
6559 canonicalize_filename (fn
)
6563 /* Canonicalize drive letter case. */
6564 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6565 fn
[0] = upcase (fn
[0]);
6566 /* Convert backslashes to slashes. */
6567 for (; *fn
!= '\0'; fn
++)
6572 fn
= NULL
; /* shut up the compiler */
6577 /* Initialize a linebuffer for use */
6579 linebuffer_init (lbp
)
6582 lbp
->size
= (DEBUG
) ? 3 : 200;
6583 lbp
->buffer
= xnew (lbp
->size
, char);
6584 lbp
->buffer
[0] = '\0';
6588 /* Set the minimum size of a string contained in a linebuffer. */
6590 linebuffer_setlen (lbp
, toksize
)
6594 while (lbp
->size
<= toksize
)
6597 xrnew (lbp
->buffer
, lbp
->size
, char);
6602 /* Like malloc but get fatal error if memory is exhausted. */
6607 PTR result
= (PTR
) malloc (size
);
6609 fatal ("virtual memory exhausted", (char *)NULL
);
6614 xrealloc (ptr
, size
)
6618 PTR result
= (PTR
) realloc (ptr
, size
);
6620 fatal ("virtual memory exhausted", (char *)NULL
);
6626 * c-indentation-style: gnu
6627 * indent-tabs-mode: t
6630 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")